Exemplo n.º 1
0
        public static void GenerateMSDF(Bitmap <Color4b> output, Shape shape, Rectangle region, double range, Vector2 scale, Vector2 translate, double edgeThreshold)
        {
            int contourCount = shape.Contours.Count;

            int[] windings = new int[contourCount];

            for (int i = 0; i < shape.Contours.Count; i++)
            {
                windings[i] = shape.Contours[i].Winding;
            }

            int xStart = Math.Min(Math.Max(0, (int)region.Left), output.Width);
            int yStart = Math.Min(Math.Max(0, (int)region.Top), output.Height);
            int xEnd   = Math.Min(Math.Max(0, (int)region.Right), output.Width);
            int yEnd   = Math.Min(Math.Max(0, (int)region.Bottom), output.Height);

            MultiDistance[] contourSD = new MultiDistance[contourCount];

            for (int y = yStart; y < yEnd; y++)
            {
                int row = shape.InverseYAxis ? yEnd - (y - yStart) - 1 : y;
                for (int x = xStart; x < xEnd; x++)
                {
                    Vector2 p = (new Vector2(x, y) - region.Position - translate) / scale;
                    output[x, row] = new Color4b(EvaluateMSDF(shape, windings, contourSD, p, range), 255);
                }
            }
        }
Exemplo n.º 2
0
        static Color3 EvaluateMSDF(Shape shape, int[] windings, MultiDistance[] contourSD, Vector2 p, double range)
        {
            int contourCount = contourSD.Length;

            p += new Vector2(0.5f, 0.5f);

            EdgePoint sr = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };
            EdgePoint sg = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };
            EdgePoint sb = new EdgePoint {
                minDistance = new SignedDistance(-1e240, 1)
            };

            double d       = Math.Abs(SignedDistance.Infinite.distance);
            double negDist = -SignedDistance.Infinite.distance;
            double posDist = SignedDistance.Infinite.distance;
            int    winding = 0;

            for (int i = 0; i < contourCount; i++)
            {
                Contour   contour = shape.Contours[i];
                EdgePoint r       = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };
                EdgePoint g = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };
                EdgePoint b = new EdgePoint {
                    minDistance = new SignedDistance(-1e240, 1)
                };

                for (int j = 0; j < contour.Edges.Count; j++)
                {
                    EdgeSegment edge = contour.Edges[j];
                    double      param;

                    SignedDistance distance = edge.GetSignedDistance(p, out param);
                    if ((edge.Color & EdgeColor.Red) == EdgeColor.Red && distance < r.minDistance)
                    {
                        r.minDistance = distance;
                        r.nearEdge    = edge;
                        r.nearParam   = param;
                    }
                    if ((edge.Color & EdgeColor.Green) == EdgeColor.Green && distance < g.minDistance)
                    {
                        g.minDistance = distance;
                        g.nearEdge    = edge;
                        g.nearParam   = param;
                    }
                    if ((edge.Color & EdgeColor.Blue) == EdgeColor.Blue && distance < b.minDistance)
                    {
                        b.minDistance = distance;
                        b.nearEdge    = edge;
                        b.nearParam   = param;
                    }
                }

                if (r.minDistance < sr.minDistance)
                {
                    sr = r;
                }
                if (g.minDistance < sg.minDistance)
                {
                    sg = g;
                }
                if (b.minDistance < sb.minDistance)
                {
                    sb = b;
                }

                double medMinDistance = Math.Abs(Median(r.minDistance.distance, g.minDistance.distance, b.minDistance.distance));

                if (medMinDistance < d)
                {
                    d       = medMinDistance;
                    winding = -windings[i];
                }

                if (r.nearEdge != null)
                {
                    r.nearEdge.DistanceToPseudoDistance(ref r.minDistance, p, r.nearParam);
                }
                if (g.nearEdge != null)
                {
                    g.nearEdge.DistanceToPseudoDistance(ref g.minDistance, p, g.nearParam);
                }
                if (b.nearEdge != null)
                {
                    b.nearEdge.DistanceToPseudoDistance(ref b.minDistance, p, b.nearParam);
                }

                medMinDistance = Median(r.minDistance.distance, g.minDistance.distance, b.minDistance.distance);

                contourSD[i].r   = r.minDistance.distance;
                contourSD[i].g   = g.minDistance.distance;
                contourSD[i].b   = b.minDistance.distance;
                contourSD[i].med = medMinDistance;

                if (windings[i] > 0 && medMinDistance >= 0 && Math.Abs(medMinDistance) < Math.Abs(posDist))
                {
                    posDist = medMinDistance;
                }
                if (windings[i] < 0 && medMinDistance <= 0 && Math.Abs(medMinDistance) < Math.Abs(negDist))
                {
                    negDist = medMinDistance;
                }
            }

            if (sr.nearEdge != null)
            {
                sr.nearEdge.DistanceToPseudoDistance(ref sr.minDistance, p, sr.nearParam);
            }
            if (sg.nearEdge != null)
            {
                sg.nearEdge.DistanceToPseudoDistance(ref sg.minDistance, p, sg.nearParam);
            }
            if (sb.nearEdge != null)
            {
                sb.nearEdge.DistanceToPseudoDistance(ref sb.minDistance, p, sb.nearParam);
            }

            MultiDistance msd = new MultiDistance {
                r   = SignedDistance.Infinite.distance,
                g   = SignedDistance.Infinite.distance,
                b   = SignedDistance.Infinite.distance,
                med = SignedDistance.Infinite.distance,
            };

            if (posDist >= 0 && Math.Abs(posDist) <= Math.Abs(negDist))
            {
                msd.med = SignedDistance.Infinite.distance;
                winding = 1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] > 0 && contourSD[i].med > msd.med && Math.Abs(contourSD[i].med) < Math.Abs(negDist))
                    {
                        msd = contourSD[i];
                    }
                }
            }
            else if (negDist <= 0 && Math.Abs(negDist) <= Math.Abs(posDist))
            {
                msd.med = -SignedDistance.Infinite.distance;
                winding = -1;
                for (int i = 0; i < contourCount; i++)
                {
                    if (windings[i] < 0 && contourSD[i].med < msd.med && Math.Abs(contourSD[i].med) < Math.Abs(posDist))
                    {
                        msd = contourSD[i];
                    }
                }
            }

            for (int i = 0; i < contourCount; i++)
            {
                if (windings[i] != winding && Math.Abs(contourSD[i].med) < Math.Abs(msd.med))
                {
                    msd = contourSD[i];
                }
            }

            if (Median(sr.minDistance.distance, sg.minDistance.distance, sb.minDistance.distance) == msd.med)
            {
                msd.r = sr.minDistance.distance;
                msd.g = sg.minDistance.distance;
                msd.b = sb.minDistance.distance;
            }

            return(new Color3((float)(msd.r / range) + 0.5f, (float)(msd.g / range) + 0.5f, (float)(msd.b / range) + 0.5f));
        }