public ChordMetrics(System.Drawing.Graphics graphics, ChordSymbol chord, VerticalDir voiceStemDirection, float gap, float stemStrokeWidthVBPX) : base() { _top = float.MaxValue; _right = float.MinValue; _bottom = float.MinValue; _left = float.MaxValue; _drawObjects = chord.DrawObjects; _gap = gap; // The _objectType is written to the SVG file as a group name, but is otherwise not used. if(chord is CautionaryChordSymbol) _objectType = "cautionary chord"; else _objectType = "chord"; GetStaffParameters(chord); // sets _clef to the most recent clef, and _nStafflines. // For each component, find its characterID, deltaX and deltaY re the chord's origin. // The chord's x-origin is the centre of the outermost notehead. // (deltaX of the outermost notehead is 0.) // The chord's y-origin is the top line of the staff. // (deltaY of a notehead on the top line of the staff is 0.) if(chord.BeamBlock != null && chord.BeamBlock.Chords[0] == chord) this.BeamBlock = chord.BeamBlock; SetHeadsMetrics(chord, stemStrokeWidthVBPX); if(chord.Stem.Draw) // false for cautionary chords SetStemAndFlags(chord, _headsMetricsTopDown, stemStrokeWidthVBPX); // if the chord is part of a beamGroup, the stem tips are all at one height here. // These objects are created with originX and originY at 0,0 (the chord's origin). CreateLedgerlineAndAccidentalMetrics(chord.FontHeight, chord.HeadsTopDown, _headsMetricsTopDown, stemStrokeWidthVBPX); CautionaryChordSymbol cautionaryChordSymbol = chord as CautionaryChordSymbol; if(cautionaryChordSymbol != null) { CreateCautionaryBracketsMetrics(cautionaryChordSymbol); } else { bool dynamicIsBelow; bool ornamentIsBelow; _lyricMetrics = NewLyricMetrics(chord.Voice.StemDirection, graphics, gap); GetRelativePositions(chord.Voice.StemDirection, _lyricMetrics, out ornamentIsBelow, out dynamicIsBelow); _ornamentMetrics = NewOrnamentMetrics(graphics, gap, ornamentIsBelow); _dynamicMetrics = NewDynamicMetrics(gap, dynamicIsBelow); MoveAuxilliaries(chord.Stem.Direction, gap); } SetExternalBoundary(); }
/// <summary> /// returns null if there is no lyric in the _drawObjects /// </summary> /// <param name="graphics"></param> /// <param name="gap"></param> /// <param name="lyricIsBelow"></param> /// <returns></returns> private LyricMetrics NewLyricMetrics(VerticalDir voiceStemDirection, Graphics graphics, float gap) { LyricText lyric = null; foreach(DrawObject drawObject in _drawObjects) { lyric = drawObject as LyricText; if(lyric != null) break; } _lyricMetrics = null; if(lyric != null) { bool lyricIsBelow = true; // voiceStemDirection == VerticalDir.none || voiceStemDirection == VerticalDir.down if(voiceStemDirection == VerticalDir.up) lyricIsBelow = false; lyric.Metrics = new LyricMetrics(gap, graphics, lyric.TextInfo, lyricIsBelow); _lyricMetrics = (LyricMetrics)lyric.Metrics; } return _lyricMetrics; }
private void GetRelativePositions(VerticalDir voiceStemDirection, LyricMetrics lyricMetrics, out bool ornamentIsBelow, out bool dynamicIsBelow) { dynamicIsBelow = true; ornamentIsBelow = false; switch(voiceStemDirection) { case VerticalDir.none: // a 1-Voice staff if(lyricMetrics != null && lyricMetrics.IsBelow) dynamicIsBelow = false; break; case VerticalDir.up: // top voice of a 2-Voice staff dynamicIsBelow = false; ornamentIsBelow = false; break; case VerticalDir.down: // bottom voice of a 2-Voice staff dynamicIsBelow = true; ornamentIsBelow = true; break; } }