/// <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); }