public VerticalDir DefaultStemDirection(Clef clef) { M.Assert(this.HeadsTopDown.Count > 0); double gap = 32; // dummy value List <double> topDownHeadOriginYs = new List <double>(); int lastMidiPitch = int.MaxValue; foreach (Head head in this.HeadsTopDown) { M.Assert(head.MidiPitch < lastMidiPitch); topDownHeadOriginYs.Add(head.GetOriginY(clef, gap)); } double heightOfMiddleStaffLine = (this.Voice.Staff.NumberOfStafflines / 2) * gap; double halfHeight = 0; if (topDownHeadOriginYs.Count == 1) { halfHeight = topDownHeadOriginYs[0]; } else { halfHeight = (topDownHeadOriginYs[topDownHeadOriginYs.Count - 1] + topDownHeadOriginYs[0]) / 2; } if (halfHeight <= heightOfMiddleStaffLine) { return(VerticalDir.down); } else { return(VerticalDir.up); } }
public SmallClefMetrics(Clef clef, double gap, CSSObjectClass cssClass, ClefID clefID) : base(clef, gap, cssClass, clefID) { _right = 3.5F * gap; // small clefs have proportionally more empty space on the right. if (clef.ClefType[0] == 'b' && clef.ClefType.Length > 1) { //double lowBassBottom = gap * 4.5; _bottom = gap * 4.65; // small bass clef octaves are lower than for normal bass clefs } }
/// <summary> /// Sets Chord.Stem.Direction for each chord. /// BeamBlocks are created, beginning with a chord that has IsBeamStart == true, and ending with a chord that has IsBeamEnd == true. /// BeamBlocks only contain ChordSymbols, but these may be interspersed with other NoteObjects (barlines, clefs, rests, cautionaryChords etc...) /// </summary> public void SetChordStemDirectionsAndCreateBeamBlocks(PageFormat pageFormat) { List <List <OutputChordSymbol> > beamedGroups = GetBeamedGroups(); Clef currentClef = null; List <OutputChordSymbol> beamedGroup = null; int groupIndex = 0; OutputChordSymbol firstChordInVoice = ((OutputChordSymbol)NoteObjects.Find(x => x is OutputChordSymbol)); foreach (var noteObject in NoteObjects) { if (noteObject is OutputChordSymbol chord) { if (chord.BeamBlockDef != null) { M.Assert(currentClef != null); beamedGroup = beamedGroups[groupIndex]; if (chord.IsBeamStart || (chord == firstChordInVoice && (chord.IsBeamRestart || chord.IsBeamEnd))) { groupIndex++; } double beamThickness = pageFormat.BeamThickness; double beamStrokeThickness = pageFormat.StafflineStemStrokeWidthVBPX; chord.BeamBlock = new BeamBlock(currentClef, beamedGroup, this.StemDirection, beamThickness, beamStrokeThickness); } else if (chord.IsBeamEnd) { beamedGroup = null; } else if (beamedGroup == null) { M.Assert(currentClef != null); if (this.StemDirection == VerticalDir.none) { chord.Stem.Direction = chord.DefaultStemDirection(currentClef); } else { chord.Stem.Direction = this.StemDirection; } } } if (noteObject is Clef clef) { currentClef = clef; } } }
public ClefMetrics(Clef clef, double gap, CSSObjectClass cssClefClass, ClefID clefID) : base(cssClefClass) { double trebleTop = -4.35F * gap; double trebleRight = 3.1F * gap; double highTrebleTop = -5.9F * gap; double trebleBottom = 2.7F * gap; #region treble clefs switch (clef.ClefType) { case "t": _top = trebleTop; _right = trebleRight; _bottom = trebleBottom; break; case "t1": // trebleClef8 _top = highTrebleTop; _right = trebleRight; _bottom = trebleBottom; break; case "t2": // trebleClef2x8 _top = highTrebleTop; _right = trebleRight; _bottom = trebleBottom; break; case "t3": // trebleClef3x8 _top = highTrebleTop; _right = trebleRight; _bottom = trebleBottom; break; default: // can be a bass clef ( see below) break; } if (_right > 0F) { Move(0, 3 * gap); } #endregion treble clefs if (!(_right > 0F)) { double bassTop = -gap; double bassRight = trebleRight; double bassBottom = gap * 3; double lowBassBottom = gap * 4.5; #region bass clefs switch (clef.ClefType) { case "b": _top = bassTop; _right = bassRight; _bottom = bassBottom; break; case "b1": // bassClef8 _top = bassTop; _right = bassRight; _bottom = lowBassBottom; break; case "b2": // bassClef2x8 _top = bassTop; _right = bassRight; _bottom = lowBassBottom; break; case "b3": // bassClef3x8 _top = bassTop; _right = bassRight; _bottom = lowBassBottom; break; default: M.Assert(false, "Unknown clef type."); break; } if (_right > 0F) { Move(0, gap); } } #endregion ClefID = clefID; if (!_usedClefIDs.Contains((ClefID)clefID)) { _usedClefIDs.Add((ClefID)clefID); } }
/// <summary> /// Returns the head's y-coordinates wrt the chord. /// The chord's y-origin is the top line of the staff. /// (Y-Alignment of a notehead on the top line of the staff is 0.) /// Uses the following protected variables (in Metrics) which have been set by GetStaffParameters() /// protected double _gapVBPX = 0; /// protected int _nStafflines = 0; /// protected ClefSymbol _clef = null; /// </summary> /// <param name="headIndex"></param> /// <param name="?"></param> /// <param name="?"></param> public double GetOriginY(Clef clef, double gap) { string[] alphabet = { "C", "D", "E", "F", "G", "A", "B" }; double shiftFactor = 0; switch (this.Pitch[0]) { case 'A': shiftFactor = 2.5; break; case 'B': shiftFactor = 2; break; case 'C': shiftFactor = 5; break; case 'D': shiftFactor = 4.5; break; case 'E': shiftFactor = 4; break; case 'F': shiftFactor = 3.5; break; case 'G': shiftFactor = 3; break; } // shiftFactor is currently for the octave above middle C (octave = 5) on a normal treble clef // F6 is at shiftFactor 0 (the top line of the staff). int octave = 0; try { string octaveString = this.Pitch.Substring(this.Pitch.Length - 1); if (octaveString == ":") { octave = 10; } else { octave = int.Parse(octaveString); } } catch { M.Assert(false, "Error in octave string"); } double octaveShift = octave - 4; shiftFactor -= (octaveShift * 3.5F); // 3.5 spaces is one octave // shiftFactor is currently correct for all octaves on a normal treble clef switch (clef.ClefType) { case "t": break; case "t1": // trebleClef8 shiftFactor += 3.5; // shift down one octave break; case "t2": // trebleClef2x8 shiftFactor += 7; // shift down two octaves break; case "t3": // trebleClef3x8 shiftFactor += 10.5; // shift down three octaves break; case "b": shiftFactor -= 6; // shift up six spaces break; case "b1": // bassClef8 shiftFactor -= 9.5; // shift up six spaces + 1 octave break; case "b2": // bassClef2x8 shiftFactor -= 13; // shift up six spaces + 2 octaves break; case "b3": // bassClef3x8 shiftFactor -= 16.5; // shift up six spaces + 3 octaves break; default: break; } double headY = shiftFactor * gap; return(headY); }