/// <summary> /// Draws tuplet mark /// </summary> /// <param name="measurementService"></param> /// <param name="scoreService"></param> /// <param name="renderer"></param> /// <param name="element"></param> public static void TupletMark(IMeasurementService measurementService, IScoreService scoreService, ScoreRendererBase renderer, NoteOrRest element) { if (measurementService.TupletState == null) { throw new Exception("DrawTupletMark was called but no tuplet is currently open in staff."); } var tupletBracketPen = renderer.CreatePenFromDefaults(element, "tupletBracketThickness", s => s.DefaultTupletBracketThickness); Staff staff = scoreService.CurrentStaff; NoteOrRest firstElementInTuplet = staff.Peek <NoteOrRest>(element, PeekType.BeginningOfTuplet); int index = staff.Elements.IndexOf(firstElementInTuplet); List <MusicalSymbol> elementsUnderTuplet = staff.Elements.GetRange(index, staff.Elements.IndexOf(element) - index + 1); var noteGroupBounds = elementsUnderTuplet.OfType <Note>().GetBounds(renderer); if (IsDebugMode) { DrawNoteGroupOutline(renderer, noteGroupBounds, element); } var boundsOnOneSide = measurementService.TupletState.TupletPlacement == VerticalPlacement.Above ? new Tuple <Point, Point>(noteGroupBounds.NW, noteGroupBounds.NE) : new Tuple <Point, Point>(noteGroupBounds.SW, noteGroupBounds.SE); int placementMod = measurementService.TupletState.TupletPlacement == VerticalPlacement.Above ? -1 : 1; var bracketDefinition = new TupletBracketDefinition( boundsOnOneSide.Item1.X, boundsOnOneSide.Item1.Y + renderer.LinespacesToPixels(2) * placementMod, boundsOnOneSide.Item2.X, boundsOnOneSide.Item2.Y + renderer.LinespacesToPixels(2) * placementMod); if (measurementService.TupletState.AreSingleBeamsPresentUnderTuplet) //Draw tuplet bracket { renderer.DrawLine(bracketDefinition.StartPoint, bracketDefinition.Point25, tupletBracketPen, element); renderer.DrawLine(bracketDefinition.Point75, bracketDefinition.EndPoint, tupletBracketPen, element); renderer.DrawLine(bracketDefinition.StartPoint, bracketDefinition.StartPoint.Translate(0, renderer.LinespacesToPixels(-1) * placementMod), tupletBracketPen, element); renderer.DrawLine(bracketDefinition.EndPoint, bracketDefinition.EndPoint.Translate(0, renderer.LinespacesToPixels(-1) * placementMod), tupletBracketPen, element); } var tupletNumber = CalculateTupletNumber(elementsUnderTuplet.OfType <NoteOrRest>()); var textToWrite = renderer.Settings.MusicFontProfile.MusicFont.BuildTupletNumber(tupletNumber); var fontStyle = renderer.IsSMuFLFont ? MusicFontStyles.MusicFont : MusicFontStyles.LyricsFont; var textSize = renderer.CanMeasureString ? renderer.MeasureString(fontStyle, textToWrite) : new Size(); var textPosition = renderer.CanMeasureString ? bracketDefinition.MidPoint.Translate(textSize.Width / -2, textSize.Height / 2) : bracketDefinition.MidPoint.Translate(-3.7, 4.7); renderer.DrawString(textToWrite, fontStyle, textPosition, element); }
private Tuple <double, double> GetBraceLocationXAndWidth(ScoreRendererBase renderer) { if (renderer.IsSMuFLFont && renderer.Settings.MusicFontProfile.SMuFLMetadata != null) { var bounds = renderer.Settings.MusicFontProfile.SMuFLMetadata.GlyphBBoxes.Brace; var width = (bounds.BBoxNe[0] + bounds.BBoxSw[0]) * 3; //TODO: Sprawdzić czemu Brace ma tak mały bounding box w SMuFL return(new Tuple <double, double>(renderer.LinespacesToPixels(bounds.BBoxSw[0] * -3 - width), renderer.LinespacesToPixels(width))); } else { return(new Tuple <double, double>(-17.5, 15)); } }
/// <summary> /// Draws or performs additional logic at slur start /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY"></param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurStart(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { slurStartInfo.StartPlacement = slurPlacement; slurStartInfo.StartPointStemDirection = element.StemDirection; var polihymniaFix = renderer.LinespacesToPixels(element.GetNoteheadWidthLs(renderer) * 0.5); if (slurPlacement == VerticalPlacement.Above) { bool hasFlagOrBeam = element.BaseDuration.Denominator > 4; //If note has a flag or beam start the slur above the note. If not, start a bit to the right and down. var xShiftConcerningStemDirectionStart = slurStartInfo.StartPointStemDirection == VerticalDirection.Up ? (hasFlagOrBeam ? 5 : 10) : 1; slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionStart + polihymniaFix, element.StemDirection == VerticalDirection.Down ? notePositionY - 7 : element.StemEndLocation.Y + (hasFlagOrBeam ? -3 : 8)); } else { slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + 3 + polihymniaFix, notePositionY + 5); } }
/// <summary> /// Renders print suggestion with specific score renderer /// </summary> /// <param name="element"></param> /// <param name="renderer"></param> public override void Render(PrintSuggestion element, ScoreRendererBase renderer, FontProfile fontProfile) { if (element.IsSystemBreak && renderer.Settings.RenderingMode != ScoreRenderingModes.Panorama) { renderer.BreakSystem(renderer.TenthsToPixels(element.SystemDistance ?? scoreService.CurrentScore.DefaultPageSettings.DefaultSystemDistance ?? 0), element.IsPageBreak); var clefRenderStrategy = new ClefRenderStrategy(scoreService) { WasSystemChanged = true }; clefRenderStrategy.Render(scoreService.CurrentClef, renderer); var keyRenderStrategy = new KeyRenderStrategy(scoreService) { IsVirtualKey = true }; keyRenderStrategy.Render(scoreService.CurrentKey, renderer); //Time signature is not rendered in new line. //Render measure number: if (scoreService.CurrentStaff == scoreService.CurrentScore.FirstStaff) { renderer.DrawString((scoreService.CurrentMeasureNo).ToString(), MusicFontStyles.LyricsFont, new Primitives.Point(0, scoreService.CurrentLinePositions[0] - renderer.LinespacesToPixels(2)), scoreService.CurrentStaff); } } //Issue #44: Jeśli jesteśmy w trybie panoramy, to trzeba uzupełnić line positions dla pozostałych systemów: if (renderer.Settings.RenderingMode == ScoreRenderingModes.Panorama) { var firstSystem = scoreService.Systems.First(); foreach (var system in scoreService.Systems) { system.BuildStaffFragments(firstSystem.LinePositions.ToDictionary(p => scoreService.CurrentScore.Staves[p.Key - 1], p => p.Value)); } } }
public double GetNoteheadWidthPx(ScoreRendererBase renderer) { return(renderer.LinespacesToPixels(GetNoteheadWidthLs(renderer))); }