private void BeforeDrawRepeatSign(ScoreRendererBase renderer, Barline element, double?measureWidth) { if (element.RepeatSign == RepeatSignType.Forward && scoreService.CurrentStaff.Elements.IndexOf(element) > 0) { if (!renderer.IsSMuFLFont) { scoreService.CursorPositionX -= 8; //TODO: Temporary workaround!! } else if (!renderer.CanDrawCharacterInBounds) { scoreService.CursorPositionX -= renderer.LinespacesToPixels(1); } } if (renderer.Settings.IgnoreCustomElementPositions || !measureWidth.HasValue) { scoreService.CursorPositionX += 2 * (element.RepeatSign == RepeatSignType.Backward ? 1 : -1); } if (element.Location == HorizontalPlacement.Right) { measurementService.LastMeasurePositionX = scoreService.CursorPositionX; } if (scoreService.CurrentStaffNo > 1 && element.RenderedXPositionForFirstStaffInMultiStaffPart > 0) { scoreService.CursorPositionX = element.RenderedXPositionForFirstStaffInMultiStaffPart; } }
private void DrawFermataSign(ScoreRendererBase renderer, Note element, double notePositionY, FontProfile fontProfile) { if (element.HasFermataSign) { double ferPosY = scoreService.CurrentLinePositions[0] - renderer.LinespacesToPixels(2.5); while (ferPosY > notePositionY || ferPosY > element.StemEndLocation.Y) { ferPosY -= renderer.LinespacesToPixels(0.5); if (ferPosY < scoreService.CurrentLinePositions[0] - renderer.LinespacesToPixels(4)) { break; } } char fermataVersion = fontProfile.MusicFont.FermataUp; renderer.DrawCharacter(fermataVersion, MusicFontStyles.MusicFont, scoreService.CursorPositionX, ferPosY, element); } }
private void DrawTies(ScoreRendererBase renderer, Note element, double notePositionY) { if (element.TieType == NoteTieType.Start) { measurementService.TieStartSystem = element.Measure?.System; measurementService.TieStartPoint = new Point(scoreService.CursorPositionX + GetNoteheadWidthPx(element, renderer) / 2, notePositionY); measurementService.TieStartElement = element; } else if (element.TieType != NoteTieType.None) //Stop or StopAndStartAnother / Stop lub StopAndStartAnother { var tieEndpointThickness = renderer.GetEngravingDefault("tieEndpointThickness") ?? 1; var tieMidpointThickness = renderer.GetEngravingDefault("tieMidpointThickness") ?? 2; var tiePen = new Pen(element.CoalesceColor(renderer), tieEndpointThickness); double arcHeight = renderer.LinespacesToPixels(2); var modifierY = element.StemDirection == VerticalDirection.Down ? -1 : 1; var arcStartX = measurementService.TieStartPoint.X;// - element.GetNoteheadWidthPx(renderer) / 2; var arcStartY = measurementService.TieStartPoint.Y + renderer.LinespacesToPixels(1) * modifierY; if (renderer.Settings.RenderingMode == ScoreRenderingModes.Panorama || element.Measure?.System == measurementService.TieStartSystem) { double arcWidth = scoreService.CursorPositionX - measurementService.TieStartPoint.X + element.GetNoteheadWidthPx(renderer) / 2 - 2; //-2 to modyfikator, żeby łuki się nie krzyżowały DrawTiesInternal(renderer, arcStartX, arcStartY, arcStartY, arcWidth, arcHeight, modifierY, element, tiePen, tieMidpointThickness); } else { //Draw ties at system breaks var firstHalfOfArcWidth = (measurementService.TieStartElement.Measure?.BarlineLocationX ?? measurementService.TieStartSystem.Width) - measurementService.TieStartElement.TextBlockLocation.X - measurementService.TieStartElement.GetNoteheadWidthPx(renderer) / 2; DrawTiesInternal(renderer, arcStartX, arcStartY, arcStartY + arcHeight * modifierY, firstHalfOfArcWidth, arcHeight, modifierY, measurementService.TieStartElement, tiePen, tieMidpointThickness); var secondHalfOfArcStartX = element.TextBlockLocation.X - 20; var arcStartYSecondHalf = element.TextBlockLocation.Y + renderer.LinespacesToPixels(1) * modifierY; DrawTiesInternal(renderer, secondHalfOfArcStartX, arcStartYSecondHalf, arcStartYSecondHalf, element.TextBlockLocation.X - secondHalfOfArcStartX, arcHeight, modifierY, element, tiePen, tieMidpointThickness); } if (element.TieType == NoteTieType.StopAndStartAnother) { measurementService.TieStartPoint = new Point(scoreService.CursorPositionX + 2, notePositionY); } } }
/// <summary> /// Renders time signature symbol with specific score renderer /// </summary> /// <param name="element"></param> /// <param name="renderer"></param> public override void Render(TimeSignature element, ScoreRendererBase renderer, FontProfile fontProfile) { var topLinePosition = scoreService.CurrentLinePositions[0]; if (element.Measure.Elements.FirstOrDefault() == element) { scoreService.CursorPositionX += renderer.LinespacesToPixels(1); //Żeby był lekki margines między kreską taktową a symbolem. Być może ta linijka będzie do usunięcia } if (element.SignatureType != TimeSignatureType.Numbers) { renderer.DrawCharacter(element.GetCharacter(fontProfile.MusicFont), MusicFontStyles.MusicFont, scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(2), element); element.TextBlockLocation = new Primitives.Point(scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(2)); } else { if (renderer.IsSMuFLFont) { renderer.DrawString(fontProfile.MusicFont.BuildTimeSignature(element.NumberOfBeats), MusicFontStyles.MusicFont, scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(1), element); renderer.DrawString(fontProfile.MusicFont.BuildTimeSignature(element.TypeOfBeats), MusicFontStyles.MusicFont, scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(3), element); element.TextBlockLocation = new Primitives.Point(scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(3)); } else { renderer.DrawString(Convert.ToString(element.NumberOfBeats), MusicFontStyles.TimeSignatureFont, scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(2), element); renderer.DrawString(Convert.ToString(element.TypeOfBeats), MusicFontStyles.TimeSignatureFont, scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(4), element); element.TextBlockLocation = new Primitives.Point(scoreService.CursorPositionX, topLinePosition + renderer.LinespacesToPixels(4)); } } scoreService.CursorPositionX += 20; }
/// <summary> /// Renders a rest with specific score renderer /// </summary> /// <param name="element"></param> /// <param name="renderer"></param> public override void Render(Rest element, ScoreRendererBase renderer, FontProfile fontProfile) { var isOnlyElementInMeasure = element.Measure?.Elements?.OfType <NoteOrRest>().Count() == 1; if (!renderer.Settings.IgnoreCustomElementPositions && element.DefaultXPosition.HasValue) //Jeśli ustalono default-x, to pozycjonuj wg default-x, a nie automatycznie { scoreService.CursorPositionX = measurementService.LastMeasurePositionX + element.DefaultXPosition.Value * renderer.Settings.CustomElementPositionRatio; } else if (isOnlyElementInMeasure && (element.Measure?.Width.HasValue ?? false)) { scoreService.CursorPositionX = measurementService.LastMeasurePositionX + (element.Measure.Width.Value / 2) * renderer.Settings.CustomElementPositionRatio; } if (scoreService.CurrentMeasure.FirstNoteInMeasureXPosition == 0) { scoreService.CurrentMeasure.FirstNoteInMeasureXPosition = scoreService.CursorPositionX; } //If it's second voice, rewind position to the beginning of measure (but only if default-x is not set or is ignored): if (element.Voice > scoreService.CurrentVoice && (renderer.Settings.IgnoreCustomElementPositions || !element.DefaultXPosition.HasValue)) { scoreService.CursorPositionX = scoreService.CurrentMeasure.FirstNoteInMeasureXPosition; measurementService.LastNoteInMeasureEndXPosition = measurementService.LastNoteEndXPosition; } scoreService.CurrentVoice = element.Voice; double restPositionY = scoreService.CurrentLinePositions[0] + (element.DefaultYPosition.HasValue ? renderer.TenthsToPixels(element.DefaultYPosition.Value) : renderer.LinespacesToPixels(2)); renderer.DrawCharacter(element.GetCharacter(fontProfile.MusicFont), MusicFontStyles.MusicFont, scoreService.CursorPositionX, restPositionY, element); measurementService.LastNotePositionX = scoreService.CursorPositionX; element.TextBlockLocation = new Point(scoreService.CursorPositionX, restPositionY); //Draw number of measures for multimeasure rests / Rysuj ilość taktów dla pauz wielotaktowych: if (element.MultiMeasure > 1) { renderer.DrawString(Convert.ToString(element.MultiMeasure), MusicFontStyles.DirectionFont, scoreService.CursorPositionX + 6, restPositionY, element); } //Draw dots / Rysuj kropki: if (element.NumberOfDots > 0) { scoreService.CursorPositionX += 16; } for (int i = 0; i < element.NumberOfDots; i++) { renderer.DrawCharacter(fontProfile.MusicFont.AugmentationDot, MusicFontStyles.MusicFont, scoreService.CursorPositionX, restPositionY, element); scoreService.CursorPositionX += 6; } if (renderer.Settings.IgnoreCustomElementPositions || !element.DefaultXPosition.HasValue) //Pozycjonowanie automatyczne tylko, gdy nie określono default-x { if (element.Duration == RhythmicDuration.Whole) { scoreService.CursorPositionX += 48; } else if (element.Duration == RhythmicDuration.Half) { scoreService.CursorPositionX += 28; } else if (element.Duration == RhythmicDuration.Quarter) { scoreService.CursorPositionX += 17; } else if (element.Duration == RhythmicDuration.Eighth) { scoreService.CursorPositionX += 15; } else { scoreService.CursorPositionX += 14; } } measurementService.LastNoteEndXPosition = scoreService.CursorPositionX; }
public override void Render(Clef element, ScoreRendererBase renderer, FontProfile fontProfile) { if (!(fontProfile.IsSMuFLFont)) { var yPosition = element.OctaveChange > 0 ? scoreService.CurrentLinePositions[0] - renderer.LinespacesToPixels(2) : scoreService.CurrentLinePositions[4] + renderer.LinespacesToPixels(3.5); var octaveChangeText = GetOctaveChangeNumberForPolihymniaFont(element.OctaveChange); renderer.DrawString(octaveChangeText, MusicFontStyles.DirectionFont, element.TextBlockLocation.X + 6, yPosition, element); } //Don't draw clef if it's current clef: if (!WasSystemChanged && element.TypeOfClef == scoreService.CurrentClef.TypeOfClef && element.Pitch == scoreService.CurrentClef.Pitch && element.Line == scoreService.CurrentClef.Line) { return; } element.TextBlockLocation = new Point(scoreService.CursorPositionX, scoreService.CurrentLinePositions[4] - (element.Line - 1) * renderer.Settings.LineSpacing); scoreService.CurrentClef = element; if (element.TypeOfClef == ClefType.Percussion) { DrawPercussionClef(element, renderer); } else { renderer.DrawCharacter(element.GetCharacter(fontProfile.MusicFont), MusicFontStyles.MusicFont, element.TextBlockLocation.X, element.TextBlockLocation.Y, element); } scoreService.CursorPositionX += 20; }
private void DrawTrills(ScoreRendererBase renderer, Note element, double notePositionY, FontProfile fontProfile) { if (element.TrillMark != NoteTrillMark.None) { var placement = element.TrillMark == NoteTrillMark.Above ? VerticalPlacement.Above : VerticalPlacement.Below; double trillPos = CorrectOrnamentYPositionToAvoidIntersection(renderer, placement, renderer.LinespacesToPixels(2), notePositionY, element, notePositionY); renderer.DrawCharacter(fontProfile.MusicFont.Trill, MusicFontStyles.MusicFont, scoreService.CursorPositionX - 1, trillPos, element); } }
private void DrawStems(ScoreRendererBase renderer, Note element, double notePositionY, Note[] chord) { if (element.BaseDuration > RhythmicDuration.Half || element.IsUpperMemberOfChord) { return; } var additionalPlaceForFlag = Math.Log(element.BaseDuration.Denominator, 2) - 2; if (additionalPlaceForFlag < 0) { additionalPlaceForFlag = 0; } if (additionalPlaceForFlag > 1) { additionalPlaceForFlag *= 0.8; } var defaultStemLengthLs = 3 + ((element.BeamList.Any(b => b == NoteBeamType.Single) ? additionalPlaceForFlag : 0)) * (element.IsCueNote || element.IsGraceNote ? 0.66 : 1); var defaultStemLength = renderer.LinespacesToPixels(defaultStemLengthLs); double customStemEndPosition = scoreService.CurrentStaffTop + renderer.TenthsToPixels(element.StemDefaultY); double notePositionForCalculatingStemEnd = GetNotePositionForCalculatingStemEnd(renderer, element, notePositionY, chord); double notePositionForCalculatingStemStart = GetNotePositionForCalculatingStemStart(renderer, element, notePositionY, chord); if (element.StemDirection == VerticalDirection.Down) { if (renderer.Settings.IgnoreCustomElementPositions || !element.HasCustomStemEndPosition) { beamingService.CurrentStemEndPositionY = notePositionForCalculatingStemEnd + defaultStemLength; } else { beamingService.CurrentStemEndPositionY = customStemEndPosition - 4; } } else { if (renderer.Settings.IgnoreCustomElementPositions || !element.HasCustomStemEndPosition) { beamingService.CurrentStemEndPositionY = notePositionForCalculatingStemEnd - defaultStemLength; } else { beamingService.CurrentStemEndPositionY = customStemEndPosition - 6; } } if (renderer.IsSMuFLFont) { var cueNoteShift = element.StemDirection == VerticalDirection.Up ? -3 : 0; beamingService.CurrentStemPositionX = scoreService.CursorPositionX + element.GetNoteheadWidthPx(renderer) * (element.StemDirection == VerticalDirection.Down ? 0 : 1) + (element.IsGraceNote || element.IsCueNote ? cueNoteShift : 0); } else { var polihymniaBadDesignFontFix = element.GetNoteheadWidthPx(renderer) * (element.IsCueNote || element.IsGraceNote ? 2 : 1) + 0.5; beamingService.CurrentStemPositionX = scoreService.CursorPositionX + polihymniaBadDesignFontFix + (element.GetNoteheadWidthPx(renderer) / 2) * (element.StemDirection == VerticalDirection.Down ? -1 : 1) + (element.IsGraceNote || element.IsCueNote ? -2 : 0); } if (element.BeamList.Count > 0 && (element.BeamList[0] != NoteBeamType.Continue || element.HasCustomStemEndPosition)) { var stemPen = renderer.CreatePenFromDefaults(element, "stemThickness", s => s.DefaultStemThickness); renderer.DrawLine( new Point(beamingService.CurrentStemPositionX, notePositionForCalculatingStemStart), new Point(beamingService.CurrentStemPositionX, beamingService.CurrentStemEndPositionY), stemPen, element); } element.StemEndLocation = new Point(beamingService.CurrentStemPositionX, beamingService.CurrentStemEndPositionY); if (element.GraceNoteType == GraceNoteType.Slashed) { renderer.DrawLine(beamingService.CurrentStemPositionX - 5, notePositionY - 5, beamingService.CurrentStemPositionX + 5, notePositionY - 5 - 6, element); } }
private void DrawOrnaments(ScoreRendererBase renderer, Note element, double notePositionY, FontProfile fontProfile) { foreach (Ornament ornament in element.Ornaments) { double yPosition; if (ornament.DefaultYPosition.HasValue) { var yShift = renderer.TenthsToPixels(ornament.DefaultYPosition.Value); yPosition = scoreService.CurrentLinePositions[0] + yShift; } else { yPosition = notePositionY + (ornament.Placement == VerticalPlacement.Above ? -20 : 20); } yPosition = CorrectOrnamentYPositionToAvoidIntersection(renderer, ornament.Placement, renderer.LinespacesToPixels(1), yPosition, element, notePositionY); Mordent mordent = ornament as Mordent; if (mordent != null) { if (renderer.IsSMuFLFont) { renderer.DrawCharacter(mordent.GetCharacter(fontProfile.MusicFont), MusicFontStyles.MusicFont, scoreService.CursorPositionX - element.GetNoteheadWidthPx(renderer) / 2, yPosition, element); } else { renderer.DrawCharacter(fontProfile.MusicFont.MordentShort, MusicFontStyles.GraceNoteFont, scoreService.CursorPositionX, yPosition, element); renderer.DrawCharacter(fontProfile.MusicFont.Mordent, MusicFontStyles.GraceNoteFont, scoreService.CursorPositionX + 5.5, yPosition, element); } } } }
private void DrawLedgerLines(ScoreRendererBase renderer, Note element, double notePositionY) { var ledgerLinePen = renderer.CreatePenFromDefaults(element, "legerLineThickness", s => s.DefaultStaffLineThickness); double startPositionX = scoreService.CursorPositionX - (renderer.IsSMuFLFont ? element.GetNoteheadWidthPx(renderer) * 0.5 : 0); double endPositionX = scoreService.CursorPositionX + (renderer.IsSMuFLFont ? element.GetNoteheadWidthPx(renderer) * 1.5 : renderer.LinespacesToPixels(element.GetNoteheadWidthLs(renderer) * 2.2)); if (notePositionY > scoreService.CurrentLinePositions[4] + renderer.Settings.LineSpacing / 2.0f) { for (double i = scoreService.CurrentLinePositions[4]; i < notePositionY - renderer.Settings.LineSpacing / 2.0f; i += renderer.Settings.LineSpacing) { renderer.DrawLine( new Point(startPositionX, i + renderer.Settings.LineSpacing), new Point(endPositionX, i + renderer.Settings.LineSpacing), ledgerLinePen, element); } } if (notePositionY < scoreService.CurrentLinePositions[0] - renderer.Settings.LineSpacing / 2) { for (double i = scoreService.CurrentLinePositions[0]; i > notePositionY + renderer.Settings.LineSpacing / 2.0f; i -= renderer.Settings.LineSpacing) { renderer.DrawLine( new Point(startPositionX, i - renderer.Settings.LineSpacing), new Point(endPositionX, i - renderer.Settings.LineSpacing), ledgerLinePen, element); } } }
private static double GetNoteheadWidthPx(Note element, ScoreRendererBase renderer, double ratio = 1) => renderer.LinespacesToPixels(element.GetNoteheadWidthLs(renderer) * ratio);
public override void Render(Key element, ScoreRendererBase renderer, FontProfile fontProfile) { if (element.Fifths != 0 && element.Measure.Elements.FirstOrDefault() == element) { scoreService.CursorPositionX += renderer.LinespacesToPixels(1); //Żeby był lekki margines między kreską taktową a symbolem. Być może ta linijka będzie do usunięcia } scoreService.CurrentKey = element; double flatOrSharpPositionY = 0; bool jumpFourth = false; int jumpDirection = 1; int octaveShiftSharp = 0; //In G clef sharps (not flats) should be written an octave higher / W kluczu g krzyżyki (bemole nie) powinny być zapisywane o oktawę wyżej if (scoreService.CurrentClef.TypeOfClef == ClefType.GClef) { octaveShiftSharp = 1; } int octaveShiftFlat = 0; if (scoreService.CurrentClef.TypeOfClef == ClefType.FClef) { octaveShiftFlat = -1; } if (!IsVirtualKey) { element.TextBlockLocation = new Primitives.Point(scoreService.CursorPositionX, scoreService.CurrentLinePositions[0]); } if (scoreService.CurrentKey.Fifths > 0) { flatOrSharpPositionY = scoreService.CurrentClef.TextBlockLocation.Y + Pitch.StepDistance(scoreService.CurrentClef, Pitch.FromStep(Step.F, scoreService.CurrentClef.Pitch.Octave + octaveShiftSharp)) * (renderer.Settings.LineSpacing / 2); jumpFourth = true; jumpDirection = 1; } else if (scoreService.CurrentKey.Fifths < 0) { flatOrSharpPositionY = scoreService.CurrentClef.TextBlockLocation.Y + Pitch.StepDistance(scoreService.CurrentClef, Pitch.FromStep(Step.B, scoreService.CurrentClef.Pitch.Octave + octaveShiftFlat)) * (renderer.Settings.LineSpacing / 2); jumpFourth = true; jumpDirection = -1; } for (int i = 0; i < Math.Abs(scoreService.CurrentKey.Fifths); i++) { renderer.DrawCharacter(element.GetCharacter(fontProfile.MusicFont), MusicFontStyles.MusicFont, scoreService.CursorPositionX, flatOrSharpPositionY, element); if (jumpFourth) { flatOrSharpPositionY += 3 * 3 * jumpDirection; } else { flatOrSharpPositionY += 3 * 4 * jumpDirection; } jumpFourth = !jumpFourth; jumpDirection *= -1; scoreService.CursorPositionX += 8; } scoreService.CursorPositionX += 10; }