private List <float> GetX1sFromChord1(ChordMetrics chord1Metrics, float hairlinePadding) { List <float> x1s = new List <float>(); LedgerlineBlockMetrics upperLedgerlineMetrics = chord1Metrics.UpperLedgerlineBlockMetrics; LedgerlineBlockMetrics lowerLedgerlineMetrics = chord1Metrics.LowerLedgerlineBlockMetrics; List <HeadMetrics> headsMetrics = chord1Metrics.HeadsMetrics; Debug.Assert(headsMetrics.Count > 0); foreach (HeadMetrics headmetrics in headsMetrics) { float x1 = headmetrics.Right; if (upperLedgerlineMetrics != null && headmetrics.OriginY >= upperLedgerlineMetrics.Top && headmetrics.OriginY <= upperLedgerlineMetrics.Bottom) { x1 = upperLedgerlineMetrics.Right; } if (lowerLedgerlineMetrics != null && headmetrics.OriginY >= lowerLedgerlineMetrics.Top && headmetrics.OriginY <= lowerLedgerlineMetrics.Bottom) { x1 = lowerLedgerlineMetrics.Right; } x1s.Add(x1 + hairlinePadding); } return(x1s); }
private List <float> GetX2sFromChord2(List <float> ys, ChordMetrics chord2Metrics, float hairlinePadding) { List <float> x2s = new List <float>(); LedgerlineBlockMetrics c2UpperLedgerlineMetrics = chord2Metrics.UpperLedgerlineBlockMetrics; LedgerlineBlockMetrics c2LowerLedgerlineMetrics = chord2Metrics.LowerLedgerlineBlockMetrics; List <HeadMetrics> c2headsMetrics = chord2Metrics.HeadsMetrics; Debug.Assert(c2headsMetrics.Count > 0); List <AccidentalMetrics> c2AccidentalsMetrics = chord2Metrics.TopDownAccidentalsMetrics; float verticalPadding = hairlinePadding * 4.0f; foreach (float y in ys) { float x2 = float.MaxValue; if (c2UpperLedgerlineMetrics != null) { if (y >= (c2UpperLedgerlineMetrics.Top - verticalPadding) && y <= (c2UpperLedgerlineMetrics.Bottom + verticalPadding)) { x2 = x2 < c2UpperLedgerlineMetrics.Left ? x2 : c2UpperLedgerlineMetrics.Left; } } if (c2LowerLedgerlineMetrics != null) { if (y >= (c2LowerLedgerlineMetrics.Top - verticalPadding) && y <= (c2LowerLedgerlineMetrics.Bottom + verticalPadding)) { x2 = x2 < c2LowerLedgerlineMetrics.Left ? x2 : c2LowerLedgerlineMetrics.Left; } } foreach (HeadMetrics headMetrics in c2headsMetrics) { if (y >= (headMetrics.Top - verticalPadding) && y <= (headMetrics.Bottom + verticalPadding)) { x2 = x2 < headMetrics.Left ? x2 : headMetrics.Left; } } foreach (AccidentalMetrics accidentalMetrics in c2AccidentalsMetrics) { if (y >= (accidentalMetrics.Top - verticalPadding) && y <= (accidentalMetrics.Bottom + verticalPadding)) { x2 = x2 < accidentalMetrics.Left ? x2 : accidentalMetrics.Left; } } x2 = x2 < float.MaxValue ? x2 : chord2Metrics.Left; x2s.Add(x2 - hairlinePadding); } float minX = float.MaxValue; foreach (float x in x2s) { minX = minX < x ? minX : x; } List <float> x2sMinimum = new List <float>(); foreach (float x in x2s) { x2sMinimum.Add(minX); } return(x2sMinimum); }
/// <summary> /// The accidental is at the correct height (accidental.OriginY == head.OriginY), /// but it has not yet been added to this.MetricsList, or used to set this chord's Boundary. /// The accidental is now moved left, such that it does not overlap noteheads, stem, ledgerlines or accidentals. /// It is added to this.MetricsList after this function returns. /// </summary> private void MoveAccidentalLeft(AccidentalMetrics accidentalMetrics, List<HeadMetrics> topDownHeadsMetrics, StemMetrics stemMetrics, LedgerlineBlockMetrics upperLedgerlineBlockMetrics, LedgerlineBlockMetrics lowerLedgerlineBlockMetrics, List<AccidentalMetrics> existingAccidentalsMetrics) { #region move left of ledgerline block if(upperLedgerlineBlockMetrics != null) { MoveAccidentalLeftOfLedgerlineBlock(accidentalMetrics, upperLedgerlineBlockMetrics); } if(lowerLedgerlineBlockMetrics != null) { MoveAccidentalLeftOfLedgerlineBlock(accidentalMetrics, lowerLedgerlineBlockMetrics); } #endregion #region move left of noteheads float topRange = accidentalMetrics.OriginY - (_gap * 1.51F); float bottomRange = accidentalMetrics.OriginY + (_gap * 1.51F); foreach(HeadMetrics head in topDownHeadsMetrics) { if(head.OriginY > topRange && head.OriginY < bottomRange && head.Overlaps(accidentalMetrics)) { float extraHorizontalSpace = 0; if(accidentalMetrics.ID_Type == "b") extraHorizontalSpace = accidentalMetrics.FontHeight * -0.03F; accidentalMetrics.Move(head.Left - extraHorizontalSpace - accidentalMetrics.Right, 0); } } #endregion #region move left of stem (can be in another chord) if(stemMetrics != null) { // Note that the length of the stem is ignored here. float maxRight = stemMetrics.Left - stemMetrics.StrokeWidth; if(maxRight < accidentalMetrics.Right) accidentalMetrics.Move(maxRight - accidentalMetrics.Right, 0F); } #endregion #region move accidental left of existing accidentals MoveLeftOfExistingAccidentals(existingAccidentalsMetrics, 0, accidentalMetrics); #endregion }
private void MoveAccidentalLeftOfLedgerlineBlock(AccidentalMetrics accidentalM, LedgerlineBlockMetrics ledgerlineBlockM) { Debug.Assert(accidentalM != null && ledgerlineBlockM != null); //float top = ledgerlineBlockM.Top - (_gap * 0.51F); //float bottom = ledgerlineBlockM.Bottom + (_gap * 0.51F); float top = ledgerlineBlockM.Top - (_gap * 1.01F); float bottom = ledgerlineBlockM.Bottom + (_gap * 1.01F); if(accidentalM.OriginY > top && accidentalM.OriginY < bottom) accidentalM.Move(ledgerlineBlockM.Left - accidentalM.Right, 0F); }
private LedgerlineBlockMetrics CreateLowerLedgerlineBlock(List<HeadMetrics> topDownHeadsMetrics, float limbLength, float strokeWidth) { Debug.Assert(topDownHeadsMetrics != null); float minLeftX = float.MaxValue; float maxRightX = float.MinValue; foreach(HeadMetrics head in topDownHeadsMetrics) { if(head.OriginY >= _gap * _nStafflines) { minLeftX = minLeftX < head.LeftStemX ? minLeftX : head.LeftStemX; maxRightX = maxRightX > head.RightStemX ? maxRightX : head.RightStemX; } } float leftX = minLeftX - limbLength; float rightX = maxRightX + limbLength; Metrics bottomHeadMetrics = topDownHeadsMetrics[topDownHeadsMetrics.Count - 1]; LedgerlineBlockMetrics lowerLedgerlineBlockMetrics = null; if(bottomHeadMetrics.OriginY > (_gap * 4.75)) { lowerLedgerlineBlockMetrics = new LedgerlineBlockMetrics(leftX, rightX, strokeWidth); // contains no ledgerlines float bottomLedgerlineY = bottomHeadMetrics.OriginY; if((bottomLedgerlineY % _gap) > 0) { bottomLedgerlineY -= (_gap / 2F); } for(float y = (_gap * _nStafflines); y <= bottomLedgerlineY; y += _gap) { lowerLedgerlineBlockMetrics.AddLedgerline(y, _gap); } } return lowerLedgerlineBlockMetrics; }
private LedgerlineBlockMetrics CreateUpperLedgerlineBlock(List<HeadMetrics> topDownHeadsMetrics, float limbLength, float strokeWidth) { Debug.Assert(topDownHeadsMetrics != null); #region upper ledgerline block float minLeftX = float.MaxValue; float maxRightX = float.MinValue; foreach(HeadMetrics head in topDownHeadsMetrics) { if(head.OriginY <= _gap * 0.75F) { minLeftX = minLeftX < head.LeftStemX ? minLeftX : head.LeftStemX; maxRightX = maxRightX > head.RightStemX ? maxRightX : head.RightStemX; } } float left = minLeftX - limbLength; float right = maxRightX + limbLength; Metrics topHeadMetrics = topDownHeadsMetrics[0]; LedgerlineBlockMetrics upperLedgerlineBlockMetrics = null; if(topHeadMetrics.OriginY < -(_gap * 0.75F)) { upperLedgerlineBlockMetrics = new LedgerlineBlockMetrics(left, right, strokeWidth); // contains no ledgerlines float topLedgerlineY = topHeadMetrics.OriginY; if((topLedgerlineY % _gap) < 0) { topLedgerlineY += (_gap / 2F); } for(float y = topLedgerlineY; y < 0; y += _gap) { upperLedgerlineBlockMetrics.AddLedgerline(y, _gap); } } #endregion upper ledgerline block return upperLedgerlineBlockMetrics; }
private void CreateLedgerlineAndAccidentalMetrics(float fontHeight, List<Head> topDownHeads, List<HeadMetrics> topDownHeadsMetrics, float ledgerlineStemStrokeWidth) { float limbLength = (topDownHeadsMetrics[0].RightStemX - topDownHeadsMetrics[0].LeftStemX) / 2F; // change to taste later _upperLedgerlineBlockMetrics = CreateUpperLedgerlineBlock(topDownHeadsMetrics, limbLength, ledgerlineStemStrokeWidth); _lowerLedgerlineBlockMetrics = CreateLowerLedgerlineBlock(topDownHeadsMetrics, limbLength, ledgerlineStemStrokeWidth); List<AccidentalMetrics> existingAccidentalsMetrics = new List<AccidentalMetrics>(); for(int i = 0; i < topDownHeads.Count; i++) { HeadMetrics headMetrics = topDownHeadsMetrics[i]; Head head = topDownHeads[i]; if(head.DisplayAccidental == DisplayAccidental.force) { AccidentalMetrics accidentalMetrics = new AccidentalMetrics(head, fontHeight, _gap); accidentalMetrics.Move(headMetrics.OriginX, headMetrics.OriginY); MoveAccidentalLeft(accidentalMetrics, topDownHeadsMetrics, _stemMetrics, _upperLedgerlineBlockMetrics, _lowerLedgerlineBlockMetrics, existingAccidentalsMetrics); existingAccidentalsMetrics.Add(accidentalMetrics); if(_topDownAccidentalsMetrics == null) _topDownAccidentalsMetrics = new List<AccidentalMetrics>(); this._topDownAccidentalsMetrics.Add(accidentalMetrics); } } }
private LedgerlineBlockMetrics CombinedLedgerlineBlockMetrics(LedgerlineBlockMetrics lbm1, LedgerlineBlockMetrics lbm2, float staffLineStemStrokeWidth) { LedgerlineBlockMetrics ledgerlineBlockMetrics = null; float top = float.MaxValue; float right = float.MaxValue; float bottom = float.MaxValue; float left = float.MaxValue; if(lbm1 != null && lbm2 != null) { top = lbm1.Top < lbm2.Top ? lbm1.Top : lbm2.Top; right = lbm1.Right > lbm2.Right ? lbm1.Right : lbm2.Right; bottom = lbm1.Bottom > lbm2.Bottom ? lbm1.Bottom : lbm2.Bottom; left = lbm1.Left < lbm2.Left ? lbm1.Left : lbm2.Left; } else if(lbm1 != null) { top = lbm1.Top; right = lbm1.Right; bottom = lbm1.Bottom; left = lbm1.Left; } else if(lbm2 != null) { top = lbm2.Top; right = lbm2.Right; bottom = lbm2.Bottom; left = lbm2.Left; } if(top != float.MaxValue) { ledgerlineBlockMetrics = new LedgerlineBlockMetrics(left, right, staffLineStemStrokeWidth); ledgerlineBlockMetrics.SetTop(top); ledgerlineBlockMetrics.SetBottom(bottom); } return ledgerlineBlockMetrics; }
public RestMetrics(Graphics graphics, RestSymbol rest, float gap, int numberOfStafflines, float ledgerlineStrokeWidth) : base(rest.DurationClass, true, rest.FontHeight) { float dy = 0; if(numberOfStafflines > 1) dy = gap * (numberOfStafflines / 2); _top = _top + dy; _bottom += dy; _originY += dy; // the staffline on which the rest is aligned _ledgerlineStub = gap * 0.75F; Move((Left - Right) / 2F, 0F); // centre the glyph horizontally switch(rest.DurationClass) { case DurationClass.breve: case DurationClass.semibreve: Move(gap * -0.25F, 0F); if(numberOfStafflines == 1) Move(0F, gap); _ledgerline = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub, ledgerlineStrokeWidth); _ledgerline.AddLedgerline(_originY - gap, 0F); _ledgerline.Move(gap * 0.17F, 0F); _top -= (gap * 1.5F); break; case DurationClass.minim: Move(gap * 0.18F, 0); _ledgerline = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub - (gap * 0.3F), ledgerlineStrokeWidth); _ledgerline.AddLedgerline(_originY, 0F); _bottom += (gap * 1.5F); break; case DurationClass.quaver: _top -= gap * 0.5F; _bottom += gap * 0.5F; break; case DurationClass.semiquaver: _top -= gap * 0.5F; _bottom += gap * 0.5F; break; case DurationClass.threeFlags: _top -= gap * 0.5F; _right += gap * 0.2F; _bottom += gap * 0.5F; _left -= gap * 0.2F; break; case DurationClass.fourFlags: _top -= gap * 0.5F; _right += gap * 0.1F; _bottom += gap * 1.25F; _left -= gap * 0.1F; _originY += gap; break; case DurationClass.fiveFlags: _top -= gap * 1.5F; _right += gap * 0.2F; _bottom += gap * 1.25F; _left -= gap * 0.2F; _originY += gap; break; } }
public RestMetrics(Graphics graphics, RestSymbol rest, float gap, int numberOfStafflines, float ledgerlineStrokeWidth) : base(rest.DurationClass, true, rest.FontHeight) { float dy = 0; if (numberOfStafflines > 1) { dy = gap * (numberOfStafflines / 2); } _top = _top + dy; _bottom += dy; _originY += dy; // the staffline on which the rest is aligned _ledgerlineStub = gap * 0.75F; Move((Left - Right) / 2F, 0F); // centre the glyph horizontally switch (rest.DurationClass) { case DurationClass.breve: case DurationClass.semibreve: Move(gap * -0.25F, 0F); if (numberOfStafflines == 1) { Move(0F, gap); } _ledgerline = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub, ledgerlineStrokeWidth); _ledgerline.AddLedgerline(_originY - gap, 0F); _ledgerline.Move(gap * 0.17F, 0F); _top -= (gap * 1.5F); break; case DurationClass.minim: Move(gap * 0.18F, 0); _ledgerline = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub - (gap * 0.3F), ledgerlineStrokeWidth); _ledgerline.AddLedgerline(_originY, 0F); _bottom += (gap * 1.5F); break; case DurationClass.quaver: _top -= gap * 0.5F; _bottom += gap * 0.5F; break; case DurationClass.semiquaver: _top -= gap * 0.5F; _bottom += gap * 0.5F; break; case DurationClass.threeFlags: _top -= gap * 0.5F; _right += gap * 0.2F; _bottom += gap * 0.5F; _left -= gap * 0.2F; break; case DurationClass.fourFlags: _top -= gap * 0.5F; _right += gap * 0.1F; _bottom += gap * 1.25F; _left -= gap * 0.1F; _originY += gap; break; case DurationClass.fiveFlags: _top -= gap * 1.5F; _right += gap * 0.2F; _bottom += gap * 1.25F; _left -= gap * 0.2F; _originY += gap; break; } }
public RestMetrics(Graphics graphics, RestSymbol rest, double gap, int numberOfStafflines, double ledgerlineStrokeWidth) : base(rest.DurationClass, rest.FontHeight, CSSObjectClass.rest) { double dy = 0; if (numberOfStafflines > 1) { dy = gap * (numberOfStafflines / 2); } _top = _top + dy; _bottom += dy; _originY += dy; // the staffline on which the rest is aligned _ledgerlineStub = gap * 0.75; Move((Left - Right) / 2, 0F); // centre the glyph horizontally CSSObjectClass llBlockClass = CSSObjectClass.ledgerlines; switch (rest.DurationClass) { case DurationClass.breve: case DurationClass.semibreve: Move(gap * -0.25, 0F); if (numberOfStafflines == 1) { Move(0, gap); } _ledgerlineBlockMetrics = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub, ledgerlineStrokeWidth, llBlockClass); _ledgerlineBlockMetrics.AddLedgerline(_originY - gap, 0F); _ledgerlineBlockMetrics.Move(gap * 0.17, 0F); _top -= (gap * 1.5F); break; case DurationClass.minim: Move(gap * 0.18, 0); _ledgerlineBlockMetrics = new LedgerlineBlockMetrics(Left - _ledgerlineStub, Right + _ledgerlineStub - (gap * 0.3F), ledgerlineStrokeWidth, llBlockClass); _ledgerlineBlockMetrics.AddLedgerline(_originY, 0F); _bottom += (gap * 1.5F); break; case DurationClass.quaver: _top -= gap * 0.5; _bottom += gap * 0.5; break; case DurationClass.semiquaver: _top -= gap * 0.5; _bottom += gap * 0.5; break; case DurationClass.threeFlags: _top -= gap * 0.5; _right += gap * 0.2; _bottom += gap * 0.5; _left -= gap * 0.2; break; case DurationClass.fourFlags: _top -= gap * 0.5; _right += gap * 0.1; _bottom += gap * 1.25; _left -= gap * 0.1; _originY += gap; break; case DurationClass.fiveFlags: _top -= gap * 1.5; _right += gap * 0.2; _bottom += gap * 1.25; _left -= gap * 0.2; _originY += gap; break; } }