Beispiel #1
0
 unsafe void BuildGlyph(FontGlyph fontGlyph, ExportGlyph *exportTypeFace, int pxsize)
 {
     //------------------------------------------
     //copy font metrics
     fontGlyph.exportGlyph = *(exportTypeFace);
     //------------------------------------------
     //copy raw image
     NativeFontGlyphBuilder.CopyGlyphBitmap(fontGlyph, exportTypeFace);
     //outline version
     //------------------------------------------
     if (px64Font != null)
     {
         if (pxsize < 64)
         {
             NativeFontGlyphBuilder.BuildGlyphOutline(fontGlyph, exportTypeFace);
         }
         else
         {
             NativeFontGlyphBuilder.BuildGlyphOutline(fontGlyph, exportTypeFace);
         }
     }
     else
     {
         NativeFontGlyphBuilder.BuildGlyphOutline(fontGlyph, exportTypeFace);
     }
 }
Beispiel #2
0
        public override void GetGlyphPos(char[] buffer, int start, int len, ProperGlyph[] properGlyphs)
        {
            //find proper position for each glyph
            int j = buffer.Length;

            for (int i = 0; i < j; ++i)
            {
                FontGlyph f = this.GetGlyph(buffer[i]);
                properGlyphs[i].x_advance = f.horiz_adv_x >> 6; //64
                properGlyphs[i].codepoint = (uint)buffer[i];
            }
        }
Beispiel #3
0
        public void ReadSVG(string svgContent)
        {
            int    startIndex        = 0;
            String fontElementString = GetSubString(svgContent, "<font", ">", ref startIndex);

            fontId = GetStringValue(fontElementString, "id");
            GetIntValue(fontElementString, "horiz-adv-x", out horiz_adv_x);

            String fontFaceString = GetSubString(svgContent, "<font-face", "/>", ref startIndex);

            fontFamily = GetStringValue(fontFaceString, "font-family");
            GetIntValue(fontFaceString, "font-weight", out font_weight);
            font_stretch = GetStringValue(fontFaceString, "font-stretch");
            GetIntValue(fontFaceString, "units-per-em", out unitsPerEm);
            panose_1 = new Panos_1(GetStringValue(fontFaceString, "panose-1"));
            GetIntValue(fontFaceString, "ascent", out ascent);
            GetIntValue(fontFaceString, "descent", out descent);
            GetIntValue(fontFaceString, "x-height", out x_height);
            GetIntValue(fontFaceString, "cap-height", out cap_height);

            String bboxString = GetStringValue(fontFaceString, "bbox");

            String[] valuesString = bboxString.Split(' ');
            int.TryParse(valuesString[0], out boundingBox.Left);
            int.TryParse(valuesString[1], out boundingBox.Bottom);
            int.TryParse(valuesString[2], out boundingBox.Right);
            int.TryParse(valuesString[3], out boundingBox.Top);

            GetIntValue(fontFaceString, "underline-thickness", out underline_thickness);
            GetIntValue(fontFaceString, "underline-position", out underline_position);
            unicode_range = GetStringValue(fontFaceString, "unicode-range");

            String missingGlyphString = GetSubString(svgContent, "<missing-glyph", "/>", ref startIndex);

            missingGlyph = CreateGlyphFromSVGGlyphData(missingGlyphString);

            String nextGlyphString = GetSubString(svgContent, "<glyph", "/>", ref startIndex);

            while (nextGlyphString != null)
            {
                // get the data and put it in the glyph dictionary

                FontGlyph newGlyph = CreateGlyphFromSVGGlyphData(nextGlyphString);
                if (newGlyph.unicode > 0)
                {
                    originalGlyphs.Add(newGlyph.unicode, newGlyph);
                }

                nextGlyphString = GetSubString(svgContent, "<glyph", "/>", ref startIndex);
            }
        }
Beispiel #4
0
        public void Print(CanvasPainter painter, char[] buffer, double x, double y)
        {
            int j        = buffer.Length;
            int buffsize = j * 2;

            //get kerning list

            ProperGlyph[] properGlyphs = new ProperGlyph[buffsize];
            currentFont.GetGlyphPos(buffer, 0, buffsize, properGlyphs);


            double xpos = x;

            for (int i = 0; i < buffsize; ++i)
            {
                uint codepoint = properGlyphs[i].codepoint;
                if (codepoint == 0)
                {
                    break;
                }
                //-------------------------------------------------------------
                FontGlyph glyph = this.currentFont.GetGlyphByIndex(codepoint);
                var       left  = glyph.exportGlyph.img_horiBearingX;

                //--------------------------------------------------------
                //render with vector
                //var mat = Agg.Transform.Affine.NewMatix(
                //Agg.Transform.AffinePlan.Scale(0.30),
                //Agg.Transform.AffinePlan.Translate(xpos, y));
                //var vxs1 = mat.TransformToVxs(glyph.flattenVxs);

                VertexStore vxs1 = Agg.Transform.Affine.TranslateToVxs(
                    glyph.flattenVxs,
                    (float)(xpos),
                    (float)(y));

                painter.Fill(vxs1);
                //--------------------------------------------------------
                ////render with bitmap
                //this.painter.DrawImage(glyph.glyphImage32,
                //    (float)(xpos + (left >> 6)),
                //    (float)(y + (glyph.exportGlyph.bboxYmin >> 6)));

                int w = (glyph.exportGlyph.advanceX) >> 6;
                xpos += (w);
                //-------------------------------------------------------------
            }
        }
Beispiel #5
0
 internal FontGlyph ReloadGlyphFromChar(char unicodeChar, int pixelSize)
 {
     if (currentFacePixelSize != pixelSize)
     {
         currentFacePixelSize = pixelSize;
         NativeMyFontsLib.MyFtSetPixelSizes(this.ftFaceHandle, pixelSize);
     }
     //--------------------------------------------------
     unsafe
     {
         ExportGlyph exportTypeFace = new ExportGlyph();
         NativeMyFontsLib.MyFtLoadChar(ftFaceHandle, unicodeChar, ref exportTypeFace);
         FontGlyph fontGlyph = new FontGlyph();
         BuildGlyph(fontGlyph, &exportTypeFace, pixelSize);
         return(fontGlyph);
     }
 }
Beispiel #6
0
        public override FontGlyph GetGlyph(char c)
        {
            FontGlyph glyph;

            if (!cachedGlyphs.TryGetValue(c, out glyph))
            {
                //create font glyph for this font size
                var         originalGlyph  = fontface.GetGlyphForCharacter(c);
                VertexStore characterGlyph = scaleTx.TransformToVxs(originalGlyph.originalVxs);
                glyph             = new FontGlyph();
                glyph.horiz_adv_x = originalGlyph.horiz_adv_x;
                glyph.originalVxs = characterGlyph;
                //then flatten it
                characterGlyph   = curveFlattner.MakeVxs(characterGlyph);
                glyph.flattenVxs = characterGlyph;
                cachedGlyphs.Add(c, glyph);
            }
            return(glyph);
        }
        public override FontGlyph GetGlyph(char c)
        {
            FontGlyph found;

            if (!this.cachedGlyphs.TryGetValue(c, out found))
            {
                //if not found then create new one
                found = new FontGlyph();
                //------------------------
                //create vector version, using Path
                VertexStore vxs = new VertexStore();
                PixelFarm.Agg.GdiPathConverter.ConvertCharToVertexGlyph(gdiFont, c, vxs);
                found.originalVxs = vxs;
                //create flatten version
                found.flattenVxs = curveFlattener.MakeVxs(vxs);//?
                //-------------------------
                //create bmp version
                //find vxs bound
                this.cachedGlyphs.Add(c, found);
            }
            return(found);
        }
Beispiel #8
0
        public VertexStore CreateVxs(char[] buffer, double x = 0, double y = 0)
        {
            int j        = buffer.Length;
            int buffsize = j * 2;

            //get kerning list

            ProperGlyph[] properGlyphs = new ProperGlyph[buffsize];
            currentFont.GetGlyphPos(buffer, 0, buffsize, properGlyphs);
            VertexStore resultVxs = new VertexStore();


            double xpos = x;

            for (int i = 0; i < buffsize; ++i)
            {
                uint codepoint = properGlyphs[i].codepoint;
                if (codepoint == 0)
                {
                    break;
                }
                //-------------------------------------------------------------
                FontGlyph glyph = this.currentFont.GetGlyphByIndex(codepoint);
                var       left  = glyph.exportGlyph.img_horiBearingX;
                //--------------------------------------------------------
                VertexStore vxs1 = Agg.Transform.Affine.TranslateToVxs(
                    glyph.flattenVxs,
                    (float)(xpos),
                    (float)(y));
                //--------------------------------------------------------
                resultVxs.AddSubVertices(vxs1);


                int w = (glyph.exportGlyph.advanceX) >> 6;
                xpos += (w);
                //-------------------------------------------------------------
            }
            return(resultVxs);
        }
Beispiel #9
0
        unsafe internal static void CopyGlyphBitmap(FontGlyph fontGlyph, ExportGlyph *exportTypeFace)
        {
            FT_Bitmap *ftBmp = (FT_Bitmap *)exportTypeFace->bitmap;
            //image is 8 bits grayscale
            int h      = ftBmp->rows;
            int w      = ftBmp->width;
            int stride = ftBmp->pitch;
            int size   = stride * h;

            //copy it to array
            //bmp glyph is bottom up
            //so .. invert it...

            byte[] buff = new byte[size];
            //------------------------------------------------
            byte *currentSrc = ftBmp->buffer;
            int   srcpos     = size;
            int   targetpos  = 0;

            for (int r = 1; r <= h; ++r)
            {
                srcpos    -= stride;
                currentSrc = ftBmp->buffer + srcpos;
                for (int c = 0; c < stride; ++c)
                {
                    buff[targetpos] = *(currentSrc + c);
                    targetpos++;
                }
            }

            ////------------------------------------------------
            //IntPtr bmpPtr = (IntPtr)ftBmp->buffer;
            //Marshal.Copy((IntPtr)ftBmp->buffer, buff, 0, size);
            ////------------------------------------------------

            //------------------------------------------------
            fontGlyph.glyImgBuffer8 = buff;
            //convert to 32bpp
            //make gray value as alpha channel color value
            ActualImage actualImage = new ActualImage(w, h, Agg.Image.PixelFormat.Rgba32);
            int         newstride   = stride * 4;

            byte[] newBmp32Buffer = actualImage.GetBuffer();
            int    src_p          = 0;
            int    target_p       = 0;

            for (int r = 0; r < h; ++r)
            {
                for (int c = 0; c < w; ++c)
                {
                    byte srcColor = buff[src_p + c];
                    //expand to 4 channel
                    newBmp32Buffer[target_p]     = 0;        //R
                    newBmp32Buffer[target_p + 1] = 0;        //G
                    newBmp32Buffer[target_p + 2] = 0;        //B
                    newBmp32Buffer[target_p + 3] = srcColor; //A
                    target_p += 4;
                }
                src_p += stride;
            }
            fontGlyph.glyphImage32 = actualImage;
            ////------------------------------------------------
            //{
            //      //add System.Drawing to references
            //      //save image for debug***
            //
            //    byte[] buffer = new byte[size];
            //    Marshal.Copy((IntPtr)ftBmp->buffer, buffer, 0, size);
            //    ////save to
            //    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
            //    var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h),
            //        System.Drawing.Imaging.ImageLockMode.ReadWrite,
            //        bmp.PixelFormat);
            //    Marshal.Copy(buffer, 0, bmpdata.Scan0, size);
            //    bmp.UnlockBits(bmpdata);
            //    bmp.Save("d:\\WImageTest\\glyph.png");
            //}
        }
Beispiel #10
0
        unsafe internal static void BuildGlyphOutline(FontGlyph fontGlyph, ExportGlyph *exportTypeFace)
        {
            FT_Outline outline = (*(FT_Outline *)exportTypeFace->outline);
            //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;

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

            while (todoContourCount > 0)
            {
                int       nextContour        = outline.contours[startContour] + 1;
                bool      isFirstPoint       = true;
                FT_Vector secondControlPoint = new FT_Vector();
                FT_Vector thirdControlPoint  = new FT_Vector();
                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;
                    if ((vtag & 0x1) != 0)
                    {
                        //on curve
                        if (justFromCurveMode)
                        {
                            switch (controlPointCount)
                            {
                            case 1:
                            {
                                ps.Curve3(secondControlPoint.x / resize, secondControlPoint.y / resize,
                                          vpoint.x / resize, vpoint.y / resize);
                            }
                            break;

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

                            default:
                            {
                                throw new NotSupportedException();
                            }
                            }
                            controlPointCount = 0;
                            justFromCurveMode = false;
                        }
                        else
                        {
                            if (isFirstPoint)
                            {
                                isFirstPoint = false;
                                ps.MoveTo(vpoint.x / resize, vpoint.y / resize);
                            }
                            else
                            {
                                ps.LineTo(vpoint.x / resize, vpoint.y / 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 = vpoint;
                            }
                            else
                            {
                                //printf("[%d] bzc2nd,  x: %d,y:%d \n", mm, vpoint.x, vpoint.y);
                                secondControlPoint = vpoint;
                            }
                        }
                        break;

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

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

                    default:
                    { throw new NotSupportedException(); }
                    }
                    justFromCurveMode = false;
                    controlPointCount = 0;
                }
                ps.CloseFigure();
                //--------
                startContour++;
                todoContourCount--;
            }

            fontGlyph.flattenVxs = curveFlattener.MakeVxs(fontGlyph.originalVxs);
        }
Beispiel #11
0
        FontGlyph CreateGlyphFromSVGGlyphData(string svgGlyphData)
        {
            FontGlyph newGlyph = new FontGlyph();

            if (!GetIntValue(svgGlyphData, "horiz-adv-x", out newGlyph.horiz_adv_x))
            {
                newGlyph.horiz_adv_x = horiz_adv_x;
            }

            newGlyph.glyphName = GetStringValue(svgGlyphData, "glyph-name");
            String unicodeString = GetStringValue(svgGlyphData, "unicode");

            if (unicodeString != null)
            {
                if (unicodeString.Length == 1)
                {
                    newGlyph.unicode = (int)unicodeString[0];
                }
                else
                {
                    if (unicodeString.Split(';').Length > 1 && unicodeString.Split(';')[1].Length > 0)
                    {
                        throw new NotImplementedException("We do not currently support glyphs longer than one character.  You need to wirite the seach so that it will find them if you want to support this");
                    }

                    if (int.TryParse(unicodeString, NumberStyles.Number, null, out newGlyph.unicode) == false)
                    {
                        // see if it is a unicode
                        String hexNumber = GetSubString(unicodeString, "&#x", ";");
                        int.TryParse(hexNumber, NumberStyles.HexNumber, null, out newGlyph.unicode);
                    }
                }
            }

            String dString = GetStringValue(svgGlyphData, "d");
            //if (newGlyph.glyphName == "a")
            //{
            //}
            int parseIndex = 0;
            int polyStartVertexSourceIndex = 0;


            Vector2 lastXY = new Vector2(0, 0);

            double px = 0;
            double py = 0;



            PathWriter gyphPath = new PathWriter();

            newGlyph.originalVxs = gyphPath.Vxs;

            if (dString == null || dString.Length == 0)
            {
                return(newGlyph);
            }



            while (parseIndex < dString.Length)
            {
                char command = dString[parseIndex];
                switch (command)
                {
                case 'M':
                {
                    parseIndex++;
                    // svg fonts are stored cw and agg expects its shapes to be ccw.  cw shapes are holes.
                    // so we store the position of the start of this polygon so we can flip it when we colse it.
                    polyStartVertexSourceIndex = gyphPath.Count;
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.MoveTo(px, py);
                } break;

                case 'v':
                {
                    parseIndex++;
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.VerticalLineToRel(py);
                } break;

                case 'V':
                {
                    parseIndex++;
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.VerticalLineTo(py);
                } break;

                case 'h':
                {
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    gyphPath.HorizontalLineToRel(px);
                } break;

                case 'H':
                {
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    gyphPath.HorizontalLineTo(px);
                } break;

                case 'l':
                {
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.LineToRel(px, py);
                } break;

                case 'L':
                {
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.LineTo(px, py);
                } break;

                case 'q':
                {
                    //Curve3
                    parseIndex++;
                    double p2x = GetNextNumber(dString, ref parseIndex);
                    double p2y = GetNextNumber(dString, ref parseIndex);
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.Curve3Rel(p2x, p2y, px, py);
                } break;

                case 'Q':
                {           //Curve3
                    parseIndex++;
                    double p2x = GetNextNumber(dString, ref parseIndex);
                    double p2y = GetNextNumber(dString, ref parseIndex);
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.Curve3(p2x, p2y, px, py);
                }
                break;

                case 't':
                {
                    //svg smooth curve3
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.SmoothCurve3Rel(px, py);
                } break;

                case 'T':
                {
                    parseIndex++;
                    px = GetNextNumber(dString, ref parseIndex);
                    py = GetNextNumber(dString, ref parseIndex);
                    gyphPath.SmoothCurve3(px, py);
                } break;

                case 'z':
                case 'Z':
                {
                    parseIndex++;
                    //curXY = lastXY; // value not used this is to remove an error.
                    //newGlyph.glyphData.ClosePathStorage();
                    gyphPath.CloseFigure();
                    // svg fonts are stored cw and agg expects its shapes to be ccw.  cw shapes are holes.
                    // We stored the position of the start of this polygon, no we flip it as we colse it.
                    //newGlyph.glyphData.InvertPolygon(polyStartVertexSourceIndex);
                    // VertexHelper.InvertPolygon(gyphPath.Vxs, polyStartVertexSourceIndex);
                } break;

                case ' ':
                case '\n':     // some white space we need to skip
                case '\r':
                {
                    parseIndex++;
                } break;

                default:
                    throw new NotImplementedException("unrecognized d command '" + command + "'.");
                }
            }

            return(newGlyph);
        }