public override void Paint(float cx, float cy, ICanvas canvas) { // only render slur once per staff var slurId = "score.slur." + _startBeat.SlurOrigin.Id; var renderer = Renderer; var isSlurRendered = renderer.Staff.GetSharedLayoutData(slurId, false); if (!isSlurRendered) { renderer.Staff.SetSharedLayoutData(slurId, true); var startNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <BarRendererBase>(Renderer.Staff.StaveId, _startBeat.Voice.Bar); var direction = GetBeamDirection(_startBeat, startNoteRenderer); var startX = cx + startNoteRenderer.X; var startY = cy + startNoteRenderer.Y; if (_startBeat.SlurOrigin.Id == _startBeat.Id) { startX += startNoteRenderer.GetBeatX(_startBeat, BeatXPosition.MiddleNotes); var note = direction == BeamDirection.Down ? _startBeat.MinNote : _startBeat.MaxNote; startY += startNoteRenderer.GetNoteY(note); } else { startY += startNoteRenderer.Height; } var endBeat = _startBeat.SlurOrigin.SlurDestination; var endNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <ScoreBarRenderer>(Renderer.Staff.StaveId, endBeat.Voice.Bar); float endX; float endY; if (endNoteRenderer == null || startNoteRenderer.Staff != endNoteRenderer.Staff) { endNoteRenderer = (ScoreBarRenderer)startNoteRenderer.Staff.BarRenderers[startNoteRenderer.Staff.BarRenderers.Count - 1]; endX = cx + endNoteRenderer.X + endNoteRenderer.Width; endY = cy + endNoteRenderer.Y + endNoteRenderer.Height; } else { endX = cx + endNoteRenderer.X + endNoteRenderer.GetBeatX(endBeat, BeatXPosition.MiddleNotes); // if the note stem is pointing towards the slur, we need to let it end on top of the stem. var endBeatHelper = endNoteRenderer.Helpers.GetBeamingHelperForBeat(endBeat); if (endBeatHelper.Direction == direction) { endY = cy + endNoteRenderer.Y + endNoteRenderer.CalculateBeamY(endBeatHelper, endX); } else { var note = direction == BeamDirection.Down ? endBeat.MinNote : endBeat.MaxNote; endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(note); } } var height = (endX - startX) * Renderer.Settings.SlurHeightFactor; TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, direction == BeamDirection.Down, height); canvas.Fill(); } }
public override void Paint(float cx, float cy, ICanvas canvas) { // only render slur once per staff var slurId = "tab.slur." + _startNote.SlurOrigin.Beat.Id + "." + _startNote.SlurOrigin.SlurDestination.Beat.Id; var renderer = (TabBarRenderer)Renderer; var isSlurRendered = renderer.Staff.GetSharedLayoutData(slurId, false); if (!isSlurRendered) { renderer.Staff.SetSharedLayoutData(slurId, true); var startNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <BarRendererBase>(Renderer.Staff.StaveId, _startNote.Beat.Voice.Bar); var direction = GetBeamDirection(_startNote); var startX = cx + startNoteRenderer.X; var startY = cy + startNoteRenderer.Y + startNoteRenderer.GetNoteY(_startNote, true); if (direction == BeamDirection.Down) { startY += renderer.GetTabY(1); } if (_startNote.SlurOrigin.Id == _startNote.Id) { startX += startNoteRenderer.GetBeatX(_startNote.Beat, BeatXPosition.MiddleNotes); } var endNote = _startNote.SlurOrigin.SlurDestination; var endNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <BarRendererBase>(Renderer.Staff.StaveId, endNote.Beat.Voice.Bar); float endX; float endY = startY; if (endNoteRenderer == null || startNoteRenderer.Staff != endNoteRenderer.Staff) { endNoteRenderer = startNoteRenderer.Staff.BarRenderers[startNoteRenderer.Staff.BarRenderers.Count - 1]; endX = cx + endNoteRenderer.X + endNoteRenderer.Width; } else { endX = cx + endNoteRenderer.X + endNoteRenderer.GetBeatX(endNote.Beat, BeatXPosition.MiddleNotes); } TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, direction == BeamDirection.Down); canvas.Fill(); } }
public override void Paint(float cx, float cy, ICanvas canvas) { if (_isOpen) { TieGlyph.PaintTie(canvas, Scale, cx + X + Width, cy + Y + Height, cx + X + Width, cy + Y, false, Size, 3); } else { TieGlyph.PaintTie(canvas, Scale, cx + X, cy + Y, cx + X, cy + Y + Height, false, Size, 3); } canvas.Fill(); }
public override void Paint(float cx, float cy, ICanvas canvas) { var beat = _beat; switch (beat.WhammyBarType) { case WhammyType.None: case WhammyType.Custom: return; } var whammyMode = Renderer.Settings.DisplayMode; var startNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <ScoreBarRenderer>(Renderer.Staff.StaveId, beat.Voice.Bar); var startX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(beat, BeatXPosition.MiddleNotes); var beatDirection = GetBeamDirection(beat, startNoteRenderer); var direction = _beat.Notes.Count == 1 ? beatDirection : BeamDirection.Up; var textalign = canvas.TextAlign; for (var i = 0; i < beat.Notes.Count; i++) { var note = beat.Notes[i]; var startY = cy + startNoteRenderer.Y + startNoteRenderer.GetNoteY(note, true); if (direction == BeamDirection.Down) { startY += NoteHeadGlyph.NoteHeadHeight * Scale; } if (i > 0 && i >= _beat.Notes.Count / 2) { direction = BeamDirection.Down; } var endX = cx + startNoteRenderer.X; if (beat.IsLastOfVoice) { endX += startNoteRenderer.Width; } else { endX += startNoteRenderer.GetBeatX(beat, BeatXPosition.EndBeat); } endX -= EndPadding * Scale; var slurText = beat.WhammyStyle == BendStyle.Gradual && i == 0 ? "grad." : ""; ScoreBarRenderer endNoteRenderer = null; if (note.IsTieOrigin) { endNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <ScoreBarRenderer>(Renderer.Staff.StaveId, note.TieDestination.Beat.Voice.Bar); if (endNoteRenderer != null && endNoteRenderer.Staff == startNoteRenderer.Staff) { endX = cx + endNoteRenderer.X + endNoteRenderer.GetBeatX(note.TieDestination.Beat, BeatXPosition.MiddleNotes); } else { endNoteRenderer = null; } } var heightOffset = (NoteHeadGlyph.NoteHeadHeight * Scale * NoteHeadGlyph.GraceScale) * 0.5f; if (direction == BeamDirection.Up) { heightOffset = -heightOffset; } int endValue; float endY; switch (beat.WhammyBarType) { case WhammyType.Hold: if (note.IsTieOrigin) { if (endNoteRenderer == null) { endY = startY; } else { endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(note.TieDestination, true); } TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, beatDirection == BeamDirection.Down); canvas.Fill(); } break; case WhammyType.Dive: if (i == 0) { _bendNoteHeads[0].X = endX - _bendNoteHeads[0].NoteHeadOffset; _bendNoteHeads[0].Y = cy + startNoteRenderer.Y; _bendNoteHeads[0].Paint(0, 0, canvas); } endValue = GetBendNoteValue(note, beat.WhammyBarPoints[beat.WhammyBarPoints.Count - 1]); if (_bendNoteHeads[0].ContainsNoteValue(endValue)) { endY = _bendNoteHeads[0].GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, startX, startY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } else if (endNoteRenderer != null && (note.IsTieOrigin && note.TieDestination.Beat.HasWhammyBar || (note.Beat.IsContinuedWhammy))) { endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(note.TieDestination, true); DrawBendSlur(canvas, startX, startY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } else if (note.IsTieOrigin) { if (endNoteRenderer == null) { endY = startY; } else { endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(note.TieDestination, true); } TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, beatDirection == BeamDirection.Down); canvas.Fill(); } break; case WhammyType.Dip: if (whammyMode == DisplayMode.SongBook) { if (i == 0) { var simpleStartX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(_beat, BeatXPosition.OnNotes) - SimpleDipPadding * Scale; var simpleEndX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(_beat, BeatXPosition.PostNotes) + SimpleDipPadding * Scale; var middleX = (simpleStartX + simpleEndX) / 2; var text = ((_beat.WhammyBarPoints[1].Value - _beat.WhammyBarPoints[0].Value) / 4) .ToString(); canvas.Font = Renderer.Resources.TablatureFont; canvas.FillText(text, middleX, cy + Y); var simpleStartY = cy + Y + canvas.Font.Size + 2 * Scale; var simpleEndY = simpleStartY + SimpleDipHeight * Scale; if (_beat.WhammyBarPoints[1].Value > _beat.WhammyBarPoints[0].Value) { canvas.MoveTo(simpleStartX, simpleEndY); canvas.LineTo(middleX, simpleStartY); canvas.LineTo(simpleEndX, simpleEndY); } else { canvas.MoveTo(simpleStartX, simpleStartY); canvas.LineTo(middleX, simpleEndY); canvas.LineTo(simpleEndX, simpleStartY); } canvas.Stroke(); } if (note.IsTieOrigin) { if (endNoteRenderer == null) { endY = startY; } else { endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(note.TieDestination, true); } TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, beatDirection == BeamDirection.Down); canvas.Fill(); } } else { var middleX = (startX + endX) / 2; _bendNoteHeads[0].X = middleX - _bendNoteHeads[0].NoteHeadOffset; _bendNoteHeads[0].Y = cy + startNoteRenderer.Y; _bendNoteHeads[0].Paint(0, 0, canvas); var middleValue = GetBendNoteValue(note, beat.WhammyBarPoints[1]); var middleY = _bendNoteHeads[0].GetNoteValueY(middleValue) + heightOffset; DrawBendSlur(canvas, startX, startY, middleX, middleY, direction == BeamDirection.Down, Scale, slurText); _bendNoteHeads[1].X = endX - _bendNoteHeads[1].NoteHeadOffset; _bendNoteHeads[1].Y = cy + startNoteRenderer.Y; _bendNoteHeads[1].Paint(0, 0, canvas); endValue = GetBendNoteValue(note, beat.WhammyBarPoints[beat.WhammyBarPoints.Count - 1]); endY = _bendNoteHeads[1].GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, middleX, middleY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } break; case WhammyType.PrediveDive: case WhammyType.Predive: var preX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(note.Beat, BeatXPosition.PreNotes); preX += ((ScoreBeatPreNotesGlyph)startNoteRenderer.GetBeatContainer(note.Beat).PreNotes) .PrebendNoteHeadOffset; var preY = cy + startNoteRenderer.Y + startNoteRenderer.GetScoreY(startNoteRenderer.AccidentalHelper.GetNoteLineForValue(note.DisplayValue - note.Beat.WhammyBarPoints[0].Value / 2)) + heightOffset; DrawBendSlur(canvas, preX, preY, startX, startY, direction == BeamDirection.Down, Scale, slurText); if (_bendNoteHeads.Count > 0) { _bendNoteHeads[0].X = endX - _bendNoteHeads[0].NoteHeadOffset; _bendNoteHeads[0].Y = cy + startNoteRenderer.Y; _bendNoteHeads[0].Paint(0, 0, canvas); endValue = GetBendNoteValue(note, beat.WhammyBarPoints[beat.WhammyBarPoints.Count - 1]); endY = _bendNoteHeads[0].GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, startX, startY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } break; } } canvas.TextAlign = textalign; }
public override void Paint(float cx, float cy, ICanvas canvas) { // Draw note heads var startNoteRenderer = Renderer.ScoreRenderer.Layout.GetRendererForBar <ScoreBarRenderer>(Renderer.Staff.StaveId, _beat.Voice.Bar); var startX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(_beat, BeatXPosition.MiddleNotes); var endBeatX = cx + startNoteRenderer.X; if (_beat.IsLastOfVoice) { endBeatX += startNoteRenderer.PostBeatGlyphsStart; } else { endBeatX += startNoteRenderer.GetBeatX(_beat.NextBeat, BeatXPosition.PreNotes); } endBeatX -= EndPadding * Scale; var middleX = (startX + endBeatX) / 2; if (_middleNoteGlyph != null) { _middleNoteGlyph.X = middleX - _middleNoteGlyph.NoteHeadOffset; _middleNoteGlyph.Y = cy + startNoteRenderer.Y; _middleNoteGlyph.Paint(0, 0, canvas); } if (_endNoteGlyph != null) { _endNoteGlyph.X = endBeatX - _endNoteGlyph.NoteHeadOffset; _endNoteGlyph.Y = cy + startNoteRenderer.Y; _endNoteGlyph.Paint(0, 0, canvas); } _notes.Sort((a, b) => b.DisplayValue - a.DisplayValue); var directionBeat = _beat.GraceType == GraceType.BendGrace ? _beat.NextBeat : _beat; var direction = _notes.Count == 1 ? GetBeamDirection(directionBeat, startNoteRenderer) : BeamDirection.Up; // draw slurs for (var i = 0; i < _notes.Count; i++) { var note = _notes[i]; if (i > 0 && i >= _notes.Count / 2) { direction = BeamDirection.Down; } var startY = cy + startNoteRenderer.Y + startNoteRenderer.GetNoteY(note, true); var heightOffset = (NoteHeadGlyph.NoteHeadHeight * Scale * NoteHeadGlyph.GraceScale) * 0.5f; if (direction == BeamDirection.Down) { startY += NoteHeadGlyph.NoteHeadHeight * Scale; } var slurText = note.BendStyle == BendStyle.Gradual ? "grad." : ""; if (note.IsTieOrigin) { var endNote = note.TieDestination; var endNoteRenderer = endNote == null ? null : Renderer.ScoreRenderer.Layout.GetRendererForBar <ScoreBarRenderer>(Renderer.Staff.StaveId, endNote.Beat.Voice.Bar); // if we have a line break we draw only a line until the end if (endNoteRenderer == null || endNoteRenderer.Staff != startNoteRenderer.Staff) { var endX = cx + startNoteRenderer.X + startNoteRenderer.Width; var noteValueToDraw = note.TieDestination.RealValue; var accidental = startNoteRenderer.AccidentalHelper.ApplyAccidentalForValue(note.Beat, noteValueToDraw, false); var endY = cy + startNoteRenderer.Y + startNoteRenderer.GetScoreY( startNoteRenderer.AccidentalHelper.GetNoteLineForValue(noteValueToDraw)); if (note.BendType == BendType.Hold || note.BendType == BendType.Prebend) { TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, direction == BeamDirection.Down); canvas.Fill(); } else { DrawBendSlur(canvas, startX, startY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } } // otherwise we draw a line to the target note else { var endX = cx + endNoteRenderer.X + endNoteRenderer.GetBeatX(endNote.Beat, BeatXPosition.MiddleNotes); var endY = cy + endNoteRenderer.Y + endNoteRenderer.GetNoteY(endNote, true); if (direction == BeamDirection.Down) { endY += NoteHeadGlyph.NoteHeadHeight * Scale; } if (note.BendType == BendType.Hold || note.BendType == BendType.Prebend) { TieGlyph.PaintTie(canvas, Scale, startX, startY, endX, endY, direction == BeamDirection.Down); canvas.Fill(); } else { DrawBendSlur(canvas, startX, startY, endX, endY, direction == BeamDirection.Down, Scale, slurText); } } switch (note.BendType) { case BendType.Prebend: case BendType.PrebendBend: case BendType.PrebendRelease: var preX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(note.Beat, BeatXPosition.PreNotes); preX += ((ScoreBeatPreNotesGlyph)startNoteRenderer.GetBeatContainer(note.Beat).PreNotes) .PrebendNoteHeadOffset; var preY = cy + startNoteRenderer.Y + startNoteRenderer.GetScoreY( startNoteRenderer.AccidentalHelper.GetNoteLineForValue(note.DisplayValue - note.BendPoints[0].Value / 2)) + heightOffset; DrawBendSlur(canvas, preX, preY, startX, startY, direction == BeamDirection.Down, Scale); break; } } else { if (direction == BeamDirection.Up) { heightOffset = -heightOffset; } int endValue; float endY; switch (note.BendType) { case BendType.Bend: endValue = GetBendNoteValue(note, note.BendPoints[note.BendPoints.Count - 1]); endY = _endNoteGlyph.GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, startX, startY, endBeatX, endY, direction == BeamDirection.Down, Scale, slurText); break; case BendType.BendRelease: var middleValue = GetBendNoteValue(note, note.BendPoints[1]); var middleY = _middleNoteGlyph.GetNoteValueY(middleValue) + heightOffset; DrawBendSlur(canvas, startX, startY, middleX, middleY, direction == BeamDirection.Down, Scale, slurText); endValue = GetBendNoteValue(note, note.BendPoints[note.BendPoints.Count - 1]); endY = _endNoteGlyph.GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, middleX, middleY, endBeatX, endY, direction == BeamDirection.Down, Scale, slurText); break; case BendType.Release: if (_bendNoteHeads.Count > 0) { endValue = GetBendNoteValue(note, note.BendPoints[note.BendPoints.Count - 1]); endY = _bendNoteHeads[0].GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, startX, startY, endBeatX, endY, direction == BeamDirection.Down, Scale, slurText); } break; case BendType.Prebend: case BendType.PrebendBend: case BendType.PrebendRelease: var preX = cx + startNoteRenderer.X + startNoteRenderer.GetBeatX(note.Beat, BeatXPosition.PreNotes); preX += ((ScoreBeatPreNotesGlyph)startNoteRenderer.GetBeatContainer(note.Beat).PreNotes) .PrebendNoteHeadOffset; var preY = cy + startNoteRenderer.Y + startNoteRenderer.GetScoreY( startNoteRenderer.AccidentalHelper.GetNoteLineForValue(note.DisplayValue - note.BendPoints[0].Value / 2)) + heightOffset; DrawBendSlur(canvas, preX, preY, startX, startY, direction == BeamDirection.Down, Scale); if (_bendNoteHeads.Count > 0) { endValue = GetBendNoteValue(note, note.BendPoints[note.BendPoints.Count - 1]); endY = _bendNoteHeads[0].GetNoteValueY(endValue) + heightOffset; DrawBendSlur(canvas, startX, startY, endBeatX, endY, direction == BeamDirection.Down, Scale, slurText); } break; } } } }