public override async Task Render() { var firstBeat = this.Element.GetFirstBeat(); var lastBeat = this.Element.GetLastBeat(); var firstBeatRenderer = this.Root.GetRenderer <Beat, BeatRenderer>(firstBeat); var lastBeatRenderrer = this.Root.GetRenderer <Beat, BeatRenderer>(lastBeat); var x0 = firstBeatRenderer.GetNoteRenderingPosition(); var x1 = lastBeatRenderrer.GetNoteRenderingPosition(); var beamSlope = this.RenderingContext.GetBeamSlope(this.Element); if (beamSlope == null) { var beamOffset = await this.CalculateBeamOffset(); var y0 = firstBeatRenderer.GetStemTailPosition() + beamOffset; var y1 = lastBeatRenderrer.GetStemTailPosition() + beamOffset; beamSlope = new BeamSlope(x0, y0, (y1 - y0) / (x1 - x0)); this.RenderingContext.SetBeamSlope(this.Element, beamSlope); } // beam must be rendered first, so the height map will be updated correctly await this.RenderingContext.DrawBeam(this.Element.BeatNoteValue, x0, beamSlope.GetY(x0), x1, beamSlope.GetY(x1), this.Element.GetStemRenderVoicePart()); foreach (var renderer in _beatElementRenderers) { await renderer.Render(); } if (this.Element.Tuplet != null) { if (this.Element.IsRoot || this.Element.RootBeam.Tuplet != this.Element.Tuplet) { var tupletX = (x1 + x0) / 2; await this.RenderingContext.DrawTuplet(this.Element.Tuplet.Value, tupletX, this.Element.GetStemRenderVoicePart()); } } }
/// <remarks> /// <para>beat</para> could be different than <c>this.OwnerBeat</c> because we may draw for tied beats /// </remarks> public async Task Render(BeamSlope beamSlope) { var x = this.OwnerBeat.GetNoteRenderingPosition(this.Element.String); var flags = this.GetNoteRenderingFlags(); Rect bounds; if (this.Element.EffectTechnique == NoteEffectTechnique.DeadNote) { bounds = await this.RenderingContext.Owner.DrawNoteFretting(this.Element.String, "dead", x, flags); } else if (this.Element.Fret == BeatNote.UnspecifiedFret) { bounds = await this.RenderingContext.Owner.DrawNoteFretting(this.Element.String, "asChord", x, flags); } else { bounds = await this.RenderingContext.Owner.DrawNoteFretting(this.Element.String, this.Element.Fret.ToString(), x, flags); } if (!this.IsTied && this.Element.EffectTechnique == NoteEffectTechnique.ArtificialHarmonic) { this.RenderingContext.AddArtificialHarmonic(this.Element.String, this.Element.Fret, this.Element.EffectTechniqueParameter == null ? this.Element.Fret + 12 : (int)this.Element.EffectTechniqueParameter); } this.RenderingContext.Owner.SetNoteBoundingBox(this.OwnerBeat.Element.OwnerColumn.ColumnIndex, this.Element.String, bounds); if (this.OwnerBeat.Element.NoteValue.Augment != NoteValueAugment.None) { var spaceOffset = this.OwnerBeat.Element.GetStemRenderVoicePart() == VoicePart.Treble ? 0 : 1; this.RenderingContext.Owner.DrawNoteValueAugment(this.OwnerBeat.Element.NoteValue, bounds.Right - this.RenderingContext.Owner.Location.X, this.Element.String + spaceOffset); } if (this.IsTied) { var tiePosition = this.Element.TiePosition ?? this.OwnerBeat.Element.GetRenderTiePosition(); if (this.OwnerBeat.Element.IsTied) { await NoteConnectionRenderer.DrawTie(this.Root, this.OwnerBeat.Element.PreviousBeat, this.OwnerBeat.Element, this.Element.String, tiePosition); } else { Debug.Assert(this.OwnerBeat.Element == this.Element.OwnerBeat); if (this.Element.IsTied) { await NoteConnectionRenderer.DrawTie(this.Root, this.Element.PreConnectedNote?.OwnerBeat, this.OwnerBeat.Element, this.Element.String, tiePosition); } else { var preConnection = this.Element.PreConnection == PreNoteConnection.None ? (NoteConnection)this.Element.OwnerBeat.PreConnection : (NoteConnection)this.Element.PreConnection; if (preConnection != NoteConnection.None) { await this.RenderingContext.DrawConnection(this.Root, preConnection, this.Element.PreConnectedNote?.OwnerBeat, this.OwnerBeat.Element, this.Element.String, tiePosition); } } var postConnection = this.Element.PostConnection == PostNoteConnection.None ? (NoteConnection)this.Element.OwnerBeat.PostConnection : (NoteConnection)this.Element.PostConnection; if (postConnection != NoteConnection.None) { await this.RenderingContext.DrawConnection(this.Root, postConnection, this.OwnerBeat.Element, null, this.Element.String, tiePosition); } } } }
private async Task DrawSemiBeam(BaseNoteValue noteValue, VoicePart voicePart, BeamSlope beamSlope, bool isLastOfBeam) { BeatRenderer beatRenderer1, beatRenderer2; if (isLastOfBeam) { beatRenderer1 = this.Root.GetRenderer <Beat, BeatRenderer>(this.Element.PreviousBeat); beatRenderer2 = this; } else { beatRenderer1 = this; beatRenderer2 = this.Root.GetRenderer <Beat, BeatRenderer>(this.Element.NextBeat); } var position1 = beatRenderer1.GetStemPosition(); var position2 = beatRenderer2.GetStemPosition(); var beamWidth = Math.Min(this.RenderingContext.Style.MaximumSemiBeamWidth, (position2 - position1) / 2); double x0, x1; if (isLastOfBeam) { x0 = position2 - beamWidth; x1 = position2; } else { x0 = position1; x1 = position1 + beamWidth; } await this.RenderingContext.DrawBeam(noteValue, x0, beamSlope.GetY(x0), x1, beamSlope.GetY(x1), voicePart); }
public void SetBeamSlope(Beam beam, BeamSlope slope) { _beamSlopes[beam] = slope; }