Example #1
0
        VertexStore BuildVxsForGlyph(GlyphOutlineBuilder builder, char character, float size)
        {
            //-----------
            //TODO: review here
            builder.Build(character, size);
            var txToVxs = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs);

            VertexStore v2 = new VertexStore();

            using (Tools.BorrowVxs(out var v0))
                using (Tools.BorrowCurveFlattener(out var flattener))
                {
                    txToVxs.WriteOutput(v0);

                    Q1RectD bounds = v0.GetBoundingRect();

                    AffineMat mat = AffineMat.Iden();
                    mat.Scale(1, -1);//flipY
                    mat.Translate(0, bounds.Height);

                    flattener.MakeVxs(v0, mat, v2);
                }
            return(v2);
        }
Example #2
0
        public FormTess()
        {
            InitializeComponent();

            rdoSimpleIncCurveFlattener.Checked         = true;
            rdoSimpleIncCurveFlattener.CheckedChanged += (s, e) => UpdateOutput();
            //
            rdoSubdivCureveFlattener.CheckedChanged += (s, e) => UpdateOutput();

            textBox1.KeyUp += (s, e) => UpdateOutput();


            rdoTessPoly2Tri.CheckedChanged        += (s, e) => UpdateOutput();
            rdoTessSGI.CheckedChanged             += (s, e) => UpdateOutput();
            chkShowContourAnalysis.CheckedChanged += (s, e) => UpdateOutput();

            txtIncrementalTessStep.KeyUp      += (s, e) => UpdateOutput();
            txtDivCurveRecursiveLimit.KeyUp   += (s, e) => UpdateOutput();
            txtDivAngleTolerenceEpsilon.KeyUp += (s, e) => UpdateOutput();

            string testFont = "c:\\Windows\\Fonts\\Tahoma.ttf";

            using (FileStream fs = new FileStream(testFont, FileMode.Open, FileAccess.Read))
            {
                OpenFontReader reader = new OpenFontReader();
                _typeface = reader.Read(fs);
            }

            _tovxs            = new GlyphTranslatorToVxs();
            _glyphPathBuilder = new GlyphOutlineBuilder(_typeface);
            //
            _tessTool = new TessTool();
        }
Example #3
0
 public GlyphNotFoundHelper(
     SimpleBitmapAtlasBuilder atlasBuilder,
     GlyphOutlineBuilder outlineBuilder,
     OnEachGlyph onEachGlyphDel,
     AggGlyphTextureGen aggTextureGen, float sizeInPoints)
 {
     _atlasBuilder   = atlasBuilder;
     _outlineBuilder = outlineBuilder;
     _onEachGlyphDel = onEachGlyphDel;
     _aggTextureGen  = aggTextureGen;
     _sizeInPoints   = sizeInPoints;
 }
Example #4
0
        void RenderWithMsdfImg(Typeface typeface, char testChar, float sizeInPoint)
        {
            _painter.FillColor = PixelFarm.Drawing.Color.Black;
            //p.UseSubPixelRendering = chkLcdTechnique.Checked;
            _painter.Clear(PixelFarm.Drawing.Color.White);
            //----------------------------------------------------
            var builder = new GlyphOutlineBuilder(typeface);

            builder.SetHintTechnique(_glyphRenderOptions.HintTechnique);

            //----------------------------------------------------
            builder.Build(testChar, sizeInPoint);
            //----------------------------------------------------
            var glyphToContour = new ContourBuilder();


            builder.ReadShapes(new GlyphTranslatorToContourBuilder(glyphToContour));
            //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
            Msdfgen.MsdfGenParams genParams = new Msdfgen.MsdfGenParams();
            BitmapAtlasItemSource glyphImg  = MsdfImageGen.CreateMsdfImageV1(glyphToContour, genParams);

            MemBitmap actualImg = MemBitmap.CreateFromCopy(glyphImg.Width, glyphImg.Height, glyphImg.GetImageBuffer());

            _painter.DrawImage(actualImg, 0, 0);

            //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("a001_xn2_" + n + ".png");
            //}

            if (_contourAnalysisOpts.ShowGrid)
            {
                //render grid
                RenderGrids(800, 600, _gridSize, _painter);
            }

            //6. use this util to copy image from Agg actual image to System.Drawing.Bitmap
            PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSize(_destImg, _winBmp);
            //---------------
            //7. just render our bitmap
            _g.Clear(Color.White);
            _g.DrawImage(_winBmp, new Point(30, 20));
        }
Example #5
0
        private void button2_Click(object sender, EventArgs e)
        {
            //EXAMPLE, low-level

            //this show how to render a glyph on screen
            //read font file
            LoadFont();
            //inside a font
            //get some glyph by its name
            //Glyph oneGlyph = _latinModernMathFont.GetGlyphByName("one"); //for get glyph by name

            ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)'1');


            //a glyph contains coordinates of line and curves
            //we transform data inside it to vxs
            //this is done by GlyphContour builder
            GlyphTranslatorToVxs glyphTxToVxs   = new GlyphTranslatorToVxs();
            GlyphOutlineBuilder  outlineBuilder = new GlyphOutlineBuilder(_latinModernMathFont);

            outlineBuilder.BuildFromGlyphIndex(glyphIndex, 20); //read data into outline builder
            outlineBuilder.ReadShapes(glyphTxToVxs);            //translate data inside outline builder to vxs
            using (Tools.BorrowVxs(out var v1, out var v2))
                using (Tools.BorrowAggPainter(_memBmp, out var p))
                {
                    glyphTxToVxs.WriteOutput(v1);
                    //original v1 is head-down
                    Q1RectD bounds = v1.GetBoundingRect(); //with this bounds you also know glyph width/height
                    //we want head up, so => flip it
                    AffineMat aff = AffineMat.Iden();
                    aff.Translate(-bounds.Width / 2, -bounds.Height / 2);
                    aff.Scale(1, -1);
                    aff.Translate(bounds.Width / 2, bounds.Height / 2);

                    aff.TransformToVxs(v1, v2);

                    //copy data
                    //now the glyph data is inside v1
                    //test paint this glyph
                    p.Clear(PixelFarm.Drawing.Color.White);
                    p.Fill(v2, PixelFarm.Drawing.Color.Black);
                }

            //-----------
            CopyBitmapToScreen();
        }
Example #6
0
        public override void Init()
        {
            // YourImplementation.FrameworkInitWinGDI.GetFontLoader().GetInstalledTypeface("tahoma", TypefaceStyle.Regular).FontPath;

            string fontfile = "Data\\";

            this.FillBG = true;
            float sizeInPts = 72;

            using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read))
            {
                var reader = new OpenFontReader();
                //1. read typeface from font file
                Typeface typeFace = reader.Read(fs);
                //2. glyph-to-vxs builder
                var builder = new GlyphOutlineBuilder(typeFace);
                _left_vxs  = BuildVxsForGlyph(builder, 'p', sizeInPts);
                _right_vxs = BuildVxsForGlyph(builder, 'f', sizeInPts);
            }
        }
Example #7
0
        static void CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex, string outputFile)
        {
            //sample

            var reader = new OpenFontReader();

            Typeface typeface = null;

            using (var fs = new FileStream(fontfile, FileMode.Open))
            {
                //1. read typeface from font file
                typeface = reader.Read(fs);
            }

            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphOutlineBuilder(typeface);
            //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked;
            //builder.UseVerticalHinting = this.chkVerticalHinting.Checked;
            //-------------------------------------------------------------
            RequestFont reqFont = new RequestFont(typeface.Name, sizeInPoint);

            var atlasBuilder = new SimpleBitmapAtlasBuilder();

            atlasBuilder.FontFilename = System.IO.Path.GetFileName(fontfile);
            atlasBuilder.FontKey      = reqFont.FontKey;
            //create temp folder for each glyph

            string tempFolderName = "tmp_msdf";

            if (Directory.Exists(tempFolderName))
            {
                //DANGER!
                Directory.Delete(tempFolderName, true);
            }
            Directory.CreateDirectory(tempFolderName);

            if (endGlyphIndex < 1)
            {
                endGlyphIndex = (ushort)(typeface.GlyphCount - 1);
            }


            for (ushort gindex = startGlyphIndex; gindex <= endGlyphIndex; ++gindex)
            {
                //build glyph
                builder.BuildFromGlyphIndex(gindex, sizeInPoint);

                var glyphContourBuilder = new ContourBuilder();
                //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                var genParams = new MsdfGenParams();
                builder.ReadShapes(new GlyphContourBuilder2(glyphContourBuilder));
                //genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64)
                BitmapAtlasItemSource glyphImg = MsdfImageGen.CreateMsdfImageV1(glyphContourBuilder, genParams);
                glyphImg.UniqueInt16Name = gindex;
                atlasBuilder.AddItemSource(glyphImg);

                using (Bitmap bmp = new Bitmap(glyphImg.Width, glyphImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    int[] buffer  = glyphImg.GetImageBuffer();
                    var   bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg.Width, glyphImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length);
                    bmp.UnlockBits(bmpdata);
                    bmp.Save(tempFolderName + "//glyph_" + gindex + ".png");
                }
            }

            MemBitmap glyphImg2 = atlasBuilder.BuildSingleImage(true);

            glyphImg2.SaveImage(outputFile);


            string saveToFile = "a_info.bin";

            using (System.IO.FileStream saveFs = new FileStream(saveToFile, FileMode.Create))
            {
                atlasBuilder.SaveAtlasInfo(saveFs);
                saveFs.Flush();
                saveFs.Close();
            }

            //
            //-----------
            //test read texture info back
            var atlasBuilder2 = new SimpleBitmapAtlasBuilder();

            using (System.IO.FileStream readFromFs = new FileStream(saveToFile, FileMode.Open))
            {
                var readbackFontAtlas = atlasBuilder2.LoadAtlasInfo(readFromFs);
            }
        }
Example #8
0
        void CreateTextureFontFromGlyphIndices(
            Typeface typeface,
            float sizeInPoint,
            HintTechnique hintTechnique,
            SimpleBitmapAtlasBuilder atlasBuilder,
            ushort[] glyphIndices)
        {
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var outlineBuilder = new GlyphOutlineBuilder(typeface);

            outlineBuilder.SetHintTechnique(hintTechnique);
            //
            if (atlasBuilder.TextureKind == TextureKind.Msdf)
            {
                float pxscale       = typeface.CalculateScaleToPixelFromPointSize(sizeInPoint);
                var   msdfGenParams = new Msdfgen.MsdfGenParams();
                int   j             = glyphIndices.Length;

                if (MsdfGenVersion == 3)
                {
                    Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3();

                    for (int i = 0; i < j; ++i)
                    {
                        ushort gindex = glyphIndices[i];
                        //create picture with unscaled version set scale=-1
                        //(we will create glyph contours and analyze them)

                        outlineBuilder.BuildFromGlyphIndex(gindex, -1);

                        var glyphToVxs = new GlyphTranslatorToVxs();
                        outlineBuilder.ReadShapes(glyphToVxs);
                        using (Tools.BorrowVxs(out var vxs))
                        {
                            glyphToVxs.WriteUnFlattenOutput(vxs, pxscale);
                            BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs);
                            glyphImg.UniqueInt16Name = gindex;
                            _onEachGlyphDel?.Invoke(glyphImg);
                            //

                            atlasBuilder.AddItemSource(glyphImg);
                        }
                    }
                }
                else
                {
                    Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3();
                    for (int i = 0; i < j; ++i)
                    {
                        ushort gindex = glyphIndices[i];
                        //create picture with unscaled version set scale=-1
                        //(we will create glyph contours and analyze them)
                        outlineBuilder.BuildFromGlyphIndex(gindex, -1);

                        var glyphToVxs = new GlyphTranslatorToVxs();
                        outlineBuilder.ReadShapes(glyphToVxs);

                        using (Tools.BorrowVxs(out var vxs))
                        {
                            glyphToVxs.WriteUnFlattenOutput(vxs, pxscale);
                            BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs);
                            glyphImg.UniqueInt16Name = gindex;
                            _onEachGlyphDel?.Invoke(glyphImg);

                            atlasBuilder.AddItemSource(glyphImg);
                        }
                    }
                }
            }
            else
            {
                AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen();
                aggTextureGen.TextureKind = atlasBuilder.TextureKind;
                //create reusable agg painter***

                //assume each glyph size= 2 * line height
                //TODO: review here again...
                int tmpMemBmpHeight = (int)(2 * typeface.CalculateRecommendLineSpacing() * typeface.CalculateScaleToPixelFromPointSize(sizeInPoint));
                //create glyph img
                using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square
                {
                    //draw a glyph into tmpMemBmp and then copy to a GlyphImage
                    aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp);
#if DEBUG
                    tmpMemBmp._dbugNote = "CreateGlyphImage()";
#endif

                    int j = glyphIndices.Length;
                    for (int i = 0; i < j; ++i)
                    {
                        //build glyph
                        ushort gindex = glyphIndices[i];
                        outlineBuilder.BuildFromGlyphIndex(gindex, sizeInPoint);

                        BitmapAtlasItemSource glyphImg = aggTextureGen.CreateAtlasItem(outlineBuilder, 1);

                        glyphImg.UniqueInt16Name = gindex;
                        _onEachGlyphDel?.Invoke(glyphImg);
                        atlasBuilder.AddItemSource(glyphImg);
                    }
                }
            }
        }
Example #9
0
        public BitmapAtlasItemSource CreateAtlasItem(GlyphOutlineBuilder builder, float pxscale)
        {
            _txToVxs.Reset();
            //1. builder read shape and translate it with _txToVxs
            builder.ReadShapes(_txToVxs);

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

                _txToVxs.WriteOutput(glyphVxs, pxscale);

                Q1RectD 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;

                    Q1RectD bounds2 = vxs2.GetBoundingRect();
                    if (w < bounds2.Right)
                    {
                        w = (int)Math.Ceiling(bounds2.Right);
                    }
                    //
                    painter.UseLcdEffectSubPixelRendering = true;
                    //we use white glyph on black bg for this texture


                    painter.Clear(Color.Black);
                    painter.FillColor = Color.White;


                    //painter.Clear(Color.FromArgb(0, 255, 255, 255)); //white -transparent
                    //painter.FillColor = Color.Black;


                    //painter.Clear(Color.White);
                    //painter.FillColor = Color.Black;

                    //painter.Clear(Color.Empty);
                    //painter.FillColor = Color.Black;

                    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.UseLcdEffectSubPixelRendering = 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 BitmapAtlasItemSource(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.TextureXOffset = (short)dx;
                glyphImage.TextureYOffset = (short)dy;

                glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(painter.RenderSurface.DestBitmap, w, h), false);
                //copy data from agg canvas to glyph image
                return(glyphImage);
            }
        }
Example #10
0
        void CreateTextureFontFromGlyphIndices(
            HintTechnique hintTechnique,
            SimpleBitmapAtlasBuilder atlasBuilder,
            ushort[] glyphIndices)
        {
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var outlineBuilder = new GlyphOutlineBuilder(_typeface);

            outlineBuilder.SetHintTechnique(hintTechnique);
            //
            AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen();

            GlyphNotFoundHelper glyphNotFoundHelper = new GlyphNotFoundHelper(atlasBuilder,
                                                                              outlineBuilder,
                                                                              _onEachGlyphDel,
                                                                              aggTextureGen,
                                                                              _sizeInPoints);


            //create reusable agg painter***
            //assume each glyph size= 2 * line height
            //TODO: review here again...

            //please note that DPI effect glyph size //***

            int tmpMemBmpHeight = (int)(2 * _typeface.CalculateRecommendLineSpacing() * _px_scale);

            //
            if (atlasBuilder.TextureKind == TextureKind.Msdf)
            {
                var msdfGenParams = new Msdfgen.MsdfGenParams();
                int j             = glyphIndices.Length;

                if (MsdfGenVersion == 3)
                {
                    Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3();

                    for (int i = 0; i < j; ++i)
                    {
                        ushort gindex = glyphIndices[i];
                        //create picture with unscaled version set scale=-1
                        //(we will create glyph contours and analyze them)

                        var glyphToVxs = new GlyphTranslatorToVxs();
                        outlineBuilder.BuildFromGlyphIndex(gindex, -1, glyphToVxs);

                        using (Tools.BorrowVxs(out var vxs))
                        {
                            glyphToVxs.WriteUnFlattenOutput(vxs, _px_scale);
                            BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs);
                            glyphImg.UniqueInt16Name = gindex;
                            _onEachGlyphDel?.Invoke(glyphImg);
                            //

                            atlasBuilder.AddItemSource(glyphImg);
                        }
                    }
                }
                else
                {
                    //use gen3
                    Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3();
                    for (int i = 0; i < j; ++i)
                    {
                        ushort gindex = glyphIndices[i];
                        //create picture with unscaled version set scale=-1
                        //(we will create glyph contours and analyze them)

                        var glyphToVxs = new GlyphTranslatorToVxs();
                        outlineBuilder.BuildFromGlyphIndex(gindex, -1, glyphToVxs);

                        using (Tools.BorrowVxs(out var vxs))
                        {
                            glyphToVxs.WriteUnFlattenOutput(vxs, _px_scale);
                            BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs);
                            glyphImg.UniqueInt16Name = gindex;
                            _onEachGlyphDel?.Invoke(glyphImg);

                            atlasBuilder.AddItemSource(glyphImg);
                        }
                    }
                }
                return;
            }
            else if (atlasBuilder.TextureKind == TextureKind.Bitmap)
            {
                //generate color bitmap atlas
                int j = glyphIndices.Length;

                GlyphMeshStore glyphMeshStore = new GlyphMeshStore();
                glyphMeshStore.SetFont(_typeface, _sizeInPoints);
                aggTextureGen.TextureKind = TextureKind.Bitmap;

                using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square
                {
                    aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp);
#if DEBUG
                    tmpMemBmp._dbugNote = "CreateGlyphImage()";
#endif


                    if (_typeface.HasColorTable())
                    {
                        //outline glyph

                        for (int i = 0; i < j; ++i)
                        {
                            ushort gindex = glyphIndices[i];
                            if (!_typeface.COLRTable.LayerIndices.TryGetValue(gindex, out ushort colorLayerStart))
                            {
                                //not found, then render as normal
                                //TODO: impl

                                //create glyph img
                                glyphNotFoundHelper.HandleNotFoundGlyph(gindex);
                            }
                            else
                            {
                                //TODO: review this again
                                GlyphBitmap glyphBmp = GetGlyphBitmapFromColorOutlineGlyph(gindex, glyphMeshStore, colorLayerStart);
                                if (glyphBmp == null)
                                {
                                    glyphNotFoundHelper.HandleNotFoundGlyph(gindex);
                                }
                                else
                                {
                                    int w = glyphBmp.Width;
                                    int h = glyphBmp.Height;

                                    BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height);

                                    glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX;
                                    glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY;

                                    //
                                    glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false);

                                    glyphImage.UniqueInt16Name = gindex;
                                    _onEachGlyphDel?.Invoke(glyphImage);
                                    atlasBuilder.AddItemSource(glyphImage);

                                    //clear
                                    glyphBmp.Bitmap.Dispose();
                                    glyphBmp.Bitmap = null;
                                }
                            }
                        }
                    }
                    else if (_typeface.IsBitmapFont)
                    {
                        aggTextureGen.TextureKind = TextureKind.Bitmap;
                        //test this with Noto Color Emoji
                        for (int i = 0; i < j; ++i)
                        {
                            ushort gindex = glyphIndices[i];

                            GlyphBitmap glyphBmp = GetGlyphBitmapFromBitmapFont(gindex);
                            if (glyphBmp == null)
                            {
                                glyphNotFoundHelper.HandleNotFoundGlyph(gindex);
                            }
                            else
                            {
                                int w = glyphBmp.Width;
                                int h = glyphBmp.Height;

                                BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height);

                                glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX;
                                glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY;

                                //
                                glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false);

                                glyphImage.UniqueInt16Name = gindex;
                                _onEachGlyphDel?.Invoke(glyphImage);
                                atlasBuilder.AddItemSource(glyphImage);

                                //clear
                                glyphBmp.Bitmap.Dispose();
                                glyphBmp.Bitmap = null;
                            }
                        }
                    }
                    else if (_typeface.HasSvgTable())
                    {
                        aggTextureGen.TextureKind = TextureKind.Bitmap;
                        //test this with TwitterEmoji
                        //generate membitmap from svg
#if DEBUG
                        System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch();
                        sw1.Start();
#endif

                        for (int i = 0; i < j; ++i)
                        {
                            //TODO: add mutli-threads / async version

                            ushort      gindex   = glyphIndices[i];
                            GlyphBitmap glyphBmp = GetGlyphBitmapFromSvg(gindex);
                            if (glyphBmp == null)
                            {
                                glyphNotFoundHelper.HandleNotFoundGlyph(gindex);
                            }
                            else
                            {
                                int w = glyphBmp.Width;
                                int h = glyphBmp.Height;

                                BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height);

                                glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX;
                                glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY;

                                //
                                glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false);

                                glyphImage.UniqueInt16Name = gindex;
                                _onEachGlyphDel?.Invoke(glyphImage);
                                atlasBuilder.AddItemSource(glyphImage);

                                //clear
                                glyphBmp.Bitmap.Dispose();
                                glyphBmp.Bitmap = null;
                            }
                        }

#if DEBUG
                        sw1.Stop();
                        long ms = sw1.ElapsedMilliseconds;
#endif
                    }
                    return; //NO go below //***
                } //END using
            }


            //---------------------------
            //OTHERS....
            {
                aggTextureGen.TextureKind = atlasBuilder.TextureKind;
                //create glyph img
                using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square
                {
                    //draw a glyph into tmpMemBmp and then copy to a GlyphImage
                    aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp);
#if DEBUG
                    tmpMemBmp._dbugNote = "CreateGlyphImage()";
#endif

                    int j = glyphIndices.Length;
                    for (int i = 0; i < j; ++i)
                    {
                        //build glyph
                        ushort gindex = glyphIndices[i];
                        outlineBuilder.BuildFromGlyphIndex(gindex, _sizeInPoints);

                        BitmapAtlasItemSource glyphImg = aggTextureGen.CreateAtlasItem(outlineBuilder, 1);

                        glyphImg.UniqueInt16Name = gindex;
                        _onEachGlyphDel?.Invoke(glyphImg);
                        atlasBuilder.AddItemSource(glyphImg);
                    }
                }
            }
        }
Example #11
0
        void UpdateOutput()
        {
            string oneChar = this.textBox1.Text.Trim();

            if (string.IsNullOrEmpty(oneChar))
            {
                return;
            }
            //
            char selectedChar = oneChar[0];

            //
            //
            //selectedChar = 'e';
            if (_g == null)
            {
                _g = this.panel1.CreateGraphics();
            }

            _g.Clear(Color.White);

            //-------
            //string testFont = "c:\\Windows\\Fonts\\Tahoma.ttf";
            string testFont = @"Test\SourceSansPro-Regular.ttf";


            using (FileStream fs = new FileStream(testFont, FileMode.Open, FileAccess.Read))
            {
                OpenFontReader reader   = new OpenFontReader();
                Typeface       typeface = reader.Read(fs);


                var writablePath = new WritablePath();
                var txToPath     = new GlyphTranslatorToPath(); //translator
                txToPath.SetOutput(writablePath);

                var builder = new GlyphOutlineBuilder(typeface);
                builder.BuildFromGlyphIndex(typeface.GetGlyphIndex(selectedChar), 300, txToPath);

                //------
                //
                //**flatten contour before send to Tess***
                var curveFlattener = new SimpleCurveFlattener();

                if (rdoSimpleIncCurveFlattener.Checked)
                {
                    if (int.TryParse(txtIncrementalTessStep.Text, out int incSteps))
                    {
                        curveFlattener.IncrementalStep = incSteps;
                    }
                    curveFlattener.FlattenMethod = CurveFlattenMethod.Inc;
                }
                else
                {
                    if (double.TryParse(txtDivAngleTolerenceEpsilon.Text, out double angleTolerenceEpsilon))
                    {
                        //convert degree to rad
                        curveFlattener.DivCurveAngleTolerenceEpsilon = DegToRad(angleTolerenceEpsilon);
                    }
                    if (int.TryParse(txtDivCurveRecursiveLimit.Text, out int recuvesiveLim))
                    {
                        curveFlattener.DivCurveRecursiveLimit = recuvesiveLim;
                    }
                    curveFlattener.FlattenMethod = CurveFlattenMethod.Div;
                }
                _glyphPoints2 = curveFlattener.Flatten(writablePath._points, out _contourEnds);

                ////--------------------------------------
                ////raw glyph points
                //int j = glyphPoints.Length;
                //float scale = typeface.CalculateToPixelScaleFromPointSize(256);
                //glyphPoints2 = new float[j * 2];
                //int n = 0;
                //for (int i = 0; i < j; ++i)
                //{
                //    GlyphPointF pp = glyphPoints[i];
                //    glyphPoints2[n] = pp.X * scale;
                //    n++;
                //    glyphPoints2[n] = pp.Y * scale;
                //    n++;
                //}
                ////--------------------------------------
            }
            DrawOutput();
        }