Example #1
0
        private void button4_Click(object sender, EventArgs e)
        {
            string          fontfilename = "d:\\WImageTest\\a_total.xml";
            var             atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder();
            SimpleFontAtlas fontAtlas    = atlasBuilder.LoadFontInfo(fontfilename);

            using (Bitmap totalImg = new Bitmap("d:\\WImageTest\\a_total.png"))
            {
                var bmpdata = totalImg.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, totalImg.PixelFormat);
                var buffer  = new int[totalImg.Width * totalImg.Height];
                System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, buffer, 0, buffer.Length);
                totalImg.UnlockBits(bmpdata);
                var glyImage = new GlyphImage(totalImg.Width, totalImg.Height);
                glyImage.SetImageBuffer(buffer, false);
                fontAtlas.TotalGlyph = glyImage;
            }
        }
        /// <summary>
        /// test only, shapen org image with Paint.net sharpen filter
        /// </summary>
        /// <param name="org"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        static GlyphImage Sharpen(GlyphImage org, int radius)
        {
            GlyphImage newImg = new GlyphImage(org.Width, org.Height);

            Agg.Imaging.ShapenFilterPdn sharpen1 = new Agg.Imaging.ShapenFilterPdn();
            int[] orgBuffer = org.GetImageBuffer();
            unsafe
            {
                fixed(int *orgHeader = &orgBuffer[0])
                {
                    int[] output = sharpen1.Sharpen(orgHeader, org.Width, org.Height, org.Width * 4, radius);
                    newImg.SetImageBuffer(output, org.IsBigEndian);
                }
            }

            return(newImg);
        }
        static GlyphImage ReadGlyphImages(string filename)
        {
            using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Open))
            {
                Hjg.Pngcs.PngReader reader  = new Hjg.Pngcs.PngReader(fs, filename);
                Hjg.Pngcs.ImageInfo imgInfo = reader.ImgInfo;
                Hjg.Pngcs.ImageLine iline2  = new Hjg.Pngcs.ImageLine(imgInfo, Hjg.Pngcs.ImageLine.ESampleType.BYTE);

                int imgH    = imgInfo.Rows;
                int imgW    = imgInfo.Cols;
                int stride  = imgInfo.BytesPerRow;
                int widthPx = imgInfo.Cols;

                int[] buffer = new int[(stride / 4) * imgH];
                //read each row
                //and fill the glyph image
                int startWriteAt = (imgW * (imgH - 1));
                int destIndex    = startWriteAt;

                for (int row = 0; row < imgH; row++)
                {
                    Hjg.Pngcs.ImageLine iline = reader.ReadRowByte(row);
                    byte[] scline             = iline.ScanlineB;

                    int b_src = 0;
                    destIndex = startWriteAt;

                    for (int mm = 0; mm < imgW; ++mm)
                    {
                        byte b = scline[b_src];
                        byte g = scline[b_src + 1];
                        byte r = scline[b_src + 2];
                        byte a = scline[b_src + 3];
                        b_src            += 4;
                        buffer[destIndex] = (b << 16) | (g << 8) | (r) | (a << 24);
                        destIndex++;
                    }
                    startWriteAt -= imgW;
                }

                GlyphImage img = new GlyphImage(imgW, imgH);
                img.SetImageBuffer(buffer, true);
                return(img);
            }
        }
Example #4
0
        private void button5_Click(object sender, EventArgs e)
        {
            //1. load font
            string fontName = "tahoma";
            string fontfile = "c:\\Windows\\Fonts\\tahoma.ttf";
            //string fontfile = @"D:\WImageTest\THSarabunNew\THSarabunNew.ttf";
            ActualFont font = GetActualFont(fontfile, 18);// nativeFontStore.LoadFont(fontName, fontfile, 28);
            //2. get glyph
            var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder();

            //for (int i = 0; i < 256; ++i)
            //BuildFontGlyphsByIndex(font, atlasBuilder, 0, 255);
            //BuildFontGlyphs(font, atlasBuilder, 0x0e00, 0x0e5b);
            //BuildFontGlyphsByIndex(font, atlasBuilder, 0, 3417);
            //BuildFontGlyphsByIndex(font, atlasBuilder, 0, 509);
            //BuildFontGlyphsByIndex(font, atlasBuilder, 97, 97);
            BuildFontGlyph(font, atlasBuilder, 'B');
            //----------------------------------------------------
            //GlyphImage totalImg = atlasBuilder.BuildSingleImage();
            GlyphImage totalImg = atlasBuilder.BuildSingleImage();

            using (Bitmap bmp = new Bitmap(totalImg.Width, totalImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            {
                int[] buffer = totalImg.GetImageBuffer();
                if (totalImg.IsBigEndian)
                {
                    NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
                    totalImg.SetImageBuffer(buffer, false);
                }

                var bmpdata = bmp.LockBits(
                    new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height),
                    System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                bmp.UnlockBits(bmpdata);
                bmp.Save("d:\\WImageTest\\a_total.png");
            }

            string fontfilename = "d:\\WImageTest\\a_total.xml";

            atlasBuilder.SaveFontInfo(fontfilename);
            //----------------------------------
        }
Example #5
0
        static void BuildFontGlyph(ActualFont nativefont, Typography.Rendering.SimpleFontAtlasBuilder atlasBuilder, char c)
        {
            //font glyph for specific font face



            FontGlyph  fontGlyph = nativefont.GetGlyph(c);
            GlyphImage glyphImg  = NativeMsdfGen.BuildMsdfFontImage(fontGlyph);

            int w = glyphImg.Width;
            int h = glyphImg.Height;

            int[] buffer = glyphImg.GetImageBuffer();
            NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
            glyphImg.SetImageBuffer(buffer, false);
            atlasBuilder.AddGlyph(0, glyphImg);
            //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            //{
            //    var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
            //    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
            //    bmp.UnlockBits(bmpdata);
            //    bmp.Save("d:\\WImageTest\\a001_x1_" + (int)c + ".png");
            //}
        }
Example #6
0
        static SimpleFontAtlasBuilder CreateAggSubPixelRenderingTextureFont(
            Typeface typeface, float sizeInPoint, HintTechnique hintTech, IEnumerable <ushort> glyphIndexIter)
        {
            ////read type face from file
            //Typeface typeface;
            //using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read))
            //{
            //    var reader = new OpenFontReader();
            //    //1. read typeface from font file
            //    typeface = reader.Read(fs);
            //}
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique(hintTech);
            //-------------------------------------------------------------
            var atlasBuilder = new SimpleFontAtlasBuilder();

            atlasBuilder.SetAtlasInfo(TextureKind.AggSubPixel, sizeInPoint);
            VertexStorePool vxsPool = new VertexStorePool();

            //create agg cavnas

            foreach (ushort gindex in glyphIndexIter)
            {
                //build glyph

                builder.BuildFromGlyphIndex(gindex, sizeInPoint);


                var txToVxs = new GlyphTranslatorToVxs();
                builder.ReadShapes(txToVxs);
                //
                //create new one
                var glyphVxs = new VertexStore();
                txToVxs.WriteOutput(glyphVxs, vxsPool);
                //find bound

                //--------------------------------------------
                //GlyphImage glyphImg = new GlyphImage()
                RectD bounds = new Agg.RectD();
                BoundingRect.GetBoundingRect(new VertexStoreSnap(glyphVxs), ref bounds);

                //--------------------------------------------
                int w = (int)System.Math.Ceiling(bounds.Width);
                int h = (int)System.Math.Ceiling(bounds.Height);
                if (w < 5)
                {
                    w = 5;
                }
                if (h < 5)
                {
                    h = 5;
                }
                //translate to positive quadrant
                double dx = (bounds.Left < 0) ? -bounds.Left : 0;
                double dy = (bounds.Bottom < 0) ? -bounds.Bottom : 0;
                w = w * 4;

                if (dx != 0 || dy != 0)
                {
                    Agg.Transform.Affine transformMat = Agg.Transform.Affine.NewTranslation(dx, dy);
                    VertexStore          vxs2         = new VertexStore();
                    glyphVxs.TranslateToNewVxs(dx, dy, vxs2);
                    glyphVxs = vxs2;
                }
                //--------------------------------------------
                //create glyph img
                ActualImage      img         = new Agg.ActualImage(w, h, PixelFormat.ARGB32);
                ImageGraphics2D  imgCanvas2d = new Agg.ImageGraphics2D(img);
                AggCanvasPainter painter     = new Agg.AggCanvasPainter(imgCanvas2d);
                //we use white glyph on black bg for this texture
                painter.Clear(Color.Black); //fill with black
                painter.FillColor   = Color.White;
                painter.StrokeColor = Color.White;
                //--------------------------------------------

                painter.UseSubPixelRendering = true;
                //--------------------------------------------


                //--------------------------------------------
                painter.Fill(glyphVxs);
                //--------------------------------------------
                var glyphImage = new GlyphImage(w, h);
                glyphImage.TextureOffsetX = dx;
                glyphImage.TextureOffsetY = dy;
                glyphImage.SetImageBuffer(ActualImage.GetBuffer2(img), false);
                //copy data from agg canvas to glyph image
                atlasBuilder.AddGlyph(gindex, glyphImage);

                //int[] buffer = glyphImage.GetImageBuffer();
                //using (var bmp = new System.Drawing.Bitmap(glyphImage.Width, glyphImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                //{
                //    var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImage.Width, glyphImage.Height),
                //        System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                //    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                //    bmp.UnlockBits(bmpdata);
                //    bmp.Save("d:\\WImageTest\\a001_subpix_xn2_" + gindex + ".png");
                //}
            }
            //var glyphImg2 = atlasBuilder.BuildSingleImage();
            //using (var bmp = new System.Drawing.Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            //{
            //    var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height),
            //        System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
            //    int[] intBuffer = glyphImg2.GetImageBuffer();

            //    System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length);
            //    bmp.UnlockBits(bmpdata);
            //    bmp.Save("d:\\WImageTest\\a_total.png");
            //}
            //atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml");

            return(atlasBuilder);
        }
Example #7
0
        public GlyphImage CreateGlyphImage(GlyphPathBuilder builder, float pxscale)
        {
            _txToVxs.Reset();
            //1. builder read shape and translate it with _txToVxs
            builder.ReadShapes(_txToVxs);

            using (VxsTemp.Borrow(out var glyphVxs, out var vxs2))
            {
                //2. write translated data (in the _txToVxs) to glyphVxs

                _txToVxs.WriteOutput(glyphVxs, pxscale);

                RectD bounds = glyphVxs.GetBoundingRect();

                //--------------------------------------------
                int w = (int)System.Math.Ceiling(bounds.Width);
                int h = (int)System.Math.Ceiling(bounds.Height);
                if (w < 5)
                {
                    w = 5;
                }
                if (h < 5)
                {
                    h = 5;
                }
                //we need some margin
                int horizontal_margin = 1;
                int vertical_margin   = 1;

                //translate to positive quadrant and use minimum space

                int dx = (int)Math.Ceiling((bounds.Left < 0) ? -bounds.Left : 0);
                int dy = 0;

                //vertical adjust =>since we need to move it, then move it with integer value
                if (bounds.Bottom < 0)
                {
                    dy = (int)Math.Ceiling(-bounds.Bottom);
                }
                else if (bounds.Bottom > 0)
                {
                    dy = (int)Math.Floor(-bounds.Bottom);
                }
                dx += horizontal_margin; //margin left
                dy += vertical_margin;
                //--------------------------------------------
                w = dx + w + horizontal_margin;            //+right margin

                h = vertical_margin + h + vertical_margin; //+bottom margin
                AggPainter painter = Painter;
                if (TextureKind == TextureKind.StencilLcdEffect)
                {
                    glyphVxs.TranslateToNewVxs(dx + 0.33f, dy, vxs2); //offset to proper x of subpixel rendering  ***
                    glyphVxs = vxs2;

                    RectD bounds2 = vxs2.GetBoundingRect();
                    if (w < bounds2.Right)
                    {
                        w = (int)Math.Ceiling(bounds2.Right);
                    }
                    //
                    painter.UseSubPixelLcdEffect = true;
                    //we use white glyph on black bg for this texture
                    painter.Clear(Color.Black);
                    painter.FillColor = Color.White;
                    painter.Fill(glyphVxs);

                    //apply sharpen filter
                    //painter.DoFilter(new RectInt(0, h, w, 0), 2);
                    //painter.DoFilter(new RectInt(0, h, w, 0), 2); //?
                }
                else
                {
                    glyphVxs.TranslateToNewVxs(dx, dy, vxs2);
                    glyphVxs = vxs2;

                    painter.UseSubPixelLcdEffect = false;

                    if (TextureKind == TextureKind.StencilGreyScale)
                    {
                        painter.Clear(Color.Empty);
                        painter.FillColor = Color.Black;
                    }
                    else
                    {
                        painter.Clear(BackGroundColor);
                        painter.FillColor = this.GlyphColor;
                    }
                    painter.Fill(glyphVxs);
                }
                //


                if (w > painter.RenderSurface.DestBitmap.Width)
                {
                    w = painter.RenderSurface.DestBitmap.Width;
                }
                if (h > painter.RenderSurface.DestBitmap.Height)
                {
                    h = painter.RenderSurface.DestBitmap.Height;
                }

                var glyphImage = new GlyphImage(w, h);

#if DEBUG
                if (dx < short.MinValue || dx > short.MaxValue)
                {
                    throw new NotSupportedException();
                }
                if (dy < short.MinValue || dy > short.MaxValue)
                {
                    throw new NotSupportedException();
                }
#endif

                glyphImage.TextureOffsetX = (short)dx;
                glyphImage.TextureOffsetY = (short)dy;

                glyphImage.SetImageBuffer(MemBitmapExtensions.CopyImgBuffer(painter.RenderSurface.DestBitmap, w, h), false);
                //copy data from agg canvas to glyph image
                return(glyphImage);
            }
        }
        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);
        }
Example #9
0
        public GlyphImage CreateGlyphImage(GlyphPathBuilder builder, float pxscale)
        {
            //1. create

            var txToVxs = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs);
            //
            //create new one
            var glyphVxs = new VertexStore();

            txToVxs.WriteOutput(glyphVxs, pxscale);
            //find bound
            //--------------------------------------------
            //GlyphImage glyphImg = new GlyphImage()
            RectD bounds = RectD.ZeroIntersection;

            PixelFarm.CpuBlit.VertexProcessing.BoundingRect.GetBoundingRect(new VertexStoreSnap(glyphVxs), ref bounds);

            ////--------------------------------------------
            int w = (int)System.Math.Ceiling(bounds.Width);
            int h = (int)System.Math.Ceiling(bounds.Height);

            if (w < 5)
            {
                w = 5;
            }
            if (h < 5)
            {
                h = 5;
            }

            //translate to positive quadrant
            //
            double dx = (bounds.Left < 0) ? -bounds.Left : 0;
            double dy = (bounds.Bottom < 0) ? -bounds.Bottom : 0;

            //
            dx = Math.Ceiling(dx); //since we need to move it, then move it with integer value
            dy = Math.Ceiling(dy); //since we need to move it, then move it with integer value

            //we need some borders
            int horizontal_margin = 1;                         //'margin' 1px
            int vertical_margin   = 1;                         //margin 1 px

            dx += horizontal_margin;                           //+ left margin
            dy += vertical_margin;                             //+ top margin
                                                               //--------------------------------------------
                                                               //create glyph img
            w = (int)Math.Ceiling(dx + w + horizontal_margin); //+right margin
            h = (int)Math.Ceiling(dy + h + vertical_margin);   //+bottom margin

            ActualBitmap img     = new ActualBitmap(w, h);
            AggPainter   painter = AggPainter.Create(img);

            if (TextureKind == TextureKind.StencilLcdEffect)
            {
                VertexStore vxs2 = new VertexStore();
                glyphVxs.TranslateToNewVxs(dx + 0.33f, dy, vxs2); //offset to proper x of subpixel rendering  ***
                glyphVxs = vxs2;
                //
                painter.UseSubPixelLcdEffect = true;

                //we use white glyph on black bg for this texture
                painter.Clear(Color.Black);
                painter.FillColor = Color.White;
                painter.Fill(glyphVxs);

                //apply sharpen filter
                //painter.DoFilter(new RectInt(0, h, w, 0), 2);
                //painter.DoFilter(new RectInt(0, h, w, 0), 2); //?
            }
            else
            {
                VertexStore vxs2 = new VertexStore();
                glyphVxs.TranslateToNewVxs(dx, dy, vxs2);
                glyphVxs = vxs2;

                painter.UseSubPixelLcdEffect = false;

                if (TextureKind == TextureKind.StencilGreyScale)
                {
                    painter.Clear(Color.Empty);
                    painter.FillColor = Color.Black;
                }
                else
                {
                    painter.Clear(BackGroundColor);
                    painter.FillColor = this.GlyphColor;
                }
                painter.Fill(glyphVxs);
            }
            //
            var glyphImage = new GlyphImage(w, h);

            glyphImage.TextureOffsetX = dx;
            glyphImage.TextureOffsetY = dy;
            glyphImage.SetImageBuffer(ActualBitmapExtensions.CopyImgBuffer(img, w), false);
            //copy data from agg canvas to glyph image
            return(glyphImage);
        }
Example #10
0
        internal unsafe static GlyphImage BuildMsdfFontImage()
        {
            IntPtr shape = MyFtLib.CreateShape();
            IntPtr cnt   = MyFtLib.ShapeAddBlankContour(shape);

            //MyFtLib.ContourAddLinearSegment(cnt, 10, 10, 25, 25);
            //MyFtLib.ContourAddLinearSegment(cnt, 25, 25, 15, 10);
            //MyFtLib.ContourAddLinearSegment(cnt, 15, 10, 10, 10);
            //

            MyFtLib.ContourAddLinearSegment(cnt, 10, 10, 25, 25);
            MyFtLib.ContourAddQuadraticSegment(cnt, 25, 25, 15, 30, 10, 15);
            MyFtLib.ContourAddLinearSegment(cnt, 10, 15, 10, 10);

            double s_left, s_bottom, s_right, s_top;

            MyFtLib.ShapeFindBounds(shape, out s_left, out s_bottom, out s_right, out s_top);
            var glyphBounds = new PixelFarm.Drawing.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.Contours.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);
        }
Example #11
0
        private void button6_Click(object sender, EventArgs e)
        {
            //1. load font
            ActualFont font = GetActualFont("tahoma", 28);// nativeFontStore.LoadFont("tahoma", 28);
            //2. get glyph

            var g1 = font.GetGlyph('C');

            var plans = new List <Typography.TextLayout.GlyphPlan>();

            PixelFarm.Drawing.Text.TextShapingService.GetGlyphPos(font, "ABC".ToCharArray(), 0, 3, plans);


            int[] glyphIndice = new int[] { 1076, 1127, 1164 };
            int   j           = glyphIndice.Length;

            var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder();

            for (int i = 0; i < j; ++i)
            {
                int       codepoint = glyphIndice[i];
                FontGlyph fontGlyph = font.GetGlyphByIndex((uint)codepoint);

                GlyphImage glyphImg = NativeMsdfGen.BuildMsdfFontImage(fontGlyph);
                int        w        = glyphImg.Width;
                int        h        = glyphImg.Height;
                int[]      buffer   = glyphImg.GetImageBuffer();
                NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
                glyphImg.SetImageBuffer(buffer, false);
                atlasBuilder.AddGlyph(codepoint, glyphImg);

                using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                    bmp.UnlockBits(bmpdata);
                    bmp.Save("d:\\WImageTest\\a001_y1_" + codepoint + ".png");
                }
            }
            //----------------------------------------------------
            GlyphImage totalImg = atlasBuilder.BuildSingleImage();

            using (Bitmap bmp = new Bitmap(totalImg.Width, totalImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            {
                int[] buffer = totalImg.GetImageBuffer();
                if (totalImg.IsBigEndian)
                {
                    NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
                    totalImg.SetImageBuffer(buffer, false);
                }

                var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                bmp.UnlockBits(bmpdata);
                bmp.Save("d:\\WImageTest\\a_total.png");
            }

            string fontfilename = "d:\\WImageTest\\a_total.xml";

            atlasBuilder.SaveFontInfo(fontfilename);
            //----------------------------------
        }
Example #12
0
        private void button3_Click(object sender, EventArgs e)
        {
            //1. load font
            string     fontName      = "tahoma";
            int        fontSizeInPts = 28;
            ActualFont font          = GetActualFont(fontName, fontSizeInPts);

            //2. get glyph
            char[] fontChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
            int    j         = fontChars.Length;


            var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder();

            atlasBuilder.SetAtlasInfo(TextureKind.Msdf, fontSizeInPts);

            for (int i = 0; i < j; ++i)
            {
                char c = fontChars[i];

                FontGlyph  fontGlyph = font.GetGlyph(c);
                GlyphImage glyphImg  = NativeMsdfGen.BuildMsdfFontImage(fontGlyph);

                int   w      = glyphImg.Width;
                int   h      = glyphImg.Height;
                int[] buffer = glyphImg.GetImageBuffer();
                NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
                glyphImg.SetImageBuffer(buffer, false);
                atlasBuilder.AddGlyph(0, glyphImg);

                using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    var bmpdata = bmp.LockBits(
                        new System.Drawing.Rectangle(0, 0, w, h),
                        System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                    bmp.UnlockBits(bmpdata);
                    bmp.Save("d:\\WImageTest\\a001_x1_" + (int)c + ".png");
                }
            }
            //----------------------------------------------------
            GlyphImage totalImg = atlasBuilder.BuildSingleImage();

            using (Bitmap bmp = new Bitmap(totalImg.Width, totalImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
            {
                int[] buffer = totalImg.GetImageBuffer();
                if (totalImg.IsBigEndian)
                {
                    NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer);
                    totalImg.SetImageBuffer(buffer, false);
                }

                var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                bmp.UnlockBits(bmpdata);
                bmp.Save("d:\\WImageTest\\a_total.png");
            }

            string fontfilename = "d:\\WImageTest\\a_total.xml";

            atlasBuilder.SaveFontInfo(fontfilename);
            //----------------------------------
        }