private void DrawSlideNote(RenderContext context, double now, Note note)
        {
            if (note.FlickType != NoteFlickType.None)
            {
                DrawFlickNote(context, now, note);
                return;
            }

            float x, y, r;

            if (note.IsSlideEnd || NotesLayerUtils.IsNoteOnStage(note, now))
            {
                x = NotesLayerUtils.GetNoteXPosition(context, now, note);
                y = NotesLayerUtils.GetNoteYPosition(context, now, note);
                r = NotesLayerUtils.GetNoteRadius(now, note);
            }
            else if (NotesLayerUtils.IsNotePassed(note, now))
            {
                if (!note.HasNextFlickOrSlide || NotesLayerUtils.IsNotePassed(note.NextFlickOrSlide, now))
                {
                    return;
                }
                var nextSlideNote = note.NextFlickOrSlide;
                if (nextSlideNote == null)
                {
                    // Actually, here is an example of invalid format. :)
                    DrawTapNote(context, now, note);
                    return;
                }
                else
                {
                    var startX = NotesLayerUtils.GetEndXByNotePosition(context.ClientSize, note.FinishPosition);
                    var endX   = NotesLayerUtils.GetEndXByNotePosition(context.ClientSize, nextSlideNote.FinishPosition);
                    y = NotesLayerUtils.GetAvatarYPosition(context.ClientSize);
                    x = (float)((now - note.HitTiming) / (nextSlideNote.HitTiming - note.HitTiming)) * (endX - startX) + startX;
                    r = Definitions.AvatarCircleRadius;
                }
            }
            else
            {
                return;
            }

            DrawNoteImage(context, note, x, y, r);
        }
 private void DrawSlideRibbon(RenderContext context, double now, Note startNote, Note endNote)
 {
     if (endNote.IsFlick)
     {
         DrawFlickRibbon(context, now, startNote, endNote);
         return;
     }
     if (startNote.IsSlideEnd || NotesLayerUtils.IsNoteOnStage(startNote, now))
     {
         DrawHoldRibbon(context, now, startNote, endNote);
         return;
     }
     if (NotesLayerUtils.IsNotePassed(startNote, now))
     {
         var nextSlideNote = startNote.NextFlickOrSlide;
         if (nextSlideNote == null)
         {
             // Actually, here is an example of invalid format. :)
             DrawHoldRibbon(context, now, startNote, endNote);
             return;
         }
         if (NotesLayerUtils.IsNotePassed(nextSlideNote, now))
         {
             return;
         }
         var   startX = NotesLayerUtils.GetEndXByNotePosition(context.ClientSize, startNote.FinishPosition);
         var   endX   = NotesLayerUtils.GetEndXByNotePosition(context.ClientSize, nextSlideNote.FinishPosition);
         var   y1     = NotesLayerUtils.GetAvatarYPosition(context.ClientSize);
         var   x1     = (float)((now - startNote.HitTiming) / (nextSlideNote.HitTiming - startNote.HitTiming)) * (endX - startX) + startX;
         float t1     = NotesLayerUtils.GetNoteTransformedTime(now, startNote, clampComing: true, clampPassed: true);
         float t2     = NotesLayerUtils.GetNoteTransformedTime(now, endNote, clampComing: true, clampPassed: true);
         float tmid   = (t1 + t2) * 0.5f;
         float x2     = NotesLayerUtils.GetNoteXPosition(context, endNote.FinishPosition, t2);
         float xmid   = NotesLayerUtils.GetNoteXPosition(context, endNote.FinishPosition, tmid);
         float y2     = NotesLayerUtils.GetNoteYPosition(context, t2);
         float ymid   = NotesLayerUtils.GetNoteYPosition(context, tmid);
         NotesLayerUtils.GetBezierFromQuadratic(x1, xmid, x2, out float xcontrol1, out float xcontrol2);
         NotesLayerUtils.GetBezierFromQuadratic(y1, ymid, y2, out float ycontrol1, out float ycontrol2);
         // TODO:
         //context.DrawBezier(ConnectionPen, x1, y1, xcontrol1, ycontrol1, xcontrol2, ycontrol2, x2, y2);
     }
 }