public ActiveEdge(GlyphEdge e, int offsetX, float start)
            {
                float dxDy = (e.X1 - e.X) / (e.Y1 - e.Y);

                Fdx       = dxDy;
                Fdy       = dxDy != 0.0f ? 1.0f / dxDy : 0.0f;
                Fx        = e.X + dxDy * (start - e.Y);
                Fx       -= offsetX;
                Direction = e.Invert ? 1.0f : -1.0f;
                Sy        = e.Y;
                Ey        = e.Y1;
            }
        public static void RenderGlyph(GlyphCanvas canvas, Glyph glyph, float scale, bool invertY = true)
        {
            if (scale == 0f)
            {
                return;
            }
            if (canvas.Width == 0 || canvas.Height == 0)
            {
                return;
            }

            GlyphVertex[] vertices = glyph.Vertices;

            var flatnessInPixels = 0.35f;

            Vector2[] windings = FlattenCurves(vertices, flatnessInPixels / scale, out int[] contourLengths);

            if (windings == null)
            {
                return;
            }

            float scaleX = scale;
            float scaleY = scale;

            if (invertY)
            {
                scaleY = -scaleY;
            }
            int n = contourLengths.Sum();

            var e = new GlyphEdge[n + 1];

            n = 0;
            var wOffset   = 0;
            var subSample = 1;

            for (var i = 0; i < contourLengths.Length; i++)
            {
                int j = contourLengths[i] - 1;
                for (var k = 0; k < contourLengths[i]; j = k++)
                {
                    int a = k;
                    int b = j;
                    if (windings[wOffset + j].Y == windings[wOffset + k].Y)
                    {
                        continue;
                    }
                    e[n].Invert = false;
                    if (invertY && windings[wOffset + j].Y > windings[wOffset + k].Y || !invertY && windings[wOffset + j].Y < windings[wOffset + k].Y)
                    {
                        e[n].Invert = true;
                        a           = j;
                        b           = k;
                    }

                    e[n].X  = windings[wOffset + a].X * scaleX;
                    e[n].Y  = windings[wOffset + a].Y * scaleY * subSample;
                    e[n].X1 = windings[wOffset + b].X * scaleX;
                    e[n].Y1 = windings[wOffset + b].Y * scaleY * subSample;
                    n++;
                }

                wOffset += contourLengths[i];
            }

            Array.Resize(ref e, n + 1); // todo

            QuickSortEdges(new Span <GlyphEdge>(e), n);

            // Insert Sort
            for (var i = 1; i < n; i++)
            {
                GlyphEdge t = e[i];
                int       j = i;
                while (j > 0)
                {
                    ref GlyphEdge b = ref e[j - 1];
                    if (!(t.Y < b.Y))
                    {
                        break;
                    }
                    e[j] = e[j - 1];
                    j--;
                }

                if (i != j)
                {
                    e[j] = t;
                }
            }