예제 #1
0
        public void DrawString(char[] text, int startAt, int len, double x, double y)
        {
            float ox = canvasPainter.OriginX;
            float oy = canvasPainter.OriginY;

            //1. update some props..
            //2. update current type face
            UpdateTypefaceAndGlyphBuilder();
            Typeface typeface = _glyphPathBuilder.Typeface;
            //3. layout glyphs with selected layout technique
            //TODO: review this again, we should use pixel?

            float fontSizePoint = this.FontSizeInPoints;
            float scale         = typeface.CalculateToPixelScaleFromPointSize(fontSizePoint);

            _outputGlyphPlans.Clear();
            _glyphLayout.Layout(typeface, text, startAt, len, _outputGlyphPlans);
            //4. render each glyph
            int j = _outputGlyphPlans.Count;

            //---------------------------------------------------
            //consider use cached glyph, to increase performance
            hintGlyphCollection.SetCacheInfo(typeface, fontSizePoint, this.HintTechnique);
            //---------------------------------------------------
            for (int i = 0; i < j; ++i)
            {
                GlyphPlan glyphPlan = _outputGlyphPlans[i];
                //-----------------------------------
                //TODO: review here ***
                //PERFORMANCE revisit here
                //if we have create a vxs we can cache it for later use?
                //-----------------------------------
                VertexStore glyphVxs;
                if (!hintGlyphCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out glyphVxs))
                {
                    //if not found then create new glyph vxs and cache it
                    _glyphPathBuilder.SetHintTechnique(this.HintTechnique);
                    _glyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, fontSizePoint);
                    //-----------------------------------
                    _tovxs.Reset();
                    _glyphPathBuilder.ReadShapes(_tovxs);

                    //TODO: review here,
                    //float pxScale = _glyphPathBuilder.GetPixelScale();
                    glyphVxs = new VertexStore();
                    _tovxs.WriteOutput(glyphVxs, _vxsPool);
                    //
                    hintGlyphCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, glyphVxs);
                }
                canvasPainter.SetOrigin((float)(glyphPlan.x * scale + x), (float)(glyphPlan.y * scale + y));
                canvasPainter.Fill(glyphVxs);
            }
            //restore prev origin
            canvasPainter.SetOrigin(ox, oy);
        }
예제 #2
0
        VertexStore BuildVxsForGlyph(GlyphPathBuilder builder, char character, int size, int resolution)
        {
            //TODO: review here
            builder.Build(character, size);
            var txToVxs = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs);
            VertexStore v0 = _vxsPool.GetFreeVxs();

            txToVxs.WriteOutput(v0);
            var mat = PixelFarm.Agg.Transform.Affine.NewMatix(
                //translate
                new PixelFarm.Agg.Transform.AffinePlan(
                    PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, 10, 10),
                //scale
                new PixelFarm.Agg.Transform.AffinePlan(
                    PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, 1, 1)
                );

            VertexStore v1 = _vxsPool.GetFreeVxs();
            VertexStore v2 = new VertexStore();

            mat.TransformToVxs(v0, v1);
            curveFlattener.MakeVxs(v0, v2);

            _vxsPool.Release(ref v0);
            _vxsPool.Release(ref v1);

            return(v2);
        }
예제 #3
0
        VertexStore BuildVxsForGlyph(GlyphPathBuilder builder, char character, int size, int resolution)
        {
            //-----------
            //TODO: review here
            builder.Build(character, size);
            var txToVxs = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs);

            VertexStore v2 = new VertexStore();

            using (VxsTemp.Borrow(out var v0))
            {
                txToVxs.WriteOutput(v0);
                var mat = PixelFarm.CpuBlit.VertexProcessing.Affine.NewMatix(
                    //translate
                    new PixelFarm.CpuBlit.VertexProcessing.AffinePlan(
                        PixelFarm.CpuBlit.VertexProcessing.AffineMatrixCommand.Translate, 10, 10),
                    //scale
                    new PixelFarm.CpuBlit.VertexProcessing.AffinePlan(
                        PixelFarm.CpuBlit.VertexProcessing.AffineMatrixCommand.Scale, 1, 1)
                    );
                //mat.TransformToVxs(v0, v1);
                _curveFlattener.MakeVxs(v0, mat, v2);
            }
            return(v2);
        }
예제 #4
0
        static void CreateSampleMsdfTextureFont(
            string fontfile, float sizeInPoint,
            char[] chars, string outputFile)
        {
            //sample
            var reader = new OpenFontReader();

            using (var fs = new FileStream(fontfile, FileMode.Open))
            {
                //1. read typeface from font file
                Typeface typeface = reader.Read(fs);
                //sample: create sample msdf texture
                //-------------------------------------------------------------
                var builder = new GlyphPathBuilder(typeface);
                //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked;
                //builder.UseVerticalHinting = this.chkVerticalHinting.Checked;
                //-------------------------------------------------------------
                var atlasBuilder = new SimpleFontAtlasBuilder();

                MsdfGenParams msdfGenParams = new MsdfGenParams();

                int j = chars.Length;
                for (int i = 0; i < j; ++i)
                {
                    //build glyph
                    ushort gindex = typeface.LookupIndex(chars[i]);
                    builder.BuildFromGlyphIndex(gindex, -1);

                    var glyphToContour = new GlyphContourBuilder();
                    //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                    builder.ReadShapes(glyphToContour);
                    msdfGenParams.shapeScale = 1f / 64;
                    GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams);
                    atlasBuilder.AddGlyph(gindex, glyphImg);
                    int w = glyphImg.Width;
                    int h = glyphImg.Height;
                    using (Bitmap bmp = new Bitmap(glyphImg.Width, glyphImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                    {
                        var   bmpdata   = bmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                        int[] imgBuffer = glyphImg.GetImageBuffer();
                        System.Runtime.InteropServices.Marshal.Copy(imgBuffer, 0, bmpdata.Scan0, imgBuffer.Length);
                        bmp.UnlockBits(bmpdata);
                        bmp.Save("d:\\WImageTest\\a001_xn2_" + (chars[i]) + ".png");
                    }
                }

                var glyphImg2 = atlasBuilder.BuildSingleImage();
                using (Bitmap bmp = new 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");
            }
        }
예제 #5
0
        private void InitGlyphPointsAndContourEnds(char c)
        {
            try {
                using (FileStream fs = File.OpenRead(ttfPath)) {
                    OpenFontReader reader   = new OpenFontReader();
                    Typeface       typeface = reader.Read(fs);

                    var builder = new GlyphPathBuilder(typeface);
                    builder.BuildFromGlyphIndex(typeface.LookupIndex(c), 300);

                    var txToPath     = new GlyphTranslatorToPath();
                    var writablePath = new WritablePath();
                    txToPath.SetOutput(writablePath);
                    builder.ReadShapes(txToPath);

                    var     curveFlattener = new SimpleCurveFlattener();
                    float[] flattenPoints  = curveFlattener.Flatten(
                        writablePath._points, out _contourEnds);
                    _glyphPoints2 = flattenPoints;
                }
            }
            catch (Exception) {
                ClearGlyphData();
                pnlGlyph.Invalidate();
            }
        }
        void CreateTextureFontFromGlyphIndices(
            Typeface typeface,
            float sizeInPoint,
            HintTechnique hintTechnique,
            SimpleFontAtlasBuilder atlasBuilder,
            bool applyFilter,
            ushort[] glyphIndices)
        {
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique(hintTechnique);
            //
            if (atlasBuilder.TextureKind == TextureKind.Msdf)
            {
                MsdfGenParams msdfGenParams = new MsdfGenParams();
                int           j             = glyphIndices.Length;
                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)
                    builder.BuildFromGlyphIndex(gindex, -1);
                    var glyphToContour = new GlyphContourBuilder();
                    builder.ReadShapes(glyphToContour);
                    //msdfgen with  scale the glyph to specific shapescale
                    msdfGenParams.shapeScale = 1f / 64; //as original
                    GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams);
                    //
                    atlasBuilder.AddGlyph(gindex, glyphImg);
                }
            }
            else
            {
                AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen();
                aggTextureGen.TextureKind = atlasBuilder.TextureKind;
                int j = glyphIndices.Length;
                for (int i = 0; i < j; ++i)
                {
                    //build glyph
                    ushort gindex = glyphIndices[i];
                    builder.BuildFromGlyphIndex(gindex, sizeInPoint);

                    GlyphImage glyphImg = aggTextureGen.CreateGlyphImage(builder, 1);
                    if (applyFilter)
                    {
                        glyphImg = Sharpen(glyphImg, 1);
                        //TODO:
                        //the filter make the image shift x and y 1 px
                        //temp fix with this,
                        glyphImg.TextureOffsetX += 1;
                        glyphImg.TextureOffsetY += 1;
                    }
                    //
                    atlasBuilder.AddGlyph(gindex, glyphImg);
                }
            }
        }
예제 #7
0
        void RenderWithMiniAgg(Typeface typeface, char testChar, float sizeInPoint)
        {
            //----------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique((HintTechnique)lstHintList.SelectedItem);
            //----------------------------------------------------
            builder.Build(testChar, sizeInPoint);
            var txToVxs1 = new GlyphTranslatorToVxs();

            builder.ReadShapes(txToVxs1);

            VertexStore vxs = new VertexStore();

            txToVxs1.WriteOutput(vxs, _vxsPool);

            //----------------------------------------------------
            p.UseSubPixelRendering = chkLcdTechnique.Checked;

            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            p.Clear(PixelFarm.Drawing.Color.White);

            if (chkFillBackground.Checked)
            {
                //5.2
                p.FillColor = PixelFarm.Drawing.Color.Black;
                //5.3
                p.Fill(vxs);
            }
            if (chkBorder.Checked)
            {
                //5.4
                // p.StrokeWidth = 3;
                p.StrokeColor = PixelFarm.Drawing.Color.Green;
                //user can specific border width here...
                //p.StrokeWidth = 2;
                //5.5
                p.Draw(vxs);
            }



            if (chkShowGrid.Checked)
            {
                //render grid
                RenderGrid(800, 600, _gridSize, p);
            }



            //6. use this util to copy image from Agg actual image to System.Drawing.Bitmap
            PixelFarm.Agg.Imaging.BitmapHelper.CopyToGdiPlusBitmapSameSize(destImg, winBmp);
            //---------------
            //7. just render our bitmap
            g.Clear(Color.White);
            g.DrawImage(winBmp, new Point(30, 20));
        }
예제 #8
0
        public override void DrawFromGlyphPlans(GlyphPlanSequence seq, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

            //draw data in glyph plan
            //3. render each glyph

            float sizeInPoints = this.FontSizeInPoints;
            float pxscale      = _currentTypeface.CalculateScaleToPixelFromPointSize(sizeInPoints);

            //
            _glyphMeshCollections.SetCacheInfo(this.Typeface, sizeInPoints, this.HintTechnique);


            //this draw a single line text span***
            Graphics g = this.TargetGraphics;

            float cx = 0;
            float cy = 0;

            var snapToPxScale = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, pxscale);

            while (snapToPxScale.Read())
            {
                GraphicsPath foundPath;

                if (!_glyphMeshCollections.TryGetCacheGlyph(snapToPxScale.CurrentGlyphIndex, out foundPath))
                {
                    //if not found then create a new one
                    _currentGlyphPathBuilder.BuildFromGlyphIndex(snapToPxScale.CurrentGlyphIndex, sizeInPoints);
                    _txToGdiPath.Reset();
                    _currentGlyphPathBuilder.ReadShapes(_txToGdiPath);
                    foundPath = _txToGdiPath.ResultGraphicsPath;

                    //register
                    _glyphMeshCollections.RegisterCachedGlyph(snapToPxScale.CurrentGlyphIndex, foundPath);
                }
                //------
                //then move pen point to the position we want to draw a glyph

                cx = (float)Math.Round(snapToPxScale.ExactX + x);
                cy = (float)Math.Floor(snapToPxScale.ExactY + y);

                g.TranslateTransform(cx, cy);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, foundPath);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, foundPath);
                }
                //and then we reset back ***
                g.TranslateTransform(-cx, -cy);
            }
        }
예제 #9
0
        public override void DrawFromGlyphPlans(List <GlyphPlan> glyphPlanList, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

            //draw data in glyph plan
            //3. render each glyph

            float sizeInPoints = this.FontSizeInPoints;
            float scale        = _currentTypeface.CalculateToPixelScaleFromPointSize(sizeInPoints);

            //
            _glyphMeshCollections.SetCacheInfo(this.Typeface, sizeInPoints, this.HintTechnique);


            //this draw a single line text span***
            int endBefore = startAt + len;

            Graphics g = this.TargetGraphics;

            for (int i = startAt; i < endBefore; ++i)
            {
                GlyphPlan glyphPlan = glyphPlanList[i];

                //check if we have a cache of this glyph
                //if not -> create it

                GraphicsPath foundPath;
                if (!_glyphMeshCollections.TryGetCacheGlyph(glyphPlan.glyphIndex, out foundPath))
                {
                    //if not found then create a new one
                    _currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints);
                    _txToGdiPath.Reset();
                    _currentGlyphPathBuilder.ReadShapes(_txToGdiPath);
                    foundPath = _txToGdiPath.ResultGraphicsPath;

                    //register
                    _glyphMeshCollections.RegisterCachedGlyph(glyphPlan.glyphIndex, foundPath);
                }
                //------
                //then move pen point to the position we want to draw a glyph
                float tx = x + glyphPlan.ExactX;
                float ty = y + glyphPlan.ExactY;
                g.TranslateTransform(tx, ty);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, foundPath);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, foundPath);
                }
                //and then we reset back ***
                g.TranslateTransform(-tx, -ty);
            }
        }
예제 #10
0
        /// <summary>
        /// generate glyph run into a given textRun
        /// </summary>
        /// <param name="outputTextRun"></param>
        /// <param name="charBuffer"></param>
        /// <param name="start"></param>
        /// <param name="len"></param>
        public void GenerateGlyphRuns(TextRun outputTextRun, char[] charBuffer, int start, int len)
        {
            // layout glyphs with selected layout technique
            float sizeInPoints = this.FontSizeInPoints;

            outputTextRun.typeface     = this.CurrentTypeFace;
            outputTextRun.sizeInPoints = sizeInPoints;

            //in this version we store original glyph into the mesh collection
            //and then we scale it later, so I just specific font size=0 (you can use any value)
            _glyphMeshCollection.SetCacheInfo(this.CurrentTypeFace, 0, this.HintTechnique);

            outputGlyphPlans.Clear();
            glyphLayout.Typeface = this.CurrentTypeFace;
            glyphLayout.GenerateGlyphPlans(charBuffer, start, len, outputGlyphPlans, null);
            // render each glyph
            int planCount = outputGlyphPlans.Count;

            for (var i = 0; i < planCount; ++i)
            {
                pathTranslator.Reset();
                //----
                //glyph path
                //----
                GlyphPlan glyphPlan = outputGlyphPlans[i];
                //
                //1. check if we have this glyph in cache?
                //if yes, not need to build it again
                ProcessedGlyph processGlyph;
                float[]        tessData = null;

                if (!_glyphMeshCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out processGlyph))
                {
                    //if not found the  create a new one and register it
                    var writablePath = new WritablePath();
                    pathTranslator.SetOutput(writablePath);
                    currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints);
                    currentGlyphPathBuilder.ReadShapes(pathTranslator);

                    //-------
                    //do tess
                    int[]   endContours;
                    float[] flattenPoints = _curveFlattener.Flatten(writablePath._points, out endContours);
                    int     nTessElems;
                    tessData = _tessTool.TessPolygon(flattenPoints, endContours, out nTessElems);
                    //-------
                    processGlyph = new ProcessedGlyph(tessData, (ushort)nTessElems);
                    _glyphMeshCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, processGlyph);
                }

                outputTextRun.AddGlyph(
                    new GlyphRun(glyphPlan,
                                 processGlyph.tessData,
                                 processGlyph.tessNElements));
            }
        }
예제 #11
0
        static void CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex, string outputFile)
        {
            //sample
            var reader = new OpenFontReader();

            using (var fs = new FileStream(fontfile, FileMode.Open))
            {
                //1. read typeface from font file
                Typeface typeface = reader.Read(fs);
                //sample: create sample msdf texture
                //-------------------------------------------------------------
                var builder = new GlyphPathBuilder(typeface);
                //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked;
                //builder.UseVerticalHinting = this.chkVerticalHinting.Checked;
                //-------------------------------------------------------------
                var atlasBuilder = new SimpleFontAtlasBuilder();


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

                    var glyphToContour = new GlyphContourBuilder();
                    //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                    var genParams = new MsdfGenParams();
                    builder.ReadShapes(glyphToContour);
                    genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64)
                    GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams);
                    atlasBuilder.AddGlyph(gindex, 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_xn2_" + n + ".png");
                    //}
                }

                var glyphImg2 = atlasBuilder.BuildSingleImage();
                using (Bitmap bmp = new 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");
            }
        }
예제 #12
0
        public override void DrawGlyphPlanList(List <GlyphPlan> glyphPlanList, int startAt, int len, float xpos, float ypos)
        {
            CanvasPainter canvasPainter = this.TargetCanvasPainter;
            Typeface      typeface      = _glyphPathBuilder.Typeface;
            //3. layout glyphs with selected layout technique
            //TODO: review this again, we should use pixel?

            float fontSizePoint = this.FontSizeInPoints;
            float scale         = typeface.CalculateFromPointToPixelScale(fontSizePoint);


            //4. render each glyph
            float ox        = canvasPainter.OriginX;
            float oy        = canvasPainter.OriginY;
            int   endBefore = startAt + len;

            //---------------------------------------------------
            //consider use cached glyph, to increase performance
            hintGlyphCollection.SetCacheInfo(typeface, fontSizePoint, this.HintTechnique);
            //---------------------------------------------------
            for (int i = startAt; i < endBefore; ++i)
            {
                GlyphPlan glyphPlan = glyphPlanList[i];
                //-----------------------------------
                //TODO: review here ***
                //PERFORMANCE revisit here
                //if we have create a vxs we can cache it for later use?
                //-----------------------------------
                VertexStore glyphVxs;
                if (!hintGlyphCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out glyphVxs))
                {
                    //if not found then create new glyph vxs and cache it
                    _glyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, fontSizePoint);
                    //-----------------------------------
                    _tovxs.Reset();
                    _glyphPathBuilder.ReadShapes(_tovxs);

                    //TODO: review here,
                    //float pxScale = _glyphPathBuilder.GetPixelScale();
                    glyphVxs = new VertexStore();
                    _tovxs.WriteOutput(glyphVxs, _vxsPool);
                    //
                    hintGlyphCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, glyphVxs);
                }
                canvasPainter.SetOrigin((float)(glyphPlan.x * scale + xpos), (float)(glyphPlan.y * scale + ypos));
                canvasPainter.Fill(glyphVxs);
            }
            //restore prev origin
            canvasPainter.SetOrigin(ox, oy);
        }
예제 #13
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 GlyphPathBuilder(typeface);

            builder.SetHintTechnique(_glyphRenderOptions.HintTechnique);

            //----------------------------------------------------
            builder.Build(testChar, sizeInPoint);
            //----------------------------------------------------
            var glyphToContour = new GlyphContourBuilder();
            var msdfGenPars    = new MsdfGenParams();

            builder.ReadShapes(glyphToContour);
            //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
            MsdfGenParams genParams = new MsdfGenParams();
            GlyphImage    glyphImg  = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams);

            var actualImg = ActualImage.CreateFromBuffer(glyphImg.Width, glyphImg.Height, PixelFormat.ARGB32, 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("d:\\WImageTest\\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.Agg.Imaging.BitmapHelper.CopyToGdiPlusBitmapSameSize(destImg, winBmp);
            //---------------
            //7. just render our bitmap
            g.Clear(Color.White);
            g.DrawImage(winBmp, new Point(30, 20));
        }
예제 #14
0
        public override void DrawGlyphPlanList(List <GlyphPlan> glyphPlanList, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

            //draw data in glyph plan
            //3. render each glyph
            System.Drawing.Drawing2D.Matrix scaleMat = null;
            float sizeInPoints = this.FontSizeInPoints;
            float scale        = _currentTypeface.CalculateFromPointToPixelScale(sizeInPoints);
            //this draw a single line text span***
            int endBefore = startAt + len;

            Graphics g = this.TargetGraphics;

            for (int i = startAt; i < endBefore; ++i)
            {
                GlyphPlan glyphPlan = glyphPlanList[i];
                _currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints);
                //
                scaleMat = new System.Drawing.Drawing2D.Matrix(
                    1, 0,                   //scale x
                    0, 1,                   //scale y
                    x + glyphPlan.x * scale,
                    y + glyphPlan.y * scale //xpos,ypos
                    );

                //
                _txToGdiPath.Reset();
                _currentGlyphPathBuilder.ReadShapes(_txToGdiPath);
                System.Drawing.Drawing2D.GraphicsPath path = _txToGdiPath.ResultGraphicsPath;
                path.Transform(scaleMat);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, path);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, path);
                }
            }
        }
예제 #15
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);
        }
예제 #16
0
        static SimpleFontAtlasBuilder CreateSampleMsdfTextureFont(
            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);
            MsdfGenParams genParams    = new MsdfGenParams();
            var           atlasBuilder = new SimpleFontAtlasBuilder();

            atlasBuilder.SetAtlasInfo(TextureKind.Msdf, sizeInPoint);
            foreach (ushort gindex in glyphIndexIter)
            {
                //build glyph
                builder.BuildFromGlyphIndex(gindex, -1); //use original glyph size (assign -1)
                var glyphToContour = new GlyphContourBuilder();


                //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                builder.ReadShapes(glyphToContour);
                genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64)
                GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams);

                atlasBuilder.AddGlyph(gindex, glyphImg);


                //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_xn2_" + c + ".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);
        }
예제 #17
0
        public void RenderChar(char testChar, HintTechnique hint)
        {
            builder.SetHintTechnique(hint);
#if DEBUG
            GlyphBoneJoint.dbugTotalId        = 0;//reset
            builder.dbugAlwaysDoCurveAnalysis = true;
#endif
            _infoView.Clear();
            _latestHint = hint;
            _testChar   = testChar;
            //----------------------------------------------------
            //
            builder.Build(testChar, _sizeInPoint);
            var txToVxs1 = new GlyphTranslatorToVxs();
            builder.GlyphDynamicEdgeOffset = this.GlyphEdgeOffset;

            builder.ReadShapes(txToVxs1);

#if DEBUG
            var ps = txToVxs1.dbugGetPathWriter();
            _infoView.ShowOrgBorderInfo(ps.Vxs);
#endif
            PixelFarm.Drawing.VertexStore vxs = new PixelFarm.Drawing.VertexStore();

            txToVxs1.WriteOutput(vxs);
            //----------------------------------------------------

            //----------------------------------------------------
            painter.UseSubPixelLcdEffect = this.UseLcdTechnique;
            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            painter.Clear(PixelFarm.Drawing.Color.White);

            RectD bounds = new RectD();
            BoundingRect.GetBoundingRect(new PixelFarm.Drawing.VertexStoreSnap(vxs), ref bounds);
            //----------------------------------------------------
            float scale = _typeface.CalculateScaleToPixelFromPointSize(_sizeInPoint);
            _pxscale = scale;
            this._infoView.PxScale = scale;


            var   left2   = 0;
            int   floor_1 = (int)left2;
            float diff    = left2 - floor_1;
            //----------------------------------------------------
            if (OffsetMinorX)
            {
                MinorOffsetInfo = left2.ToString() + " =>" + floor_1 + ",diff=" + diff;
            }
            else
            {
                MinorOffsetInfo = left2.ToString();
            }


            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            painter.Clear(PixelFarm.Drawing.Color.White);

            if (FillBackGround)
            {
                //5.2
                painter.FillColor = PixelFarm.Drawing.Color.Black;

                float xpos = 5;// - diff;
                if (OffsetMinorX)
                {
                    xpos -= diff;
                }

                painter.SetOrigin(xpos, 10);
                painter.Fill(vxs);
            }
            if (DrawBorder)
            {
                //5.4
                painter.StrokeColor = PixelFarm.Drawing.Color.Green;
                //user can specific border width here...
                //5.5
                painter.Draw(vxs);
                //--------------
                int    markOnVertexNo = _infoView.DebugMarkVertexCommand;
                double x, y;
                vxs.GetVertex(markOnVertexNo, out x, out y);
                painter.FillRect(x, y, 4, 4, PixelFarm.Drawing.Color.Red);
                //--------------
                _infoView.ShowFlatternBorderInfo(vxs);
                //--------------
            }
#if DEBUG
            builder.dbugAlwaysDoCurveAnalysis = false;
#endif

            if (ShowTess)
            {
                RenderTessTesult();
            }

            //if (DrawDynamicOutline)
            //{
            //    GlyphDynamicOutline dynamicOutline = builder.LatestGlyphFitOutline;
            //    WalkDynamicOutline(painter, dynamicOutline, scale, DrawRegenerateOutline);

            //}
        }
예제 #18
0
        void CreateTextureFontFromGlyphIndices(
            Typeface typeface,
            float sizeInPoint,
            HintTechnique hintTechnique,
            SimpleFontAtlasBuilder atlasBuilder,
            bool applyFilter,
            ushort[] glyphIndices)
        {
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique(hintTechnique);
            //
            if (atlasBuilder.TextureKind == TextureKind.Msdf)
            {
                MsdfGenParams msdfGenParams = new MsdfGenParams();
                int           j             = glyphIndices.Length;
                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)
                    builder.BuildFromGlyphIndex(gindex, -1);
                    var glyphToContour = new GlyphContourBuilder();
                    builder.ReadShapes(glyphToContour);
                    //msdfgen with  scale the glyph to specific shapescale
                    msdfGenParams.shapeScale = 1f / 64; //as original
                    GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams);
                    //
                    atlasBuilder.AddGlyph(gindex, 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];
                        builder.BuildFromGlyphIndex(gindex, sizeInPoint);

                        GlyphImage glyphImg = aggTextureGen.CreateGlyphImage(builder, 1);
                        if (applyFilter)
                        {
                            glyphImg = Sharpen(glyphImg, 1);
                            //TODO:
                            //the filter make the image shift x and y 1 px
                            //temp fix with this,
                            glyphImg.TextureOffsetX += 1;
                            glyphImg.TextureOffsetY += 1;
                        }
                        //
                        atlasBuilder.AddGlyph(gindex, glyphImg);
                    }
                }
            }
        }
예제 #19
0
        /// <summary>
        /// generate glyph run into a given textRun
        /// </summary>
        /// <param name="outputTextRun"></param>
        /// <param name="charBuffer"></param>
        /// <param name="start"></param>
        /// <param name="len"></param>
        public void GenerateGlyphRuns(TextRun outputTextRun, char[] charBuffer, int start, int len)
        {
            // layout glyphs with selected layout technique
            float sizeInPoints = this.FontSizeInPoints;

            outputTextRun.typeface     = this.Typeface;
            outputTextRun.sizeInPoints = sizeInPoints;

            //in this version we store original glyph into the mesh collection
            //and then we scale it later, so I just specific font size=0 (you can use any value)
            _glyphMeshCollection.SetCacheInfo(this.Typeface, 0, this.HintTechnique);


            GlyphLayoutMan.Typeface = this.Typeface;
            GlyphLayoutMan.Layout(charBuffer, start, len);

            float pxscale = this.Typeface.CalculateScaleToPixelFromPointSize(sizeInPoints);

            _resuableGlyphPlanList.Clear();
            GenerateGlyphPlan(charBuffer, 0, charBuffer.Length, _resuableGlyphPlanList);

            // render each glyph
            int planCount = _resuableGlyphPlanList.Count;

            for (var i = 0; i < planCount; ++i)
            {
                _pathTranslator.Reset();
                //----
                //glyph path
                //----
                UnscaledGlyphPlan glyphPlan = _resuableGlyphPlanList[i];
                //
                //1. check if we have this glyph in cache?
                //if yes, not need to build it again
                ProcessedGlyph processGlyph;
                float[]        tessData = null;

                if (!_glyphMeshCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out processGlyph))
                {
                    //if not found the  create a new one and register it
                    var writablePath = new WritablePath();
                    _pathTranslator.SetOutput(writablePath);
                    _currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints);
                    _currentGlyphPathBuilder.ReadShapes(_pathTranslator);

                    //-------
                    //do tess
                    int[]   endContours;
                    float[] flattenPoints = _curveFlattener.Flatten(writablePath._points, out endContours);

                    tessData     = _tessTool.TessAsTriVertexArray(flattenPoints, endContours, out int vertexCount);
                    processGlyph = new ProcessedGlyph(tessData, (ushort)vertexCount);

                    _glyphMeshCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, processGlyph);
                }

                outputTextRun.AddGlyph(
                    new GlyphRun(glyphPlan,
                                 processGlyph.tessData,
                                 processGlyph.vertextCount));
            }
        }
예제 #20
0
        public override void DrawFromGlyphPlans(PxScaledGlyphPlanList glyphPlanList, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

            //draw data in glyph plan
            //3. render each glyph

            float sizeInPoints = this.FontSizeInPoints;
            float scale        = _currentTypeface.CalculateScaleToPixelFromPointSize(sizeInPoints);

            //
            _glyphMeshCollections.SetCacheInfo(this.Typeface, sizeInPoints, this.HintTechnique);


            //this draw a single line text span***
            int endBefore = startAt + len;

            Graphics g = this.TargetGraphics;

            float acc_x = 0;
            float acc_y = 0;

            float g_x = 0;
            float g_y = 0;

            for (int i = startAt; i < endBefore; ++i)
            {
                PxScaledGlyphPlan glyphPlan = glyphPlanList[i];

                //check if we have a cache of this glyph
                //if not -> create it

                GraphicsPath foundPath;
                if (!_glyphMeshCollections.TryGetCacheGlyph(glyphPlan.glyphIndex, out foundPath))
                {
                    //if not found then create a new one
                    _currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints);
                    _txToGdiPath.Reset();
                    _currentGlyphPathBuilder.ReadShapes(_txToGdiPath);
                    foundPath = _txToGdiPath.ResultGraphicsPath;

                    //register
                    _glyphMeshCollections.RegisterCachedGlyph(glyphPlan.glyphIndex, foundPath);
                }
                //------
                //then move pen point to the position we want to draw a glyph

                float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * scale);

                g_x = (x + (ngx));
                g_y = (y + (ngy));

                acc_x += (float)Math.Round(glyphPlan.AdvanceX * scale);

                //g_x = (float)Math.Round(g_x);
                g_y = (float)Math.Floor(g_y);
                g.TranslateTransform(g_x, g_y);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, foundPath);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, foundPath);
                }
                //and then we reset back ***
                g.TranslateTransform(-g_x, -g_y);
            }
        }
        void CreateTextureFontFromGlyphIndices(
            Typeface typeface,
            float sizeInPoint,
            TextureKind textureKind,
            ushort[] glyphIndices, OnEachFinishTotal onFinishTotal)
        {
            if (onFinishTotal == null)
            {
                return;
            }
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.UseTrueTypeInstructions = this.UseTrueTypeInstruction;
            //-------------------------------------------------------------
            var atlasBuilder = new SimpleFontAtlasBuilder();

            atlasBuilder.SetAtlasInfo(textureKind, sizeInPoint);
            //-------------------------------------------------------------

            //
            MsdfGenParams      msdfGenParams = null;
            AggGlyphTextureGen aggTextureGen = null;

            if (textureKind == TextureKind.Msdf)
            {
                msdfGenParams = new MsdfGenParams();
            }
            else
            {
                aggTextureGen = new AggGlyphTextureGen();
            }


            float pxscale = typeface.CalculateScaleToPixelFromPointSize(sizeInPoint);
            int   j       = glyphIndices.Length;

            for (int i = 0; i < j; ++i)
            {
                //build glyph
                ushort gindex = glyphIndices[i];
                builder.BuildFromGlyphIndex(gindex, -1);
                GlyphImage glyphImg = null;
                if (textureKind == TextureKind.Msdf)
                {
                    var glyphToContour = new GlyphContourBuilder();
                    //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());
                    builder.ReadShapes(glyphToContour);
                    msdfGenParams.shapeScale = 1f / 64; //as original
                    glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams);
                }
                else
                {
                    //create alpha channel texture
                    aggTextureGen.TextureKind = textureKind;
                    glyphImg = aggTextureGen.CreateGlyphImage(builder, pxscale);
                }
                //

                atlasBuilder.AddGlyph(gindex, glyphImg);
                onFinishTotal(gindex, glyphImg, null);
            }
            onFinishTotal(0, null, atlasBuilder);
        }