This public class helps drawing beams and bars for notes.
예제 #1
0
 private void PaintBeamHelper(float cx, float cy, ICanvas canvas, BeamingHelper h)
 {
     if (h.Beats[0].GraceType != GraceType.None) return;
     var useBeams = Stave.GetSetting("use-beams", false);
     // check if we need to paint simple footer
     if (useBeams && h.Beats.Count == 1)
     {
         PaintFooter(cx, cy, canvas, h);
     }
     else
     {
         PaintBar(cx, cy, canvas, h);
     }
 }
예제 #2
0
        public BarHelpers(Bar bar)
        {
            BeamHelpers      = new FastList <FastList <BeamingHelper> >();
            BeamHelperLookup = new FastList <FastDictionary <int, BeamingHelper> >();
            TupletHelpers    = new FastList <FastList <TupletHelper> >();

            BeamingHelper currentBeamHelper   = null;
            TupletHelper  currentTupletHelper = null;

            if (bar != null)
            {
                for (int i = 0, j = bar.Voices.Count; i < j; i++)
                {
                    var v = bar.Voices[i];
                    BeamHelpers.Add(new FastList <BeamingHelper>());
                    BeamHelperLookup.Add(new FastDictionary <int, BeamingHelper>());
                    TupletHelpers.Add(new FastList <TupletHelper>());

                    for (int k = 0, l = v.Beats.Count; k < l; k++)
                    {
                        var b = v.Beats[k];
                        var forceNewTupletHelper = false;

                        // if a new beaming helper was started, we close our tuplet grouping as well
                        if (!b.IsRest)
                        {
                            // try to fit beam to current beamhelper
                            if (currentBeamHelper == null || !currentBeamHelper.CheckBeat(b))
                            {
                                if (currentBeamHelper != null)
                                {
                                    currentBeamHelper.Finish();
                                    forceNewTupletHelper = currentBeamHelper.Beats.Count > 1;
                                }
                                else
                                {
                                    forceNewTupletHelper = true;
                                }
                                // if not possible, create the next beaming helper
                                currentBeamHelper = new BeamingHelper(bar.Staff);
                                currentBeamHelper.CheckBeat(b);
                                BeamHelpers[v.Index].Add(currentBeamHelper);
                            }
                        }

                        if (b.HasTuplet)
                        {
                            // try to fit tuplet to current tuplethelper
                            // TODO: register tuplet overflow
                            var previousBeat = b.PreviousBeat;

                            // don't group if the previous beat isn't in the same voice
                            if (previousBeat != null && previousBeat.Voice != b.Voice)
                            {
                                previousBeat = null;
                            }

                            // if a new beaming helper was started, we close our tuplet grouping as well
                            if (forceNewTupletHelper && currentTupletHelper != null)
                            {
                                currentTupletHelper.Finish();
                            }

                            if (previousBeat == null || currentTupletHelper == null || !currentTupletHelper.Check(b))
                            {
                                currentTupletHelper = new TupletHelper(v.Index);
                                currentTupletHelper.Check(b);
                                TupletHelpers[v.Index].Add(currentTupletHelper);
                            }
                        }

                        BeamHelperLookup[v.Index][b.Index] = currentBeamHelper;
                    }

                    if (currentBeamHelper != null)
                    {
                        currentBeamHelper.Finish();
                    }

                    if (currentTupletHelper != null)
                    {
                        currentTupletHelper.Finish();
                    }

                    currentBeamHelper   = null;
                    currentTupletHelper = null;
                }
            }
        }
예제 #3
0
        private void PaintFooter(float cx, float cy, ICanvas canvas, BeamingHelper h)
        {
            var beat = h.Beats[0];

            var isGrace = beat.GraceType != GraceType.None;
            var scaleMod = isGrace ? NoteHeadGlyph.GraceScale : 1;

            //
            // draw line
            //

            var stemSize = GetFooterStemSize(h.ShortestDuration);

            var beatLineX = h.GetBeatLineX(beat) + Scale;

            var direction = h.Direction;

            var topY = GetScoreY(GetNoteLine(beat.MaxNote));
            var bottomY = GetScoreY(GetNoteLine(beat.MinNote));
            float beamY;
            float fingeringY;
            if (direction == BeamDirection.Down)
            {
                bottomY += stemSize * scaleMod;
                beamY = bottomY;
                fingeringY = cy + Y + bottomY;
            }
            else
            {
                topY -= stemSize * scaleMod;
                beamY = topY;
                fingeringY = cy + Y + topY;
            }

            PaintFingering(canvas, beat, cx + X + beatLineX, direction, fingeringY);

            if (beat.Duration == Duration.Whole || beat.Duration == Duration.DoubleWhole)
            {
                return;
            }

            canvas.BeginPath();
            canvas.MoveTo(cx + X + beatLineX, cy + Y + topY);
            canvas.LineTo(cx + X + beatLineX, cy + Y + bottomY);
            canvas.Stroke();

            if (isGrace)
            {
                var graceSizeY = 15 * Scale;
                var graceSizeX = 12 * Scale;

                canvas.BeginPath();
                if (direction == BeamDirection.Down)
                {
                    canvas.MoveTo(cx + X + beatLineX - (graceSizeX / 2), cy + Y + bottomY - graceSizeY);
                    canvas.LineTo(cx + X + beatLineX + (graceSizeX / 2), cy + Y + bottomY);
                }
                else
                {
                    canvas.MoveTo(cx + X + beatLineX - (graceSizeX / 2), cy + Y + topY + graceSizeY);
                    canvas.LineTo(cx + X + beatLineX + (graceSizeX / 2), cy + Y + topY);
                }
                canvas.Stroke();
            }

            //
            // Draw beam
            //
            if (beat.Duration > Duration.Quarter)
            {
                var glyph = new BeamGlyph(beatLineX - Scale / 2f, beamY, beat.Duration, direction, isGrace);
                glyph.Renderer = this;
                glyph.DoLayout();
                glyph.Paint(cx + X, cy + Y, canvas);
            }
        }
예제 #4
0
        private void PaintBeamHelper(float cx, float cy, ICanvas canvas, BeamingHelper h)
        {
            canvas.Color = h.Voice.Index == 0
                ? Resources.MainGlyphColor
                : Resources.SecondaryGlyphColor;

            // check if we need to paint simple footer
            if (h.Beats.Count == 1)
            {
                PaintFooter(cx, cy, canvas, h);
            }
            else
            {
                PaintBar(cx, cy, canvas, h);
            }
        }
예제 #5
0
        private void PaintBar(float cx, float cy, ICanvas canvas, BeamingHelper h)
        {
            for (int i = 0, j = h.Beats.Count; i < j; i++)
            {
                var beat = h.Beats[i];

                //
                // draw line
                //
                var beatLineX = h.GetBeatLineX(beat) + Scale;

                var direction = h.Direction;

                var y1 = cy + Y + (direction == BeamDirection.Up
                            ? GetScoreY(GetNoteLine(beat.MinNote))
                            : GetScoreY(GetNoteLine(beat.MaxNote)));

                var y2 = cy + Y + CalculateBeamY(h, beatLineX);

                canvas.BeginPath();
                canvas.MoveTo(cx + X + beatLineX, y1);
                canvas.LineTo(cx + X + beatLineX, y2);
                canvas.Stroke();

                float fingeringY = y2;
                if (direction == BeamDirection.Down)
                {
                    fingeringY += canvas.Font.Size * 2f;
                }
                else if (i != 0)
                {
                    fingeringY -= canvas.Font.Size * 1.5f;
                }
                PaintFingering(canvas, beat, cx + X + beatLineX, direction, fingeringY);

                var brokenBarOffset = 6 * Scale;
                var barSpacing = 6 * Scale;
                var barSize = 3 * Scale;
                var barCount = beat.Duration.GetIndex() - 2;
                var barStart = cy + Y;
                if (direction == BeamDirection.Down)
                {
                    barSpacing = -barSpacing;
                    barSize = -barSize;
                }

                for (var barIndex = 0; barIndex < barCount; barIndex++)
                {
                    float barStartX;
                    float barEndX;

                    float barStartY;
                    float barEndY;

                    var barY = barStart + (barIndex * barSpacing);

                    //
                    // Bar to Next?
                    //
                    if (i < h.Beats.Count - 1)
                    {
                        // full bar?
                        if (IsFullBarJoin(beat, h.Beats[i + 1], barIndex))
                        {
                            barStartX = beatLineX;
                            barEndX = h.GetBeatLineX(h.Beats[i + 1]) + Scale;
                        }
                        // broken bar?
                        else if (i == 0 || !IsFullBarJoin(h.Beats[i - 1], beat, barIndex))
                        {
                            barStartX = beatLineX;
                            barEndX = barStartX + brokenBarOffset;
                        }
                        else
                        {
                            continue;
                        }
                        barStartY = barY + CalculateBeamY(h, barStartX);
                        barEndY = barY + CalculateBeamY(h, barEndX);
                        PaintSingleBar(canvas, cx + X + barStartX, barStartY, cx + X + barEndX, barEndY, barSize);
                    }
                    //
                    // Broken Bar to Previous?
                    //
                    else if (i > 0 && !IsFullBarJoin(beat, h.Beats[i - 1], barIndex))
                    {
                        barStartX = beatLineX - brokenBarOffset;
                        barEndX = beatLineX;

                        barStartY = barY + CalculateBeamY(h, barStartX);
                        barEndY = barY + CalculateBeamY(h, barEndX);

                        PaintSingleBar(canvas, cx + X + barStartX, barStartY, cx + X + barEndX, barEndY, barSize);
                    }
                }
            }
        }
예제 #6
0
 private float GetStemSize(BeamingHelper helper)
 {
     return helper.Beats.Count == 1
         ? GetFooterStemSize(helper.ShortestDuration)
         : GetBarStemSize(helper.ShortestDuration);
 }
예제 #7
0
 private float CalculateBeamY(BeamingHelper h, float x)
 {
     var stemSize = GetStemSize(h);
     return h.CalculateBeamY(stemSize, Scale, x, Scale, n => GetScoreY(GetNoteLine(n)));
 }
예제 #8
0
 private float CalculateBeamY(BeamingHelper h, float x)
 {
     var correction = NoteHeadGlyph.NoteHeadHeight / 2;
     var stemSize = GetStemSize(h.MaxDuration);
     return h.CalculateBeamY(stemSize, Scale, x, Scale, n => GetScoreY(GetNoteLine(n), correction - 1));
 }
예제 #9
0
 private void PaintBeamHelper(float cx, float cy, ICanvas canvas, BeamingHelper h)
 {
     // check if we need to paint simple footer
     if (h.Beats.Count == 1)
     {
         PaintFooter(cx, cy, canvas, h);
     }
     else
     {
         PaintBar(cx, cy, canvas, h);
     }
 }
예제 #10
0
        public BarHelpers(Bar bar)
        {
            BeamHelpers = new FastList<FastList<BeamingHelper>>();
            BeamHelperLookup = new FastList<FastDictionary<int, BeamingHelper>>();
            TupletHelpers = new FastList<FastList<TupletHelper>>();

            BeamingHelper currentBeamHelper = null;
            TupletHelper currentTupletHelper = null;

            for (int i = 0, j = bar.Voices.Count; i < j; i++)
            {
                var v = bar.Voices[i];
                BeamHelpers.Add(new FastList<BeamingHelper>());
                BeamHelperLookup.Add(new FastDictionary<int, BeamingHelper>());
                TupletHelpers.Add(new FastList<TupletHelper>());

                for (int k = 0, l = v.Beats.Count; k < l; k++)
                {
                    var b = v.Beats[k];
                    var newBeamingHelper = false;

                    if (!b.IsRest)
                    {
                        // try to fit beam to current beamhelper
                        if (currentBeamHelper == null || !currentBeamHelper.CheckBeat(b))
                        {
                            // if not possible, create the next beaming helper
                            currentBeamHelper = new BeamingHelper(bar.Track);
                            currentBeamHelper.CheckBeat(b);
                            BeamHelpers[v.Index].Add(currentBeamHelper);
                            newBeamingHelper = true;
                        }
                    }

                    if (b.HasTuplet)
                    {
                        // try to fit tuplet to current tuplethelper
                        // TODO: register tuplet overflow
                        var previousBeat = b.PreviousBeat;

                        // don't group if the previous beat isn't in the same voice
                        if (previousBeat != null && previousBeat.Voice != b.Voice) previousBeat = null;

                        // if a new beaming helper was started, we close our tuplet grouping as well
                        if (newBeamingHelper && currentTupletHelper != null)
                        {
                            currentTupletHelper.Finish();
                        }

                        if (previousBeat == null || currentTupletHelper == null || !currentTupletHelper.Check(b))
                        {
                            currentTupletHelper = new TupletHelper(v.Index);
                            currentTupletHelper.Check(b);
                            TupletHelpers[v.Index].Add(currentTupletHelper);
                        }
                    }

                    BeamHelperLookup[v.Index][b.Index] = currentBeamHelper;
                }

                currentBeamHelper = null;
                currentTupletHelper = null;
            }
        }
예제 #11
0
        private void PaintFooter(float cx, float cy, ICanvas canvas, BeamingHelper h)
        {
            var beat = h.Beats[0];

            if (beat.Duration == Duration.Whole || beat.Duration == Duration.DoubleWhole)
            {
                return;
            }

            //
            // draw line
            //

            var beatLineX = h.GetBeatLineX(beat) + Scale;

            const float topY = 0;
            var bottomY = Height;

            float beamY = _direction == BeamDirection.Down ? bottomY : topY;

            canvas.BeginPath();
            canvas.MoveTo(cx + X + beatLineX, cy + Y + topY);
            canvas.LineTo(cx + X + beatLineX, cy + Y + bottomY);
            canvas.Stroke();

            //
            // Draw beam
            //
            var glyph = new BeamGlyph(beatLineX, beamY, beat.Duration, _direction, false);
            glyph.Renderer = this;
            glyph.DoLayout();
            glyph.Paint(cx + X, cy + Y, canvas);
        }
예제 #12
0
        private void PaintBar(float cx, float cy, ICanvas canvas, BeamingHelper h)
        {
            for (int i = 0, j = h.Beats.Count; i < j; i++)
            {
                var beat = h.Beats[i];

                if (h.HasBeatLineX(beat))
                {
                    //
                    // draw line
                    //
                    var beatLineX = h.GetBeatLineX(beat) + Scale;

                    var y1 = cy + Y;
                    var y2 = cy + Y + Height;

                    canvas.BeginPath();
                    canvas.MoveTo(cx + X + beatLineX, y1);
                    canvas.LineTo(cx + X + beatLineX, y2);
                    canvas.Stroke();

                    var brokenBarOffset = (6 * Scale);
                    var barSpacing = (6 * Scale);
                    var barSize = (3 * Scale);
                    var barCount = beat.Duration.GetIndex() - 2;
                    var barStart = cy + Y;
                    if (_direction == BeamDirection.Down)
                    {
                        barSpacing = -barSpacing;
                        barStart += Height;
                    }

                    for (int barIndex = 0; barIndex < barCount; barIndex++)
                    {
                        float barStartX;
                        float barEndX;

                        float barStartY;
                        float barEndY;

                        var barY = barStart + (barIndex * barSpacing);

                        //
                        // Broken Bar to Next
                        //
                        if (h.Beats.Count == 1)
                        {
                            barStartX = beatLineX;
                            barEndX = beatLineX + brokenBarOffset;
                            barStartY = barY;
                            barEndY = barY;
                            PaintSingleBar(canvas, cx + X + barStartX, barStartY, cx + X + barEndX, barEndY, barSize);
                        }
                        //
                        // Bar to Next?
                        //
                        else if (i < h.Beats.Count - 1)
                        {
                            // full bar?
                            if (IsFullBarJoin(beat, h.Beats[i + 1], barIndex))
                            {
                                barStartX = beatLineX;
                                barEndX = h.GetBeatLineX(h.Beats[i + 1]) + Scale;
                            }
                            // broken bar?
                            else if (i == 0 || !IsFullBarJoin(h.Beats[i - 1], beat, barIndex))
                            {
                                barStartX = beatLineX;
                                barEndX = barStartX + brokenBarOffset;
                            }
                            else
                            {
                                continue;
                            }
                            barStartY = barY;
                            barEndY = barY;
                            PaintSingleBar(canvas, cx + X + barStartX, barStartY, cx + X + barEndX, barEndY, barSize);
                        }
                        //
                        // Broken Bar to Previous?
                        //
                        else if (i > 0 && !IsFullBarJoin(beat, h.Beats[i - 1], barIndex))
                        {
                            barStartX = beatLineX - brokenBarOffset;
                            barEndX = beatLineX;

                            barStartY = barY;
                            barEndY = barY;

                            PaintSingleBar(canvas, cx + X + barStartX, barStartY, cx + X + barEndX, barEndY, barSize);
                        }
                    }
                }
            }
        }
예제 #13
0
 private void PaintBeamHelper(float cx, float cy, ICanvas canvas, BeamingHelper h)
 {
     if (h.Beats[0].GraceType != GraceType.None) return;
     // check if we need to paint simple footer
     if (h.Beats.Count == 1)
     {
         PaintFooter(cx, cy, canvas, h);
     }
     else
     {
         PaintBar(cx, cy, canvas, h);
     }
 }