/// <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 override NoteObject GetNoteObject(Voice voice, IUniqueDef iud, bool firstDefInVoice, ref byte currentVelocity, float musicFontHeight) { NoteObject noteObject = null; CautionaryChordDef cautionaryChordDef = iud as CautionaryChordDef; MidiChordDef midiChordDef = iud as MidiChordDef; InputChordDef inputChordDef = iud as InputChordDef; RestDef restDef = iud as RestDef; ClefChangeDef clefChangeDef = iud as ClefChangeDef; PageFormat pageFormat = voice.Staff.SVGSystem.Score.PageFormat; float cautionaryFontHeight = pageFormat.CautionaryNoteheadsFontHeight; int minimumCrotchetDuration = pageFormat.MinimumCrotchetDuration; if (cautionaryChordDef != null && firstDefInVoice) { CautionaryChordSymbol cautionaryChordSymbol = new CautionaryChordSymbol(voice, cautionaryChordDef, cautionaryFontHeight); noteObject = cautionaryChordSymbol; } else if (midiChordDef != null) { OutputChordSymbol outputChordSymbol = new OutputChordSymbol(voice, midiChordDef, minimumCrotchetDuration, musicFontHeight); if (midiChordDef.MidiVelocity != currentVelocity) { outputChordSymbol.AddDynamic(midiChordDef.MidiVelocity, currentVelocity); currentVelocity = midiChordDef.MidiVelocity; } noteObject = outputChordSymbol; } else if (inputChordDef != null) { InputChordSymbol inputChordSymbol = new InputChordSymbol(voice, inputChordDef, minimumCrotchetDuration, musicFontHeight); noteObject = inputChordSymbol; } else if (restDef != null) { RestSymbol restSymbol = new RestSymbol(voice, iud, minimumCrotchetDuration, musicFontHeight); noteObject = restSymbol; } else if (clefChangeDef != null) { ClefChangeSymbol clefChangeSymbol = new ClefChangeSymbol(voice, clefChangeDef.ClefType, cautionaryFontHeight, ((IUniqueDef)iud).MsPosition); noteObject = clefChangeSymbol; } return(noteObject); }
/// <summary> /// Returns the positive horizontal distance by which this metrics overlaps the argument metrics. /// The result can be 0, if previousMetrics.Right = this.Metrics.Left. /// If there is no overlap, float.MinValue is returned. /// </summary> public float OverlapWidth(AnchorageSymbol previousAS) { float overlap = float.MinValue; OutputChordSymbol chord = previousAS as OutputChordSymbol; if (chord != null) { overlap = chord.ChordMetrics.OverlapWidth(this); } else { overlap = this.OverlapWidth(previousAS.Metrics); } return(overlap); }
/// <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 Head(OutputChordSymbol outputChordSymbol, Note mnxcNote) { Chord = outputChordSymbol; Pitch = mnxcNote.NoteheadPitch; if (Pitch.Contains("##")) { Alteration = 2; } else if (Pitch.Contains("#")) { Alteration = 1; } else if (Pitch.Contains("bb")) { Alteration = -2; } else if (Pitch.Contains("b")) { Alteration = -1; } else { Alteration = 0; } if (mnxcNote.Accidental != null) { this.DisplayAccidental = DisplayAccidental.force; } ID = mnxcNote.ID; // can be null; if (mnxcNote.Tied != null) { Tied = mnxcNote.Tied; } }
public override NoteObject GetNoteObject(Voice voice, int absMsPosition, IUniqueDef iud, bool firstDefInVoice, ref byte currentVelocity, float musicFontHeight) { NoteObject noteObject = null; CautionaryChordDef cautionaryChordDef = iud as CautionaryChordDef; MidiChordDef midiChordDef = iud as MidiChordDef; InputChordDef inputChordDef = iud as InputChordDef; RestDef restDef = iud as RestDef; ClefChangeDef clefChangeDef = iud as ClefChangeDef; PageFormat pageFormat = voice.Staff.SVGSystem.Score.PageFormat; float cautionaryFontHeight = pageFormat.CautionaryNoteheadsFontHeight; int minimumCrotchetDuration = pageFormat.MinimumCrotchetDuration; if(cautionaryChordDef != null && firstDefInVoice) { if(cautionaryChordDef.NotatedMidiVelocities != null) { CautionaryOutputChordSymbol cautionaryOutputChordSymbol = new CautionaryOutputChordSymbol(voice, cautionaryChordDef, absMsPosition, cautionaryFontHeight); noteObject = cautionaryOutputChordSymbol; } else { CautionaryInputChordSymbol cautionaryInputChordSymbol = new CautionaryInputChordSymbol(voice, cautionaryChordDef, absMsPosition, cautionaryFontHeight); noteObject = cautionaryInputChordSymbol; } } else if(midiChordDef != null) { OutputChordSymbol outputChordSymbol = new OutputChordSymbol(voice, midiChordDef, absMsPosition, minimumCrotchetDuration, musicFontHeight); if(this._coloredVelocities == true) { outputChordSymbol.SetNoteheadColors(); } else if(midiChordDef.NotatedMidiVelocities[0] != currentVelocity) { outputChordSymbol.AddDynamic(midiChordDef.NotatedMidiVelocities[0], currentVelocity); currentVelocity = midiChordDef.NotatedMidiVelocities[0]; } noteObject = outputChordSymbol; } else if(inputChordDef != null) { InputChordSymbol inputChordSymbol = new InputChordSymbol(voice, inputChordDef, absMsPosition, minimumCrotchetDuration, musicFontHeight); noteObject = inputChordSymbol; } else if(restDef != null) { RestSymbol restSymbol = new RestSymbol(voice, iud, absMsPosition, minimumCrotchetDuration, musicFontHeight); noteObject = restSymbol; } else if(clefChangeDef != null) { ClefChangeSymbol clefChangeSymbol = new ClefChangeSymbol(voice, clefChangeDef.ClefType, absMsPosition, cautionaryFontHeight); noteObject = clefChangeSymbol; } return noteObject; }
private void AdjustRestsForVerticalChordCollisions(int restsChannelIndex) { Debug.Assert(restsChannelIndex == 0 || restsChannelIndex == 1); List <NoteObject> restObjects; List <NoteObject> chordObjects; bool shiftRestUp; if (restsChannelIndex == 0) { shiftRestUp = true; restObjects = Voices[0].NoteObjects; chordObjects = Voices[1].NoteObjects; } else { shiftRestUp = false; restObjects = Voices[1].NoteObjects; chordObjects = Voices[0].NoteObjects; } // Move rests in the top voice up by gap increments if they are synchronous with an overlapping chord in the lower voice. // Move rests in the bottom voice down by gap increments if they are synchronous with an overlapping chord in the top voice. foreach (NoteObject restObject in restObjects) { RestSymbol restSymbol = restObject as RestSymbol; if (restSymbol != null) { foreach (NoteObject chordObject in chordObjects) { OutputChordSymbol chordSymbol = chordObject as OutputChordSymbol; if (chordSymbol != null) { if (chordSymbol.MsPosition > restSymbol.MsPosition) { break; } if (chordSymbol.MsPosition == restSymbol.MsPosition) { RestMetrics restMetrics = restSymbol.RestMetrics; ChordMetrics chordMetrics = chordSymbol.ChordMetrics; //float verticalOverlap = chordMetrics.OverlapHeight(restMetrics, Gap / 2F); float verticalOverlap = chordMetrics.OverlapHeight(restMetrics, 0F); if (verticalOverlap > 0) { if (shiftRestUp) { //float newMaxBottom = chordMetrics.Top - Gap; float newMaxBottom = chordMetrics.Top; newMaxBottom += DurationClassDeltaAbove(restSymbol.DurationClass, Gap); while (restMetrics.Bottom > newMaxBottom) { restMetrics.LedgerlineVisible = true; // only affects breves, semibreves and minims restMetrics.Move(0F, -Gap); } break; // to next rest symbol } else { //float newMinTop = chordMetrics.Bottom + Gap; float newMinTop = chordMetrics.Bottom; newMinTop += DurationClassDeltaBelow(restSymbol.DurationClass, Gap); while (restMetrics.Top < newMinTop) { restMetrics.LedgerlineVisible = true; // only affects breves, semibreves and minims restMetrics.Move(0F, Gap); } break; // to next rest symbol } } } } } } } }
private bool NextNoteObjectIsABarline(OutputChordSymbol chord) { bool nextNoteObjectIsABarline = false; List<NoteObject> noteObjects = chord.Voice.NoteObjects; for(int i = 0; i < noteObjects.Count - 1; ++i) { if(noteObjects[i] == chord) { nextNoteObjectIsABarline = (noteObjects[i + 1] is Barline); break; } } return nextNoteObjectIsABarline; }