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); }
private void CreateEmptyInputStaves(List <List <VoiceDef> > barDefsInOneSystem) { int nPrintedOutputStaves = _pageFormat.VisibleOutputVoiceIndicesPerStaff.Count; int nPrintedInputStaves = _pageFormat.VisibleInputVoiceIndicesPerStaff.Count; int nStaffNames = _pageFormat.ShortStaffNames.Count; for (int i = 0; i < Systems.Count; i++) { SvgSystem system = Systems[i]; List <VoiceDef> barDef = barDefsInOneSystem[i]; for (int staffIndex = 0; staffIndex < nPrintedInputStaves; staffIndex++) { int staffNameIndex = nPrintedOutputStaves + staffIndex; string staffname = StaffName(i, staffNameIndex); float gap = _pageFormat.Gap * _pageFormat.InputStavesSizeFactor; float stafflineStemStrokeWidth = _pageFormat.StafflineStemStrokeWidth * _pageFormat.InputStavesSizeFactor; InputStaff inputStaff = new InputStaff(system, staffname, _pageFormat.StafflinesPerStaff[staffIndex], gap, stafflineStemStrokeWidth); List <byte> inputVoiceIndices = _pageFormat.VisibleInputVoiceIndicesPerStaff[staffIndex]; for (int ivIndex = 0; ivIndex < inputVoiceIndices.Count; ++ivIndex) { InputVoiceDef inputVoiceDef = barDef[inputVoiceIndices[ivIndex] + _algorithm.MidiChannelIndexPerOutputVoice.Count] as InputVoiceDef; Debug.Assert(inputVoiceDef != null); InputVoice inputVoice = new InputVoice(inputStaff); inputVoice.VoiceDef = inputVoiceDef; inputStaff.Voices.Add(inputVoice); } SetStemDirections(inputStaff); system.Staves.Add(inputStaff); } } }
/// <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); } } } } }
public Staff(SvgSystem svgSystem, string staffName, int numberOfStafflines, float gap, float stafflineStemStrokeWidth) { SVGSystem = svgSystem; Staffname = staffName; Debug.Assert(numberOfStafflines > 0); NumberOfStafflines = numberOfStafflines; Gap = gap; StafflineStemStrokeWidth = stafflineStemStrokeWidth; }
/// <summary> /// Creates one System per bar (=list of VoiceDefs) in the argument. /// The Systems are complete with staves and voices of the correct type: /// Each InputStaff is allocated parallel (empty) InputVoice fields. /// Each OutputStaff is allocated parallel (empty) OutputVoice fields. /// Each Voice has a VoiceDef field that is allocated to the corresponding /// VoiceDef from the argument. /// The OutputVoices are arranged according to _pageFormat.OutputVoiceIndicesPerStaff. /// The InputVoices are arranged according to _pageFormat.InputVoiceIndicesPerStaff. /// OutputVoices are given a midi channel allocated from top to bottom in the printed score. /// </summary> public void CreateEmptySystems(List <List <VoiceDef> > barDefsInOneSystem, int numberOfVisibleInputStaves) { foreach (List <VoiceDef> barVoiceDefs in barDefsInOneSystem) { SvgSystem system = new SvgSystem(this); this.Systems.Add(system); } CreateEmptyOutputStaves(barDefsInOneSystem, numberOfVisibleInputStaves); CreateEmptyInputStaves(barDefsInOneSystem); }
/// <summary> /// There is still one system per bar. /// Each VoiceDef begins with an MNXCommon.Clef (taking small clefs into account). /// An Exception will be thrown if a SmallClefDef is found on the lower voiceDef in a staff in the systems input. /// Small clefs (if there are any) are copied from the top to the bottom voice (if there is one) on each staff. /// Small clefs on lower voices on a staff have IsVisible set to false. /// </summary> /// <param name="systems"></param> public void ConvertVoiceDefsToNoteObjects(List <SvgSystem> systems) { byte[] currentChannelVelocities = new byte[systems[0].Staves.Count]; var topVoiceSmallClefs = new List <SmallClef>(); int systemAbsMsPos = 0; for (int systemIndex = 0; systemIndex < systems.Count; ++systemIndex) { SvgSystem system = systems[systemIndex]; system.AbsStartMsPosition = systemAbsMsPos; int msPositionReVoiceDef = 0; for (int staffIndex = 0; staffIndex < system.Staves.Count; ++staffIndex) { Staff staff = system.Staves[staffIndex]; msPositionReVoiceDef = 0; topVoiceSmallClefs.Clear(); for (int voiceIndex = 0; voiceIndex < staff.Voices.Count; ++voiceIndex) { Voice voice = staff.Voices[voiceIndex]; voice.VoiceDef.AgglomerateRests(); msPositionReVoiceDef = 0; List <IUniqueDef> iuds = voice.VoiceDef.UniqueDefs; M.Assert(iuds[0] is ClefDef || iuds[0] is MNX.Common.Clef); /** <-------------- **/ for (int iudIndex = 0; iudIndex < iuds.Count; ++iudIndex) { IUniqueDef iud = voice.VoiceDef.UniqueDefs[iudIndex]; int absMsPosition = systemAbsMsPos + msPositionReVoiceDef; NoteObject noteObject = SymbolSet.GetNoteObject(voice, absMsPosition, iud, iudIndex, ref currentChannelVelocities[staffIndex]); if (noteObject is SmallClef smallClef) { if (voiceIndex == 0) { if (staff.Voices.Count > 1) { topVoiceSmallClefs.Add(smallClef); } } else { throw new Exception("SmallClefs may not be defined for a lower voice. They will be copied from the top voice"); } } if (iud is IUniqueSplittableChordDef iscd && iscd.MsDurationToNextBarline != null) { msPositionReVoiceDef += (int)iscd.MsDurationToNextBarline; }
private void AddExtendersAtTheEndsOfStaves(List <Staff> staves, float rightMarginPos, float gap, float extenderStrokeWidth, float hairlinePadding, SvgSystem nextSystem) { for (int staffIndex = 0; staffIndex < staves.Count; ++staffIndex) { Staff staff = staves[staffIndex]; if (!(staff is InvisibleOutputStaff)) { for (int voiceIndex = 0; voiceIndex < staff.Voices.Count; ++voiceIndex) { Voice voice = staff.Voices[voiceIndex]; List <NoteObject> noteObjects = voice.NoteObjects; ChordSymbol lastChord = null; RestSymbol lastRest = null; CautionaryChordSymbol cautionary = null; for (int index = noteObjects.Count - 1; index >= 0; --index) { lastChord = noteObjects[index] as ChordSymbol; lastRest = noteObjects[index] as RestSymbol; cautionary = noteObjects[index] as CautionaryChordSymbol; if (cautionary != null) { cautionary.Visible = false; // a CautionaryChordSymbol is a ChordSymbol, but we have not found a real one yet. } else if (lastChord != null || lastRest != null) { break; } } if (lastChord != null && lastChord.MsDurationToNextBarline != null) { List <float> x1s = GetX1sFromChord1(lastChord.ChordMetrics, hairlinePadding); List <float> x2s; List <float> ys = lastChord.ChordMetrics.HeadsOriginYs; if (nextSystem != null && FirstDurationSymbolOnNextSystemIsCautionary(nextSystem.Staves[staffIndex].Voices[voiceIndex])) { x2s = GetEqualFloats(rightMarginPos + gap, x1s.Count); } else { x2s = GetEqualFloats(rightMarginPos, x1s.Count); } lastChord.ChordMetrics.NoteheadExtendersMetrics = CreateExtenders(x1s, x2s, ys, extenderStrokeWidth, gap, true); } } } } }
private void GetNumberOfVoices(SvgSystem svgSystem, ref int nOutputVoices) { nOutputVoices = 0; foreach (Staff staff in svgSystem.Staves) { foreach (Voice voice in staff.Voices) { if (voice is OutputVoice) { nOutputVoices++; } } } }
private void CreateEmptyOutputStaves(List <List <VoiceDef> > barDefsInOneSystem, int numberOfVisibleInputStaves) { int nVisibleOutputStaves = _pageFormat.VisibleOutputVoiceIndicesPerStaff.Count; List <byte> invisibleOutputVoiceIndices = new List <byte>(); if (numberOfVisibleInputStaves > 0) { invisibleOutputVoiceIndices = InvisibleOutputVoiceIndices(_pageFormat.VisibleOutputVoiceIndicesPerStaff, barDefsInOneSystem[0]); } for (int i = 0; i < Systems.Count; i++) { SvgSystem system = Systems[i]; List <VoiceDef> barDef = barDefsInOneSystem[i]; #region create invisible staves if (invisibleOutputVoiceIndices.Count > 0) { foreach (byte invisibleOutputVoiceIndex in invisibleOutputVoiceIndices) { TrkDef invisibleTrkDef = barDef[invisibleOutputVoiceIndex] as TrkDef; InvisibleOutputStaff invisibleOutputStaff = new InvisibleOutputStaff(system); OutputVoice outputVoice = new OutputVoice(invisibleOutputStaff, invisibleTrkDef.MidiChannel, invisibleTrkDef.MasterVolume); outputVoice.VoiceDef = invisibleTrkDef; invisibleOutputStaff.Voices.Add(outputVoice); system.Staves.Add(invisibleOutputStaff); } } #endregion create invisible staves for (int printedStaffIndex = 0; printedStaffIndex < nVisibleOutputStaves; printedStaffIndex++) { string staffname = StaffName(i, printedStaffIndex); OutputStaff outputStaff = new OutputStaff(system, staffname, _pageFormat.StafflinesPerStaff[printedStaffIndex], _pageFormat.Gap, _pageFormat.StafflineStemStrokeWidth); List <byte> outputVoiceIndices = _pageFormat.VisibleOutputVoiceIndicesPerStaff[printedStaffIndex]; for (int ovIndex = 0; ovIndex < outputVoiceIndices.Count; ++ovIndex) { TrkDef trkDef = barDef[outputVoiceIndices[ovIndex]] as TrkDef; Debug.Assert(trkDef != null); OutputVoice outputVoice = new OutputVoice(outputStaff, trkDef.MidiChannel, trkDef.MasterVolume); outputVoice.VoiceDef = trkDef; outputStaff.Voices.Add(outputVoice); } SetStemDirections(outputStaff); system.Staves.Add(outputStaff); } } }
/// <summary> /// The current msPosition of a voice will be retrievable as currentMsPositionPerVoicePerStaff[staffIndex][voiceIndex]. /// </summary> /// <param name="system"></param> /// <returns></returns> private List <List <int> > InitializeCurrentMsPositionPerVoicePerStaff(SvgSystem system) { List <List <int> > currentMsPositionPerVoicePerStaff = new List <List <int> >(); foreach (Staff staff in system.Staves) { List <int> currentVoiceMsPositions = new List <int>(); currentMsPositionPerVoicePerStaff.Add(currentVoiceMsPositions); foreach (Voice voice in staff.Voices) { currentVoiceMsPositions.Add(0); } } return(currentMsPositionPerVoicePerStaff); }
/// <summary> /// Copies Systems[systemIndex]'s content to the end of the previous system (taking account of clefs), /// then removes Systems[systemIndex] from the Systems list. /// </summary> /// <param name="barlineIndex"></param> private void JoinToPreviousSystem(int systemIndex) { Debug.Assert(Systems.Count > 1 && Systems.Count > systemIndex); SvgSystem system1 = Systems[systemIndex - 1]; SvgSystem system2 = Systems[systemIndex]; Debug.Assert(system1.Staves.Count == system2.Staves.Count); for (int staffIndex = 0; staffIndex < system2.Staves.Count; staffIndex++) { bool visibleStaff = !(system1.Staves[staffIndex] is InvisibleOutputStaff); string clefTypeAtEndOfStaff1 = null; if (visibleStaff) { // If a staff has two voices, both contain the same clefTypes (some clefs may be invisible). clefTypeAtEndOfStaff1 = FindClefTypeAtEndOfStaff1(system1.Staves[staffIndex].Voices[0]); } for (int voiceIndex = 0; voiceIndex < system2.Staves[staffIndex].Voices.Count; voiceIndex++) { Voice voice1 = system1.Staves[staffIndex].Voices[voiceIndex]; Voice voice2 = system2.Staves[staffIndex].Voices[voiceIndex]; if (visibleStaff) { ClefSymbol voice2FirstClef = voice2.NoteObjects[0] as ClefSymbol; Debug.Assert(voice2FirstClef != null && clefTypeAtEndOfStaff1 == voice2FirstClef.ClefType); voice2.NoteObjects.Remove(voice2FirstClef); } try { voice1.AppendNoteObjects(voice2.NoteObjects); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } Systems.Remove(system2); system2 = null; }
public override void AddNoteheadExtenderLines(List <Staff> staves, float rightMarginPos, float gap, float extenderStrokeWidth, float hairlinePadding, SvgSystem nextSystem) { AddExtendersAtTheBeginningsofStaves(staves, rightMarginPos, gap, extenderStrokeWidth, hairlinePadding); AddExtendersInStaves(staves, extenderStrokeWidth, gap, hairlinePadding); AddExtendersAtTheEndsOfStaves(staves, rightMarginPos, gap, extenderStrokeWidth, hairlinePadding, nextSystem); }
/// <summary> /// There is still one system per bar. /// </summary> /// <param name="systems"></param> public void ConvertVoiceDefsToNoteObjects(List <SvgSystem> systems) { byte[] currentChannelVelocities = new byte[systems[0].Staves.Count]; List <ClefChangeDef> voice0ClefChangeDefs = new List <ClefChangeDef>(); List <ClefChangeDef> voice1ClefChangeDefs = new List <ClefChangeDef>(); for (int systemIndex = 0; systemIndex < systems.Count; ++systemIndex) { SvgSystem system = systems[systemIndex]; int visibleStaffIndex = -1; for (int staffIndex = 0; staffIndex < system.Staves.Count; ++staffIndex) { Staff staff = system.Staves[staffIndex]; if (!(staff is InvisibleOutputStaff)) { visibleStaffIndex++; } voice0ClefChangeDefs.Clear(); voice1ClefChangeDefs.Clear(); for (int voiceIndex = 0; voiceIndex < staff.Voices.Count; ++voiceIndex) { Voice voice = staff.Voices[voiceIndex]; float musicFontHeight = (voice is OutputVoice) ? _pageFormat.MusicFontHeight : _pageFormat.MusicFontHeight * _pageFormat.InputStavesSizeFactor; if (!(staff is InvisibleOutputStaff)) { Debug.Assert(_pageFormat.ClefsList[visibleStaffIndex] != null); voice.NoteObjects.Add(new ClefSymbol(voice, _pageFormat.ClefsList[visibleStaffIndex], musicFontHeight)); } bool firstLmdd = true; if (staff is InputStaff) { InputVoice inputVoice = staff.Voices[voiceIndex] as InputVoice; if (systemIndex == 0) { InputVoiceDef inputVoiceDef = inputVoice.VoiceDef as InputVoiceDef; inputVoice.SetMidiChannel(inputVoiceDef.MidiChannel, systemIndex); } } foreach (IUniqueDef iud in voice.VoiceDef.UniqueDefs) { NoteObject noteObject = SymbolSet.GetNoteObject(voice, iud, firstLmdd, ref currentChannelVelocities[staffIndex], musicFontHeight); ClefChangeSymbol clefChangeSymbol = noteObject as ClefChangeSymbol; if (clefChangeSymbol != null) { if (voiceIndex == 0) { voice0ClefChangeDefs.Add(iud as ClefChangeDef); } else { voice1ClefChangeDefs.Add(iud as ClefChangeDef); } } voice.NoteObjects.Add(noteObject); firstLmdd = false; } } if (voice0ClefChangeDefs.Count > 0 || voice1ClefChangeDefs.Count > 0) { // the main clef on this staff in the next system SetNextSystemClefType(staffIndex, voice0ClefChangeDefs, voice1ClefChangeDefs); } if (staff.Voices.Count == 2) { InsertInvisibleClefChangeSymbols(staff.Voices, voice0ClefChangeDefs, voice1ClefChangeDefs); CheckClefTypes(staff.Voices); StandardSymbolSet standardSymbolSet = SymbolSet as StandardSymbolSet; if (standardSymbolSet != null) { standardSymbolSet.ForceNaturalsInSynchronousChords(staff); } } } } }
/// <summary> /// Feb. 2012: Currently only the StandardSymbolSet supports notehead extender lines. /// </summary> public virtual void AddNoteheadExtenderLines(List <Staff> staves, float rightMarginPos, float gap, float extenderStrokeWidth, float hairlinePadding, SvgSystem nextSystem) { }
/// <summary> /// Feb. 2012: Currently only the StandardSymbolSet supports notehead extender lines. /// </summary> public virtual void AddNoteheadExtenderLines(List <Staff> staves, double rightMarginPos, double gap, double extenderStrokeWidth, double hairlinePadding, SvgSystem nextSystem) { }
public OutputStaff(SvgSystem svgSystem, string staffName, int numberOfStafflines, double gap, double stafflineStemStrokeWidth) : base(svgSystem, staffName, numberOfStafflines, gap, stafflineStemStrokeWidth) { }
public InputStaff(SvgSystem svgSystem, string staffName, int numberOfStafflines, float gap, float stafflineStemStrokeWidth) : base(svgSystem, staffName, numberOfStafflines, gap, stafflineStemStrokeWidth) { }
public InvisibleOutputStaff(SvgSystem svgSystem) : base(svgSystem, "", 1, 1, 1) // These default values will never be used. { }