/// <summary> /// Recursive function. /// </summary> private void MoveLeftOfExistingAccidentals(List<AccidentalMetrics> existingAccidentals, int index, AccidentalMetrics accidental) { // This delta is very important. Without it, an accidental will collide with the accidental above it, // if the upper accidental has been moved left. For example, chord (D1,G1,D2) with an accidental on each notehead. float xDelta = accidental.FontHeight * 0.001F; for(int i = index; i < existingAccidentals.Count; i++) { Metrics existingAccidental = existingAccidentals[i]; if(existingAccidental.Overlaps(accidental)) { if(existingAccidental.OriginY < (accidental.OriginY - (_gap * 1.75))) { if(accidental.ID_Type == "n") xDelta = accidental.FontHeight * -0.05F; else if(accidental.ID_Type == "b") xDelta = accidental.FontHeight * -0.14F; //else if(accidental.ID_Type == "#") // xDelta = accidental.FontHeight * 0.03F; } accidental.Move(existingAccidental.Left - xDelta - accidental.Right, 0); } if(i < (existingAccidentals.Count - 1)) MoveLeftOfExistingAccidentals(existingAccidentals, i + 1, accidental); } }
/// <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 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); } } }