Exemplo n.º 1
0
 public FtVec2(FT_Vector v)
 {
     this.x = v.x;
     this.y = v.y;
 }
 static FtVec2 GetMidPoint(FtVec2 v1, FT_Vector v2)
 {
     return(new FtVec2(
                (v1.x + (double)v2.x) / 2d,
                (v1.y + (double)v2.y) / 2d));
 }
        const double FT_RESIZE = 64; //essential to be floating point
        internal unsafe static GlyphImage BuildMsdfFontImage(NativeFontGlyph fontGlyph)
        {
            IntPtr     shape   = MyFtLib.CreateShape();
            FT_Outline outline = (*(FT_Outline *)fontGlyph.nativeOutlinePtr);            //outline version
            //------------------------------
            int npoints = outline.n_points;
            List <PixelFarm.VectorMath.Vector2> points = new List <PixelFarm.VectorMath.Vector2>(npoints);
            int startContour      = 0;
            int cpoint_index      = 0;
            int todoContourCount  = outline.n_contours;
            int controlPointCount = 0;

            while (todoContourCount > 0)
            {
                int  nextContour  = outline.contours[startContour] + 1;
                bool isFirstPoint = true;
                //---------------
                //create contour

                IntPtr cnt = MyFtLib.ShapeAddBlankContour(shape);
                FtVec2 secondControlPoint = new FtVec2();
                FtVec2 thirdControlPoint  = new FtVec2();
                bool   justFromCurveMode  = false;
                FtVec2 lastMoveTo         = new FtVec2();
                FtVec2 lastPoint          = new FtVec2();
                FtVec2 current_point      = new Fonts.FtVec2();
                for (; cpoint_index < nextContour; ++cpoint_index)
                {
                    FT_Vector xvpoint = outline.points[cpoint_index];
                    current_point = new FtVec2(xvpoint.x / FT_RESIZE, xvpoint.y / FT_RESIZE);
                    //Console.WriteLine(xvpoint.x.ToString() + "," + xvpoint.y);
                    byte vtag        = outline.tags[cpoint_index];
                    bool has_dropout = (((vtag >> 2) & 0x1) != 0);
                    int  dropoutMode = vtag >> 3;
                    if ((vtag & 0x1) != 0)
                    {
                        if (justFromCurveMode)
                        {
                            switch (controlPointCount)
                            {
                            case 1:
                            {
                                MyFtLib.ContourAddQuadraticSegment(cnt,
                                                                   lastPoint.x, lastPoint.y,
                                                                   secondControlPoint.x, secondControlPoint.y,
                                                                   current_point.x, current_point.y);
                                lastPoint = current_point;
                            }
                            break;

                            case 2:
                            {
                                MyFtLib.ContourAddCubicSegment(cnt,
                                                               lastPoint.x, lastPoint.y,
                                                               secondControlPoint.x, secondControlPoint.y,
                                                               thirdControlPoint.x, thirdControlPoint.y,
                                                               current_point.x, current_point.y);
                                lastPoint = current_point;
                            }
                            break;

                            default:
                            {
                                throw new NotSupportedException();
                            }
                            }
                            controlPointCount = 0;
                            justFromCurveMode = false;
                        }
                        else
                        {
                            //line mode
                            if (isFirstPoint)
                            {
                                isFirstPoint = false;
                                lastMoveTo   = lastPoint = current_point;
                            }
                            else
                            {
                                MyFtLib.ContourAddLinearSegment(cnt,
                                                                lastPoint.x, lastPoint.y,
                                                                current_point.x, current_point.y);
                                lastPoint = current_point;
                            }
                        }
                    }
                    else
                    {
                        if (isFirstPoint)
                        {
                            isFirstPoint = false;
                            lastMoveTo   = lastPoint = current_point;
                        }

                        switch (controlPointCount)
                        {
                        case 0:
                        {           //bit 1 set=> off curve, this is a control point
                                    //if this is a 2nd order or 3rd order control point
                            if (((vtag >> 1) & 0x1) != 0)
                            {
                                ////printf("[%d] bzc3rd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                thirdControlPoint = new FtVec2(current_point.x, current_point.y);
                            }
                            else
                            {
                                ////printf("[%d] bzc2nd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                secondControlPoint = new FtVec2(current_point.x, current_point.y);
                            }
                        }
                        break;

                        case 1:
                        {
                            if (((vtag >> 1) & 0x1) != 0)
                            {
                                ////printf("[%d] bzc3rd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                thirdControlPoint = new FtVec2(current_point.x, current_point.y);
                            }
                            else
                            {
                                //we already have prev second control point
                                //so auto calculate line to
                                //between 2 point
                                FtVec2 mid = GetMidPoint(secondControlPoint, current_point);
                                MyFtLib.ContourAddQuadraticSegment(cnt,
                                                                   lastPoint.x, lastPoint.y,
                                                                   secondControlPoint.x, secondControlPoint.y,
                                                                   mid.x, mid.y);
                                lastPoint = mid;
                                //------------------------
                                controlPointCount--;
                                //------------------------
                                //printf("[%d] bzc2nd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                secondControlPoint = current_point;
                            }
                        }
                        break;

                        default:
                        {
                            throw new NotSupportedException();
                        }
                        }

                        controlPointCount++;
                        justFromCurveMode = true;
                    }
                }
                //--------
                //close figure
                //if in curve mode
                if (justFromCurveMode)
                {
                    switch (controlPointCount)
                    {
                    case 0: break;

                    case 1:
                    {
                        MyFtLib.ContourAddQuadraticSegment(cnt,
                                                           lastPoint.x, lastPoint.y,
                                                           secondControlPoint.x, secondControlPoint.y,
                                                           lastMoveTo.x, lastMoveTo.y);
                        lastPoint = current_point;
                    }
                    break;

                    case 2:
                    {
                        MyFtLib.ContourAddCubicSegment(cnt,
                                                       lastPoint.x, lastPoint.y,
                                                       secondControlPoint.x, secondControlPoint.y,
                                                       thirdControlPoint.x, thirdControlPoint.y,
                                                       lastMoveTo.x, lastMoveTo.y);
                        lastPoint = current_point;
                    }
                    break;

                    default:
                    { throw new NotSupportedException(); }
                    }
                    justFromCurveMode = false;
                    controlPointCount = 0;
                }
                else
                {
                    MyFtLib.ContourAddLinearSegment(cnt,
                                                    current_point.x, current_point.y,
                                                    lastMoveTo.x, lastMoveTo.y);
                    lastPoint = current_point;
                }

                //ps.CloseFigure();
                //--------
                startContour++;
                todoContourCount--;
            }
            //------------

            double s_left, s_bottom, s_right, s_top;

            MyFtLib.ShapeFindBounds(shape, out s_left, out s_bottom, out s_right, out s_top);
            RectangleF glyphBounds = new RectangleF((float)s_left, (float)s_top, (float)(s_right - s_left), (float)(s_top - s_bottom));

            //then create msdf texture
            if (!MyFtLib.ShapeValidate(shape))
            {
                throw new NotSupportedException();
            }
            MyFtLib.ShapeNormalize(shape);
            int borderXY = 0;
            int w        = (int)Math.Ceiling(glyphBounds.Width) + (borderXY + borderXY);
            int h        = (int)(Math.Ceiling(glyphBounds.Height)) + (borderXY + borderXY);

            if (w == 0)
            {
                w = 5;
                h = 5;
            }
            int[]      outputBuffer = new int[w * h];
            GlyphImage glyphImage   = new GlyphImage(w, h);

            glyphImage.BorderXY            = borderXY;
            glyphImage.OriginalGlyphBounds = Typography.Rendering.RectangleF.FromLTRB(
                glyphBounds.Left,
                glyphBounds.Top,
                glyphBounds.Right,
                glyphBounds.Bottom);

            unsafe
            {
                fixed(int *output_header = &outputBuffer[0])
                {
                    float dx = 0;
                    float dy = 0;

                    if (s_left < 0)
                    {
                        //make it positive
                        dx = (float)-s_left;
                    }
                    else if (s_left > 0)
                    {
                    }
                    if (s_bottom < 0)
                    {
                        //make it positive
                        dy = (float)-s_bottom;
                    }
                    else if (s_bottom > 0)
                    {
                    }
                    //this glyph image has border (for msdf to render correctly)
                    MyFtLib.MyFtGenerateMsdf(shape, w, h, 4, 1, dx + borderXY, dy + borderXY, -1, 3, output_header);
                    MyFtLib.DeleteUnmanagedObj(shape);
                }

                glyphImage.SetImageBuffer(outputBuffer, true);
            }
            return(glyphImage);
        }
        unsafe internal static void BuildGlyphOutline(NativeFontGlyph fontGlyph)
        {
            FT_Outline outline = (*(FT_Outline *)fontGlyph.nativeOutlinePtr);
            //outline version
            //------------------------------
            int npoints = outline.n_points;

            int startContour     = 0;
            int cpoint_index     = 0;
            int todoContourCount = outline.n_contours;

            PixelFarm.Agg.VertexSource.PathWriter ps = new Agg.VertexSource.PathWriter();
            fontGlyph.originalVxs = ps.Vxs;
            int controlPointCount = 0;

            while (todoContourCount > 0)
            {
                int    nextContour        = outline.contours[startContour] + 1;
                bool   isFirstPoint       = true;
                FtVec2 secondControlPoint = new FtVec2();
                FtVec2 thirdControlPoint  = new FtVec2();
                bool   justFromCurveMode  = false;
                //FT_Vector vpoint = new FT_Vector();
                for (; cpoint_index < nextContour; ++cpoint_index)
                {
                    FT_Vector vpoint      = outline.points[cpoint_index];
                    byte      vtag        = outline.tags[cpoint_index];
                    bool      has_dropout = (((vtag >> 2) & 0x1) != 0);
                    int       dropoutMode = vtag >> 3;

                    // Console.WriteLine(vpoint.ToString() + " " + vtag);

                    if ((vtag & 0x1) != 0)
                    {
                        //on curve
                        if (justFromCurveMode)
                        {
                            switch (controlPointCount)
                            {
                            case 1:
                            {
                                ps.Curve3(secondControlPoint.x / FT_RESIZE, secondControlPoint.y / FT_RESIZE,
                                          vpoint.x / FT_RESIZE, vpoint.y / FT_RESIZE);
                            }
                            break;

                            case 2:
                            {
                                ps.Curve4(secondControlPoint.x / FT_RESIZE, secondControlPoint.y / FT_RESIZE,
                                          thirdControlPoint.x / FT_RESIZE, thirdControlPoint.y / FT_RESIZE,
                                          vpoint.x / FT_RESIZE, vpoint.y / FT_RESIZE);
                            }
                            break;

                            default:
                            {
                                throw new NotSupportedException();
                            }
                            }
                            controlPointCount = 0;
                            justFromCurveMode = false;
                        }
                        else
                        {
                            if (isFirstPoint)
                            {
                                isFirstPoint = false;
                                ps.MoveTo(vpoint.x / FT_RESIZE, vpoint.y / FT_RESIZE);
                            }
                            else
                            {
                                ps.LineTo(vpoint.x / FT_RESIZE, vpoint.y / FT_RESIZE);
                            }

                            if (has_dropout)
                            {
                                //printf("[%d] on,dropoutMode=%d: %d,y:%d \n", mm, dropoutMode, vpoint.x, vpoint.y);
                            }
                            else
                            {
                                //printf("[%d] on,x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                            }
                        }
                    }
                    else
                    {
                        switch (controlPointCount)
                        {
                        case 0:
                        {           //bit 1 set=> off curve, this is a control point
                                    //if this is a 2nd order or 3rd order control point
                            if (((vtag >> 1) & 0x1) != 0)
                            {
                                //printf("[%d] bzc3rd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                thirdControlPoint = new FtVec2(vpoint);
                            }
                            else
                            {
                                //printf("[%d] bzc2nd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                secondControlPoint = new FtVec2(vpoint);
                            }
                        }
                        break;

                        case 1:
                        {
                            if (((vtag >> 1) & 0x1) != 0)
                            {
                                //printf("[%d] bzc3rd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                thirdControlPoint = new FtVec2(vpoint);
                            }
                            else
                            {
                                //we already have prev second control point
                                //so auto calculate line to
                                //between 2 point
                                FtVec2 mid = GetMidPoint(secondControlPoint, vpoint);
                                //----------
                                //generate curve3
                                ps.Curve3(secondControlPoint.x / FT_RESIZE, secondControlPoint.y / FT_RESIZE,
                                          mid.x / FT_RESIZE, mid.y / FT_RESIZE);
                                //------------------------
                                controlPointCount--;
                                //------------------------
                                //printf("[%d] bzc2nd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                secondControlPoint = new FtVec2(vpoint);
                            }
                        }
                        break;

                        default:
                        {
                            throw new NotSupportedException();
                        }
                        break;
                        }

                        controlPointCount++;
                        justFromCurveMode = true;
                    }
                }
                //--------
                //close figure
                //if in curve mode
                if (justFromCurveMode)
                {
                    switch (controlPointCount)
                    {
                    case 0: break;

                    case 1:
                    {
                        ps.Curve3(secondControlPoint.x / FT_RESIZE, secondControlPoint.y / FT_RESIZE,
                                  ps.LastMoveX, ps.LastMoveY);
                    }
                    break;

                    case 2:
                    {
                        ps.Curve4(secondControlPoint.x / FT_RESIZE, secondControlPoint.y / FT_RESIZE,
                                  thirdControlPoint.x / FT_RESIZE, thirdControlPoint.y / FT_RESIZE,
                                  ps.LastMoveX, ps.LastMoveY);
                    }
                    break;

                    default:
                    { throw new NotSupportedException(); }
                    }
                    justFromCurveMode = false;
                    controlPointCount = 0;
                }
                ps.CloseFigure();
                //--------
                startContour++;
                todoContourCount--;
            }
        }
Exemplo n.º 5
0
 public FtVec2(FT_Vector v)
 {
     this.x = v.x;
     this.y = v.y;
 }
 static FtVec2 GetMidPoint(FtVec2 v1, FT_Vector v2)
 {
     return new FtVec2(
         (v1.x + (double)v2.x) / 2d,
         (v1.y + (double)v2.y) / 2d);
 }