/// <summary> /// Adds the staff name to the first barline of each visible staff in the score. /// </summary> private void SetStaffNames() { foreach (SvgSystem system in Systems) { for (int staffIndex = 0; staffIndex < system.Staves.Count; staffIndex++) { Staff staff = system.Staves[staffIndex]; if (!(staff is InvisibleOutputStaff)) { foreach (NoteObject noteObject in staff.Voices[0].NoteObjects) { Barline firstBarline = noteObject as Barline; if (firstBarline != null) { float fontHeight = _pageFormat.StaffNameFontHeight; if (staff is InputStaff) { fontHeight *= _pageFormat.InputStavesSizeFactor; } StaffNameText staffNameText = new StaffNameText(firstBarline, staff.Staffname, fontHeight); firstBarline.DrawObjects.Add(staffNameText); break; } } } } } }
private float GetLeftMarginPos(SvgSystem system, Graphics graphics, PageFormat pageFormat) { float leftMarginPos = pageFormat.LeftMarginPos; float maxNameWidth = 0; foreach (Staff staff in system.Staves) { foreach (NoteObject noteObject in staff.Voices[0].NoteObjects) { Barline firstBarline = noteObject as Barline; if (firstBarline != null) { foreach (DrawObject drawObject in firstBarline.DrawObjects) { StaffNameText staffName = drawObject as StaffNameText; if (staffName != null) { Debug.Assert(staffName.TextInfo != null); TextMetrics staffNameMetrics = new TextMetrics(graphics, null, staffName.TextInfo); float nameWidth = staffNameMetrics.Right - staffNameMetrics.Left; maxNameWidth = (maxNameWidth > nameWidth) ? maxNameWidth : nameWidth; } } break; } } } leftMarginPos = maxNameWidth + (pageFormat.Gap * 2.0F); leftMarginPos = (leftMarginPos > pageFormat.LeftMarginPos) ? leftMarginPos : pageFormat.LeftMarginPos; return(leftMarginPos); }
/// <summary> /// There is currently one bar per System. /// All Duration Symbols have been constructed in voice.NoteObjects. /// There are no barlines in the score yet. /// Add a barline to each Voice in the staff, adding a double bar to the final system /// </summary> /// <param name="barlineType"></param> /// <param name="systemNumbers"></param> private void SetBarlines() { for (int systemIndex = 0; systemIndex < Systems.Count; ++systemIndex) { foreach (Staff staff in Systems[systemIndex].Staves) { if (!(staff is InvisibleOutputStaff)) { foreach (Voice voice in staff.Voices) { Debug.Assert(voice.NoteObjects.Count > 0 && !(voice.NoteObjects[voice.NoteObjects.Count - 1] is Barline)); Barline barline = new Barline(voice); if (systemIndex == Systems.Count - 1) { barline.BarlineType = BarlineType.end; } else { barline.BarlineType = BarlineType.single; } voice.NoteObjects.Add(barline); } } } } }
/// <summary> /// Adds a bar number to the first Barline in the top visible voice of each system except the first. /// </summary> private void AddBarNumbers() { int barNumber = 1; foreach (SvgSystem system in Systems) { Voice topVisibleVoice = system.TopVisibleVoice(); bool isFirstBarline = true; for (int i = 0; i < topVisibleVoice.NoteObjects.Count - 1; i++) { Barline barline = topVisibleVoice.NoteObjects[i] as Barline; if (barline != null) { if (isFirstBarline && system != Systems[0]) { FramedBarNumberText framedBarNumber = new FramedBarNumberText(this, barNumber.ToString(), _pageFormat.Gap, _pageFormat.StafflineStemStrokeWidth); barline.DrawObjects.Add(framedBarNumber); isFirstBarline = false; } barNumber++; } } } }
/// <summary> /// Aligns barline glyphs in this moment, moving an immediately preceding clef, but /// without moving the following duration symbol (which is aligned at this.AlignmentX). /// </summary> public void AlignBarlineGlyphs() { float minBarlineOriginX = float.MaxValue; foreach (NoteObject noteObject in _noteObjects) { Barline b = noteObject as Barline; if (b != null && b.Metrics != null && b.Metrics.OriginX < minBarlineOriginX) { minBarlineOriginX = b.Metrics.OriginX; } } for (int index = 0; index < _noteObjects.Count; index++) { Barline barline = _noteObjects[index] as Barline; if (barline != null && barline.Metrics != null) { Debug.Assert(AlignmentX == 0F); if (index > 0) { ClefSymbol clef = _noteObjects[index - 1] as ClefSymbol; if (clef != null) { clef.Metrics.Move(minBarlineOriginX - barline.Metrics.OriginX, 0); } } barline.Metrics.Move(minBarlineOriginX - barline.Metrics.OriginX, 0); } } }
/// <summary> /// Writes out an SVG Voice /// </summary> /// <param name="w"></param> public virtual void WriteSVG(SvgWriter w, bool staffIsVisible) { for (int i = 0; i < NoteObjects.Count; ++i) { NoteObject noteObject = NoteObjects[i]; Barline barline = noteObject as Barline; if (staffIsVisible && barline != null) { bool isLastNoteObject = (i == (NoteObjects.Count - 1)); float top = Staff.Metrics.StafflinesTop; float bottom = Staff.Metrics.StafflinesBottom; PageFormat pageFormat = Staff.SVGSystem.Score.PageFormat; float barlineStrokeWidth = pageFormat.BarlineStrokeWidth; float stafflineStrokeWidth = pageFormat.StafflineStemStrokeWidth; barline.WriteSVG(w, top, bottom, barlineStrokeWidth, stafflineStrokeWidth, isLastNoteObject, false); } ChordSymbol chordSymbol = noteObject as ChordSymbol; if (chordSymbol != null) { chordSymbol.WriteSVG(w, staffIsVisible); } else { // if this is the first barline, the staff name and (maybe) barnumber will be written. noteObject.WriteSVG(w, staffIsVisible); } } }
/// <summary> /// The score contains the correct number of bars per system. /// Now, if a barline comes before any chords in a staff, it is moved to the end of the corresponding /// staff in the previous system -- or deleted altogether if it is in the first System. /// </summary> private void MoveInitialBarlinesToPreviousSystem() { for (int systemIndex = 0; systemIndex < Systems.Count; systemIndex++) { SvgSystem system = Systems[systemIndex]; for (int staffIndex = 0; staffIndex < system.Staves.Count; staffIndex++) { Staff staff = system.Staves[staffIndex]; for (int voiceIndex = 0; voiceIndex < staff.Voices.Count; voiceIndex++) { Voice voice = staff.Voices[voiceIndex]; Barline barline = voice.InitialBarline; if (barline != null) { if (systemIndex > 0) { Voice voiceInPreviousSystem = Systems[systemIndex - 1].Staves[staffIndex].Voices[voiceIndex]; voiceInPreviousSystem.NoteObjects.Add(new Barline(voiceInPreviousSystem, barline.BarlineType)); } voice.NoteObjects.Remove(barline); } } } } }
/// <summary> /// The system has been justified horizontally, so all objects are at their final horizontal positions. /// The outer tips of stems which are inside BeamBlocks have been set to the beamBlock's DefaultStemTipY value. /// This function /// 1. creates the contained beams, and sets the final coordinates of their corners. /// 2. resets the contained Stem.Metrics (by creating and re-allocating new ones) /// 3. moves objects which are outside the stem tips vertically by the same amount as the stem tips are moved. /// </summary> public void FinalizeBeamBlocks() { HashSet <ChordSymbol> chordSymbolsThatStartBeamBlocks = FindChordSymbolsThatStartBeamBlocks(); Barline rightBarline = NoteObjects[NoteObjects.Count - 1] as Barline; M.Assert(rightBarline != null); double rightBarlineX = rightBarline.Metrics.OriginX; foreach (var chordSymbol in chordSymbolsThatStartBeamBlocks) { chordSymbol.FinalizeBeamBlock(rightBarlineX); } }
/// <summary> /// Returns the first chordSymbol or restSymbol after the first cautionaryChordSymbol. /// If there are cautionaryChordSymbols between the first and the returned chordSymbol or restSymbol, they are rendered invisible. /// If there is a barline immediately preceding the durationSymbol that would otherwise be returned, the barline is returned. /// Null is returned if no further chordSymbol or RestSymbol is found in the noteObjects. /// </summary> /// <param name="noteObjects"></param> /// <returns></returns> private NoteObject GetFollowingChordRestOrBarlineSymbol(List <NoteObject> noteObjects) { NoteObject noteObjectToReturn = null; bool firstCautionaryChordSymbolFound = false; for (int i = 0; i < noteObjects.Count; ++i) { NoteObject noteObject = noteObjects[i]; if (firstCautionaryChordSymbolFound == false && noteObject is CautionaryChordSymbol) { firstCautionaryChordSymbolFound = true; continue; } if (firstCautionaryChordSymbolFound) { CautionaryChordSymbol followingCautionary = noteObject as CautionaryChordSymbol; if (followingCautionary != null) { followingCautionary.Visible = false; continue; } if (noteObject is ChordSymbol) { noteObjectToReturn = noteObject; } if (noteObject is RestSymbol) { noteObjectToReturn = noteObject; } } if (noteObjectToReturn != null) // a ChordSymbol or a RestSymbol (not a CautionaryChordSymbol) { Barline barline = noteObjects[i - 1] as Barline; if (barline != null) { noteObjectToReturn = barline; } break; } } return(noteObjectToReturn); }
public BarlineMetrics(Graphics graphics, Barline barline, float gap) : base() { _objectType = "barline"; if (barline.BarlineType == BarlineType.end) { _left = -gap * 1.7F; } else { _left = -gap * 0.5F; } _originX = 0F; _right = gap / 2F; if (graphics != null && barline != null) { foreach (DrawObject drawObject in barline.DrawObjects) { Text text = drawObject as Text; if (text != null) { Debug.Assert(text.TextInfo != null && (text is StaffNameText || text is FramedBarNumberText)); if (text is StaffNameText) { _staffNameMetrics = new TextMetrics(graphics, null, text.TextInfo); // move the staffname vertically to the middle of this staff Staff staff = barline.Voice.Staff; float staffheight = staff.Gap * (staff.NumberOfStafflines - 1); float dy = (staffheight * 0.5F) + (gap * 0.8F); _staffNameMetrics.Move(0F, dy); } else if (text is FramedBarNumberText) { _barnumberMetrics = new BarnumberMetrics(graphics, null, text.TextInfo, text.FrameInfo); //_barnumberMetrics = new TextMetrics(graphics, null, text.TextInfo); // move the bar number above this barline float deltaY = (gap * 6F); _barnumberMetrics.Move(0F, -deltaY); } } } } }
/// <summary> /// Adds all the staff's metrics, except for the top or bottom staffline. /// </summary> /// <param name="staff"></param> protected void AddStaffMetrics(Staff staff) { foreach (Voice voice in staff.Voices) { foreach (NoteObject noteObject in voice.NoteObjects) { OutputChordSymbol chordSymbol = noteObject as OutputChordSymbol; ClefSymbol clef = noteObject as ClefSymbol; if (chordSymbol != null) { chordSymbol.ChordMetrics.AddToEdge(this); } else if (clef != null && clef.ClefType != "n") { Add(clef.Metrics); } else { Add(noteObject.Metrics); } Barline barline = noteObject as Barline; if (barline != null) { BarlineMetrics barlineMetrics = barline.Metrics as BarlineMetrics; if (barlineMetrics.BarnumberMetrics != null) { Add(barlineMetrics.BarnumberMetrics); } if (barlineMetrics.StaffNameMetrics != null) { Add(barlineMetrics.StaffNameMetrics); } } } } }
public override Metrics NoteObjectMetrics(Graphics graphics, NoteObject noteObject, VerticalDir voiceStemDirection, float gap, float strokeWidth) { Metrics returnMetrics = null; ClefSymbol clef = noteObject as ClefSymbol; Barline barline = noteObject as Barline; CautionaryChordSymbol cautionaryChordSymbol = noteObject as CautionaryChordSymbol; ChordSymbol chord = noteObject as ChordSymbol; RestSymbol rest = noteObject as RestSymbol; if (barline != null) { returnMetrics = new BarlineMetrics(graphics, barline, gap); } else if (clef != null) { if (clef.ClefType != "n") { returnMetrics = new ClefMetrics(clef, gap); } } else if (cautionaryChordSymbol != null) { returnMetrics = new ChordMetrics(graphics, cautionaryChordSymbol, voiceStemDirection, gap, strokeWidth); } else if (chord != null) { returnMetrics = new ChordMetrics(graphics, chord, voiceStemDirection, gap, strokeWidth); } else if (rest != null) { // All rests are originally created on the centre line. // They are moved vertically later, if they are on a 2-Voice staff. returnMetrics = new RestMetrics(graphics, rest, gap, noteObject.Voice.Staff.NumberOfStafflines, strokeWidth); } return(returnMetrics); }
private List <float> GetCautionaryRightExtenderX2s(CautionaryChordSymbol cautionaryChordSymbol1, List <NoteObject> noteObjects, List <float> x1s, List <float> ys, float hairlinePadding) { List <float> x2s = new List <float>(); NoteObject no2 = GetFollowingChordRestOrBarlineSymbol(noteObjects); Barline barline = no2 as Barline; ChordSymbol chord2 = no2 as ChordSymbol; RestSymbol rest2 = no2 as RestSymbol; if (barline != null) { float x2 = barline.Metrics.OriginX; x2s = GetEqualFloats(x2, x1s.Count); } else if (chord2 != null) { x2s = GetX2sFromChord2(ys, chord2.ChordMetrics, hairlinePadding); } else if (rest2 != null) { float x2 = rest2.Metrics.Left - hairlinePadding; x2s = GetEqualFloats(x2, x1s.Count); } else // no2 == null { Debug.Assert(no2 == null); // This voice has no further chords or rests, // so draw extenders to the right margin. // extend to the right margin PageFormat pageFormat = cautionaryChordSymbol1.Voice.Staff.SVGSystem.Score.PageFormat; float rightMarginPos = pageFormat.RightMarginPos; float gap = pageFormat.Gap; x2s = GetEqualFloats(rightMarginPos + gap, ys.Count); } return(x2s); }
/// <summary> /// There is currently one bar per System. /// All Duration Symbols have been constructed in voice.NoteObjects. /// There are no barlines in the score yet. /// Add a barline to each Voice in the staff, adding a double bar to the final system /// </summary> /// <param name="barlineType"></param> /// <param name="systemNumbers"></param> private void SetBarlines() { for(int systemIndex = 0; systemIndex < Systems.Count; ++systemIndex) { foreach(Staff staff in Systems[systemIndex].Staves) { if(!(staff is HiddenOutputStaff)) { foreach(Voice voice in staff.Voices) { Debug.Assert(voice.NoteObjects.Count > 0 && !(voice.NoteObjects[voice.NoteObjects.Count - 1] is Barline)); Barline barline = new Barline(voice); if(systemIndex == Systems.Count - 1) barline.BarlineType = BarlineType.end; else barline.BarlineType = BarlineType.single; voice.NoteObjects.Add(barline); } } } } }
/// <summary> /// Sets Chord.Stem.Direction for each chord. /// Chords are beamed together, duration classes permitting, unless a rest or clef intervenes. /// If a barline intervenes, and beamsCrossBarlines is true, the chords are beamed together. /// If a barline intervenes, and beamsCrossBarlines is false, the beam is broken. /// </summary> public void SetChordStemDirectionsAndCreateBeamBlocks(PageFormat pageFormat) { List <ChordSymbol> chordsBeamedTogether = new List <ChordSymbol>(); ClefSymbol currentClef = null; bool breakGroup = false; ChordSymbol lastChord = null; foreach (ChordSymbol cs in ChordSymbols) { lastChord = cs; } foreach (NoteObject noteObject in NoteObjects) { CautionaryChordSymbol cautionaryChord = noteObject as CautionaryChordSymbol; ChordSymbol chord = noteObject as ChordSymbol; RestSymbol rest = noteObject as RestSymbol; ClefSymbol clef = noteObject as ClefSymbol; Barline barline = noteObject as Barline; if (cautionaryChord != null) { continue; } if (chord != null) { if (chord.DurationClass == DurationClass.cautionary || chord.DurationClass == DurationClass.breve || chord.DurationClass == DurationClass.semibreve || chord.DurationClass == DurationClass.minim || chord.DurationClass == DurationClass.crotchet) { if (currentClef != null) { if (this.StemDirection == VerticalDir.none) { chord.Stem.Direction = chord.DefaultStemDirection(currentClef); } else { chord.Stem.Direction = this.StemDirection; } } breakGroup = true; } else { chordsBeamedTogether.Add(chord); if (chord.Stem.BeamContinues) // this is true by default { breakGroup = false; } else { breakGroup = true; } } } if (chordsBeamedTogether.Count > 0) { if (rest != null) { if (rest.LocalCautionaryChordDef == null) { breakGroup = true; } } if (clef != null) { breakGroup = true; } if (barline != null && !pageFormat.BeamsCrossBarlines) { breakGroup = true; } if (chord == lastChord) { breakGroup = true; } } if (chordsBeamedTogether.Count > 0 && breakGroup) { if (currentClef != null) { if (chordsBeamedTogether.Count == 1) { if (this.StemDirection == VerticalDir.none) { chordsBeamedTogether[0].Stem.Direction = chordsBeamedTogether[0].DefaultStemDirection(currentClef); } else { chordsBeamedTogether[0].Stem.Direction = this.StemDirection; } } else if (chordsBeamedTogether.Count > 1) { float beamThickness = pageFormat.BeamThickness; float beamStrokeThickness = pageFormat.StafflineStemStrokeWidth; if (this is InputVoice) { beamThickness *= pageFormat.InputStavesSizeFactor; beamStrokeThickness *= pageFormat.InputStavesSizeFactor; } chordsBeamedTogether[0].BeamBlock = new BeamBlock(currentClef, chordsBeamedTogether, this.StemDirection, beamThickness, beamStrokeThickness); } } chordsBeamedTogether.Clear(); } if (clef != null) { currentClef = clef; } } }
public BarlineMetrics(Graphics graphics, Barline barline, float gap) : base() { _objectType = "barline"; if(barline.BarlineType == BarlineType.end) _left = -gap * 1.7F; else _left = -gap * 0.5F; _originX = 0F; _right = gap / 2F; if(graphics != null && barline != null) { foreach(DrawObject drawObject in barline.DrawObjects) { Text text = drawObject as Text; if(text != null) { Debug.Assert(text.TextInfo != null && (text is StaffNameText || text is FramedBarNumberText)); if(text is StaffNameText) { _staffNameMetrics = new TextMetrics(graphics, null, text.TextInfo); // move the staffname vertically to the middle of this staff Staff staff = barline.Voice.Staff; float staffheight = staff.Gap * (staff.NumberOfStafflines - 1); float dy = (staffheight * 0.5F) + (gap * 0.8F); _staffNameMetrics.Move(0F, dy); } else if(text is FramedBarNumberText) { _barnumberMetrics = new BarnumberMetrics(graphics, null, text.TextInfo, text.FrameInfo); //_barnumberMetrics = new TextMetrics(graphics, null, text.TextInfo); // move the bar number above this barline float deltaY = (gap * 6F); _barnumberMetrics.Move(0F, -deltaY); } } } } }
private void AddExtendersInStaves(List <Staff> staves, float extenderStrokeWidth, float gap, float hairlinePadding) { foreach (Staff staff in staves) { if (!(staff is InvisibleOutputStaff)) { foreach (Voice voice in staff.Voices) { List <NoteObject> noteObjects = voice.NoteObjects; int index = 0; while (index < noteObjects.Count - 1) { // noteObjects.Count - 1 because index is immediately incremented when a continuing // chord or rest is found, and it should always be less than noteObjects.Count. ChordSymbol chord1 = noteObjects[index] as ChordSymbol; if (chord1 != null) { List <float> x1s = GetX1sFromChord1(chord1.ChordMetrics, hairlinePadding); List <float> x2s = null; List <float> ys = null; ++index; if (chord1.MsDurationToNextBarline != null) { while (index < noteObjects.Count) { CautionaryChordSymbol cautionaryChordSymbol = noteObjects[index] as CautionaryChordSymbol; ChordSymbol chord2 = noteObjects[index] as ChordSymbol; RestSymbol rest2 = noteObjects[index] as RestSymbol; if (cautionaryChordSymbol != null) { cautionaryChordSymbol.Visible = false; } else if (chord2 != null) { ys = chord1.ChordMetrics.HeadsOriginYs; x2s = GetX2sFromChord2(ys, chord2.ChordMetrics, hairlinePadding); break; } else if (rest2 != null) { float x2 = rest2.Metrics.Left - hairlinePadding; ys = chord1.ChordMetrics.HeadsOriginYs; x2s = GetEqualFloats(x2, x1s.Count); break; } ++index; } if (x2s != null && ys != null) { bool hasContinuingBeamBlock = ((chord1.BeamBlock != null) && (chord1.BeamBlock.Chords[chord1.BeamBlock.Chords.Count - 1] != chord1)); if (hasContinuingBeamBlock) { Debug.Assert(true); } Barline barline = noteObjects[index - 1] as Barline; if (barline != null) { float x2 = barline.Metrics.OriginX; x2s = GetEqualFloats(x2, x1s.Count); } bool drawExtender = false; if (chord1.DurationClass > DurationClass.semiquaver) { drawExtender = true; } if (chord1.DurationClass < DurationClass.crotchet && hasContinuingBeamBlock) { drawExtender = false; } chord1.ChordMetrics.NoteheadExtendersMetrics = CreateExtenders(x1s, x2s, ys, extenderStrokeWidth, gap, drawExtender); } } } else { ++index; } } } } } }