/// <summary> /// Moves rests onto the top and bottom stafflines. Most rests move two gaps from the centre staffline, /// but breve and semibreve rests in the top voice move to a position 1 gap above the top staffline, and /// breve and semibreve rests in the bottom voice move onto the bottom staffline. /// Breve and semibreve rests outside the stafflines have a single, visible "ledgerline". /// </summary> private void MoveRestsOntoOuterStafflines() { for (int voiceIndex = 0; voiceIndex < 2; ++voiceIndex) { foreach (NoteObject noteObject in Voices[voiceIndex].NoteObjects) { RestSymbol rest = noteObject as RestSymbol; if (rest != null) { RestMetrics metrics = (RestMetrics)rest.Metrics; if (voiceIndex == 0) { if (rest.DurationClass == DurationClass.breve || rest.DurationClass == DurationClass.semibreve) { metrics.LedgerlineVisible = true; // only affects breves, semibreves and minims } metrics.Move(0F, this.Gap * -2); } else { if (rest.DurationClass == DurationClass.breve || rest.DurationClass == DurationClass.semibreve) { metrics.Move(0F, this.Gap * 3); } else { metrics.Move(0F, this.Gap * 2); } } } } } }
private void AdjustRestRestCollisions() { List <NoteObject> upperObjects = Voices[0].NoteObjects; List <NoteObject> lowerObjects = Voices[1].NoteObjects; // If a rest in the top voice collides with a rest in the lower voice at the same msPosition, // both rests are moved in gap steps outwards until they no longer overlap. foreach (NoteObject topObject in upperObjects) { RestSymbol topRest = topObject as RestSymbol; if (topRest != null) { RestMetrics upperRestMetrics = topRest.Metrics as RestMetrics; foreach (NoteObject lowerObject in lowerObjects) { RestSymbol lowerRestSymbol = lowerObject as RestSymbol; if (lowerRestSymbol != null) { if (topRest.MsPosition < lowerRestSymbol.MsPosition) { break; } if (topRest.MsPosition == lowerRestSymbol.MsPosition) { RestMetrics lowerRestMetrics = (RestMetrics)lowerRestSymbol.Metrics; float verticalOverlap = lowerRestMetrics.OverlapHeight(upperRestMetrics, 0F); bool moveBottomRest = true; while (verticalOverlap > 0) { float newMinBottom = upperRestMetrics.Bottom - verticalOverlap; if (upperRestMetrics.Bottom > newMinBottom) { if (moveBottomRest) { lowerRestMetrics.LedgerlineVisible = true; // only affects breves, semibreves and minims lowerRestMetrics.Move(0F, Gap); moveBottomRest = false; } else { upperRestMetrics.LedgerlineVisible = true; // only affects breves, semibreves and minims upperRestMetrics.Move(0F, -Gap); moveBottomRest = true; } } verticalOverlap = lowerRestMetrics.OverlapHeight(upperRestMetrics, 0F); } } } } } } }
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); }
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; CautionaryOutputChordSymbol cautionaryOutputChordSymbol = noteObject as CautionaryOutputChordSymbol; CautionaryInputChordSymbol cautionaryInputChordSymbol = noteObject as CautionaryInputChordSymbol; 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(cautionaryOutputChordSymbol != null) { returnMetrics = new ChordMetrics(graphics, cautionaryOutputChordSymbol, voiceStemDirection, gap, strokeWidth); } else if(cautionaryInputChordSymbol != null) { returnMetrics = new ChordMetrics(graphics, cautionaryInputChordSymbol, 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 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 } } } } } } } }