Exemplo n.º 1
0
        //
        public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan,
                                                     ILineSegmentList lineSegs,
                                                     RequestFont font,
                                                     int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight)
        {
            //layout
            //from font
            //resolve for typeface
            //
            Typeface typeface = ResolveTypeface(font);

            _txtServices.SetCurrentFont(typeface, font.SizeInPoints);


            MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs;
            float             scale      = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            outputTotalW = 0;
            int j   = mylineSegs.Count;
            int pos = 0; //start at 0

            _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer());

            for (int i = 0; i < j; ++i)
            {
                //get each segment
                MyLineSegment lineSeg = (MyLineSegment)mylineSegs.GetSegment(i);
                //each line seg may has different script lang
                _txtServices.CurrentScriptLang = lineSeg.scriptLang;
                //
                //CACHING ...., reduce number of GSUB/GPOS
                //
                //we cache used line segment for a while
                //we ask for caching context for a specific typeface and font size
                GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                  lineSeg.StartAt,
                                                                                  lineSeg.Length);

                int seqLen = seq.Count;

                for (int s = 0; s < seqLen; ++s)
                {
                    UnscaledGlyphPlan glyphPlan = seq[s];

                    double actualAdvX = glyphPlan.AdvanceX;

                    outputTotalW +=
                        outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] +=
                            (int)Math.Round(actualAdvX * scale);
                }
                pos += lineSeg.Length;
            }

            //

            lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale);

            _reusableTextBuffer.SetRawCharBuffer(null);
        }
Exemplo n.º 2
0
        public static void CopyGlyphPlans(RenderVxFormattedString renderVx, UnscaledGlyphPlanList glyphPlans, float scale)
        {
            int n = glyphPlans.Count;
            //copy
            var   renderVxGlyphPlans = new RenderVxGlyphPlan[n];
            float acc_x = 0;
            float acc_y = 0;
            float x     = 0;
            float y     = 0;
            float g_x   = 0;
            float g_y   = 0;

            for (int i = 0; i < n; ++i)
            {
                UnscaledGlyphPlan glyphPlan = glyphPlans[i];


                float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * scale);
                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                g_x = (float)(x + ngx); //ideal x
                g_y = (float)(y + ngy);


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

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


                renderVxGlyphPlans[i] = new RenderVxGlyphPlan(
                    glyphPlan.glyphIndex,
                    g_x,
                    g_y,
                    g_w
                    );
            }
            renderVx.glyphList = renderVxGlyphPlans;
        }
        public void PrepareStringForRenderVx(RenderVxFormattedString renderVx, char[] buffer, int startAt, int len)
        {
            int j = buffer.Length;

            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);

            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, font);

            float scale = _fontAtlas.TargetTextureScale;
            int   recommendLineSpacing = _fontAtlas.OriginalRecommendLineSpacing;

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            float x = 0;
            float y = 0;

            y -= ((recommendLineSpacing) * scale);
            renderVx.RecommmendLineSpacing = (int)(recommendLineSpacing * scale);

            //
            float       scaleFromTexture = _finalTextureScale;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            //--------------------------

            //TODO: review render steps
            //NOTE:
            // -glyphData.TextureXOffset => restore to original pos
            // -glyphData.TextureYOffset => restore to original pos
            // ideal_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture);
            // ideal_y = (float)(y + (glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);
            //--------------------------

            float g_x       = 0;
            float g_y       = 0;
            int   baseY     = (int)Math.Round(y);
            int   n         = glyphPlanSeq.len;
            int   endBefore = glyphPlanSeq.startAt + n;

            //***
            _glsx.SetAssociatedTextureInfo(_glBmp);
            //
            vboBufferList2.Clear();
            indexList2.Clear();

            float acc_x = 0;
            float acc_y = 0;

            for (int i = glyphPlanSeq.startAt; i < endBefore; ++i)
            {
                UnscaledGlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq);
                UnscaledGlyphPlan     glyph         = glyphPlanList[i];

                Typography.Rendering.TextureFontGlyphData glyphData;
                if (!_fontAtlas.TryGetGlyphDataByGlyphIndex(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }

                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect);

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

                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);


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

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



                switch (textureKind)
                {
                case TextureKind.Msdf:

                    _glsx.DrawSubImageWithMsdf(_glBmp,
                                               ref srcRect,
                                               g_x,
                                               g_y,
                                               scaleFromTexture);

                    break;

                case TextureKind.StencilGreyScale:

                    //stencil gray scale with fill-color
                    _glsx.DrawGlyphImageWithStecil(_glBmp,
                                                   ref srcRect,
                                                   g_x,
                                                   g_y,
                                                   scaleFromTexture);

                    break;

                case TextureKind.Bitmap:
                    _glsx.DrawSubImage(_glBmp,
                                       ref srcRect,
                                       g_x,
                                       g_y,
                                       scaleFromTexture);
                    break;

                case TextureKind.StencilLcdEffect:
                    _glsx.WriteVboToList(
                        vboBufferList2,
                        indexList2,
                        ref srcRect,
                        g_x,
                        g_y,
                        scaleFromTexture);
                    break;
                }
            }
            //---------

            DrawingGL.GLRenderVxFormattedString renderVxFormattedString = (DrawingGL.GLRenderVxFormattedString)renderVx;
            renderVxFormattedString.IndexArray   = indexList2.ToArray();
            renderVxFormattedString.VertexCoords = vboBufferList2.ToArray();
            renderVxFormattedString.VertexCount  = indexList2.Count;
        }
        public void DrawString(char[] buffer, int startAt, int len, double x, double y)
        {
            _glsx.FontFillColor = painter.FontFillColor;

            int j = buffer.Length;

            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);

            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, font);

            float scale = _fontAtlas.TargetTextureScale;
            int   recommendLineSpacing = _fontAtlas.OriginalRecommendLineSpacing;

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            y -= ((_fontAtlas.OriginalRecommendLineSpacing) * scale);

            EnsureLoadGLBmp();
            //
            float       scaleFromTexture = _finalTextureScale;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            float g_x       = 0;
            float g_y       = 0;
            int   baseY     = (int)Math.Round(y);
            int   n         = glyphPlanSeq.len;
            int   endBefore = glyphPlanSeq.startAt + n;

            //-------------------------------------
            _glsx.LoadTexture1(_glBmp);
            //-------------------------------------

            _vboBufferList.Clear(); //clear before use
            _indexList.Clear();     //clear before use


            float acc_x = 0;
            float acc_y = 0;

            for (int i = glyphPlanSeq.startAt; i < endBefore; ++i)
            {
                UnscaledGlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq);
                UnscaledGlyphPlan     glyph         = glyphPlanList[i];

                Typography.Rendering.TextureFontGlyphData glyphData;
                if (!_fontAtlas.TryGetGlyphDataByGlyphIndex(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect);


                float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale);
                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);


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

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


                switch (textureKind)
                {
                case TextureKind.Msdf:

                    _glsx.DrawSubImageWithMsdf(_glBmp,
                                               ref srcRect,
                                               g_x,
                                               g_y,
                                               scaleFromTexture);

                    break;

                case TextureKind.StencilGreyScale:

                    //stencil gray scale with fill-color
                    _glsx.DrawGlyphImageWithStecil(_glBmp,
                                                   ref srcRect,
                                                   g_x,
                                                   g_y,
                                                   scaleFromTexture);

                    break;

                case TextureKind.Bitmap:
                    _glsx.DrawSubImage(_glBmp,
                                       ref srcRect,
                                       g_x,
                                       g_y,
                                       scaleFromTexture);
                    break;

                case TextureKind.StencilLcdEffect:

                    _glsx.WriteVboToList(
                        _vboBufferList,
                        _indexList,
                        ref srcRect,
                        g_x,
                        g_y,
                        scaleFromTexture);

                    break;
                }
            }
            //-------
            //we create vbo first
            //then render
            _glsx.DrawGlyphImageWithSubPixelRenderingTechnique3(_vboBufferList.ToArray(), _indexList.ToArray());
        }
Exemplo n.º 5
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));
            }
        }
Exemplo n.º 6
0
        public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y)
        {
            //if (_stencilBmp == null)
            //{
            //    //create a stencil bmp
            //    _stencilBmp = new ActualBitmap(p.Width, p.Height);
            //    _stencilBlender = new PixelProcessing.SubBitmapBlender(_stencilBmp, new PixelProcessing.PixelBlenderBGRA());
            //    _backPainter = AggPainter.Create(_stencilBmp);
            //    //------
            //}

            int j = buffer.Length;
            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);

            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font);

            Typeface typeface = _textServices.ResolveTypeface(_font);
            float    scale    = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints);

            int recommendLineSpacing = (int)_font.LineSpacingInPixels;

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            y -= _font.LineSpacingInPixels;

            //
            float       scaleFromTexture = _finalTextureScale;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            float g_x   = 0;
            float g_y   = 0;
            int   baseY = (int)Math.Round(y);

            //-------------------------------------
            //load texture
            //_pcx.LoadTexture1(_glBmp);
            //-------------------------------------


            float acc_x = 0;
            float acc_y = 0;

            p.DrawImage(_fontBmp, 100, 100);

            int seqLen = glyphPlanSeq.Count;

            for (int i = 0; i < seqLen; ++i)
            {
                UnscaledGlyphPlan   glyph = glyphPlanSeq[i];
                TextureGlyphMapData glyphData;
                if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                int srcX, srcY, srcW, srcH;
                glyphData.GetRect(out srcX, out srcY, out srcW, out srcH);

                float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale);
                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcH) * scaleFromTexture);

                acc_x += (float)Math.Round(glyph.AdvanceX * scale);
                //g_x = (float)Math.Round(g_x);
                g_y = (float)Math.Floor(g_y);

                //p.RenderQuality = RenderQuality.Fast;

                //*** the atlas is inverted so...
                //p.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY), srcW, srcH);
                //p.DrawImage(_fontBmp, g_x, g_y);

                //1. draw to back buffer
                //_backPainter.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY), srcW, srcH);

                //2. then copy content to this

                //p.DrawImage(_stencilBmp, 100, 100);
                p.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY + srcH), srcW, srcH);
                switch (textureKind)
                {
                default:
                    break;

                case TextureKind.StencilLcdEffect:
                {
                }
                break;
                }



                //copy some part from the bitmap
                //switch (textureKind)
                //{
                //    case TextureKind.Msdf:
                //        _pcx.DrawSubImageWithMsdf(_glBmp,
                //            ref srcRect,
                //            g_x,
                //            g_y,
                //            scaleFromTexture);
                //        break;
                //    case TextureKind.StencilGreyScale:
                //        //stencil gray scale with fill-color
                //        _pcx.DrawGlyphImageWithStecil(_glBmp,
                //         ref srcRect,
                //            g_x,
                //            g_y,
                //            scaleFromTexture);
                //        break;
                //    case TextureKind.Bitmap:
                //        _pcx.DrawSubImage(_glBmp,
                //         ref srcRect,
                //            g_x,
                //            g_y,
                //            scaleFromTexture);
                //        break;
                //    case TextureKind.StencilLcdEffect:
                //        _pcx.WriteVboToList(
                //          _vboBufferList,
                //          _indexList,
                //          ref srcRect,
                //          g_x,
                //          g_y,
                //          scaleFromTexture);

                //        break;
                //}
            }
            //-------
            //we create vbo first
            //then render
        }
Exemplo n.º 7
0
        public override void DrawFromGlyphPlans(UnscaledGlyphPlanList 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)
            {
                UnscaledGlyphPlan 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);
            }
        }
Exemplo n.º 8
0
        public void MeasureString(char[] str, int startAt, int len, int limitWidth, out int charFit, out int charFitWidth)
        {
            //measure string
            if (str.Length < 1)
            {
                charFitWidth = 0;
            }

            _reusableMeasureBoxList.Clear(); //reset

            float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_fontSizeInPts);
            //NOET:at this moment, simple operation
            //may not be simple...
            //-------------------
            //input string may contain more than 1 script lang
            //user can parse it by other parser
            //but in this code, we use our Typography' parser
            //-------------------
            //user must setup the CustomBreakerBuilder before use

            int   cur_startAt = startAt;
            float accumW      = 0;

            foreach (BreakSpan breakSpan in BreakToLineSegments(str, startAt, len))
            {
                //measure string at specific px scale
                _glyphLayout.Layout(str, breakSpan.startAt, breakSpan.len);
                //

                _reusableGlyphPlanList.Clear();
                _glyphLayout.GenerateUnscaledGlyphPlans(_reusableGlyphPlanList);
                //measure ...


                //measure each glyph
                //limit at specific width
                int glyphCount = _reusableGlyphPlanList.Count;


                float acc_x = 0; //accum_x
                float acc_y = 0; //accum_y
                float g_x   = 0;
                float g_y   = 0;
                float x     = 0;
                float y     = 0;
                for (int i = 0; i < glyphCount; ++i)
                {
                    UnscaledGlyphPlan glyphPlan = _reusableGlyphPlanList[i];

                    float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * pxscale);
                    float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * pxscale);
                    //NOTE:
                    // -glyphData.TextureXOffset => restore to original pos
                    // -glyphData.TextureYOffset => restore to original pos
                    //--------------------------
                    g_x = (float)(x + (ngx)); //ideal x
                    g_y = (float)(y + (ngy));
                    float g_w = (float)Math.Round(glyphPlan.AdvanceX * pxscale);
                    acc_x += g_w;
                    //g_x = (float)Math.Round(g_x);
                    g_y = (float)Math.Floor(g_y);

                    float right = g_x + g_w;

                    if (right >= accumW)
                    {
                        //stop here at this glyph
                        charFit = i - 1;
                        //TODO: review this
                        charFitWidth = (int)System.Math.Round(accumW);
                        return;
                    }
                    else
                    {
                        accumW = right;
                    }
                }
            }

            charFit      = 0;
            charFitWidth = 0;
        }
Exemplo n.º 9
0
        public void DrawString(char[] buffer, int startAt, int len, double left, double top)
        {
            _vboBuilder.Clear();
            _vboBuilder.SetTextureInfo(_glBmp.Width, _glBmp.Height, _glBmp.IsYFlipped, _pcx.OriginKind);

            //
            _pcx.FontFillColor = _painter.FontFillColor;
            _pcx.LoadTexture(_glBmp);


            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);
            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font);
            float             px_scale     = _px_scale;
            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again

            float       scaleFromTexture = 1;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            float g_left   = 0;
            float g_top    = 0;
            int   baseLine = (int)Math.Round((float)top + _font.AscentInPixels);
            int   bottom   = (int)Math.Round((float)top + _font.AscentInPixels - _font.DescentInPixels);

            float acc_x = 0; //local accumulate x
            float acc_y = 0; //local accumulate y

#if DEBUG
            if (s_dbugShowMarkers)
            {
                if (s_dbugShowGlyphTexture)
                {
                    //show original glyph texture at top
                    _pcx.DrawImage(_glBmp, 0, 0);
                }
                //draw red-line-marker for baseLine
                _painter.StrokeColor = Color.Red;
                _painter.DrawLine(left, baseLine, left + 200, baseLine);
                //
                //draw magenta-line-marker for bottom line
                _painter.StrokeColor = Color.Magenta;
                int bottomLine = (int)Math.Round((float)top + _font.LineSpacingInPixels);
                _painter.DrawLine(left, bottomLine, left + 200, bottomLine);
                //draw blue-line-marker for top line
                _painter.StrokeColor = Color.Blue;
                _painter.DrawLine(0, top, left + 200, top);
            }

            DrawingTechnique = s_dbugDrawTechnique; //for debug only
            UseVBO           = s_dbugUseVBO;        //for debug only
#endif



            int seqLen = glyphPlanSeq.Count;

            for (int i = 0; i < seqLen; ++i)
            {
                UnscaledGlyphPlan glyph = glyphPlanSeq[i];
                Typography.Rendering.TextureGlyphMapData glyphData;
                if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------

                //paint src rect
                //temp fix, glyph texture img is not flipped
                //but the associate info is flipped => so
                //we need remap exact Y from the image

                Rectangle srcRect =
                    new Rectangle(glyphData.Left,
                                  _glBmp.Height - (glyphData.Top + glyphData.Height),
                                  glyphData.Width,
                                  glyphData.Height);

                //offset length from 'base-line'
                float x_offset = acc_x + (float)Math.Round(glyph.OffsetX * px_scale - glyphData.TextureXOffset);
                float y_offset = acc_y + (float)Math.Round(glyph.OffsetY * px_scale - glyphData.TextureYOffset) + srcRect.Height; //***

                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------

                g_left = (float)(left + x_offset);
                g_top  = (float)(bottom - y_offset); //***

                acc_x += (float)Math.Round(glyph.AdvanceX * px_scale);

                //g_x = (float)Math.Round(g_x); //***
                g_top = (float)Math.Floor(g_top);//adjust to integer num ***

#if DEBUG
                if (s_dbugShowMarkers)
                {
                    if (s_dbugShowGlyphTexture)
                    {
                        //draw yellow-rect-marker on original texture
                        _painter.DrawRectangle(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Color.Yellow);
                    }

                    //draw debug-rect box at target glyph position
                    _painter.DrawRectangle(g_left, g_top, srcRect.Width, srcRect.Height, Color.Black);
                    _painter.StrokeColor = Color.Blue; //restore
                }
#endif
                if (textureKind == TextureKind.Msdf)
                {
                    _pcx.DrawSubImageWithMsdf(_glBmp,
                                              ref srcRect,
                                              g_left,
                                              g_top,
                                              scaleFromTexture);
                }
                else
                {
                    switch (DrawingTechnique)
                    {
                    case GlyphTexturePrinterDrawingTechnique.Stencil:
                        if (UseVBO)
                        {
                            _vboBuilder.WriteVboToList(
                                ref srcRect,
                                g_left, g_top);
                        }
                        else
                        {
                            //stencil gray scale with fill-color
                            _pcx.DrawGlyphImageWithStecil(_glBmp,
                                                          ref srcRect,
                                                          g_left,
                                                          g_top,
                                                          scaleFromTexture);
                        }
                        break;

                    case GlyphTexturePrinterDrawingTechnique.Copy:
                        if (UseVBO)
                        {
                            _vboBuilder.WriteVboToList(
                                ref srcRect,
                                g_left, g_top);
                        }
                        else
                        {
                            _pcx.DrawSubImage(_glBmp,
                                              ref srcRect,
                                              g_left,
                                              g_top,
                                              1);
                        }
                        break;

                    case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering:
                        if (UseVBO)
                        {
                            _vboBuilder.WriteVboToList(
                                ref srcRect,
                                g_left, g_top);
                        }
                        else
                        {
                            _pcx.DrawGlyphImageWithSubPixelRenderingTechnique2_GlyphByGlyph(
                                ref srcRect,
                                g_left,
                                g_top,
                                1);
                        }
                        break;
                    }
                }
            }
            //-------------------------------------------
            //
            if (UseVBO)
            {
                switch (DrawingTechnique)
                {
                case GlyphTexturePrinterDrawingTechnique.Copy:
                    _pcx.DrawGlyphImageWithCopy_VBO(_vboBuilder);
                    break;

                case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering:
                    _pcx.DrawGlyphImageWithSubPixelRenderingTechnique3_DrawElements(_vboBuilder);
                    break;

                case GlyphTexturePrinterDrawingTechnique.Stencil:
                    _pcx.DrawGlyphImageWithStecil_VBO(_vboBuilder);
                    break;
                }

                _vboBuilder.Clear();
            }
        }
Exemplo n.º 10
0
        void RenderAndShowMeasureBox()
        {
            bool flipY = chkFlipY.Checked;



            //set some Gdi+ props...
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.Clear(Color.White);

            Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface;
            Typography.OpenFont.TypefaceExtension2.UpdateAllCffGlyphBounds(typeface);


            float pxscale     = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints);
            int   lineSpacing = (int)System.Math.Ceiling((double)typeface.CalculateLineSpacing(LineSpacingChoice.TypoMetric) * pxscale);


            if (flipY)
            {
                //credit:
                //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control
                g.ScaleTransform(1.0F, -1.0F);    // Flip the Y-Axis
                g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly
            }


            //--------------------------------
            //textspan measurement sample
            //--------------------------------
            _currentTextPrinter.HintTechnique     = (HintTechnique)lstHintList.SelectedItem;
            _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem;
            _currentTextPrinter.UpdateGlyphLayoutSettings();

            //render at specific pos
            float x_pos = 0, y_pos = lineSpacing * 2;

            char[] textBuffer = txtInputChar.Text.ToCharArray();

            //Example 1: this is a basic draw sample
            _currentTextPrinter.FillColor      = Color.Black;
            _currentTextPrinter.TargetGraphics = g;
            _currentTextPrinter.DrawString(
                textBuffer,
                0,
                textBuffer.Length,
                x_pos,
                y_pos
                );
            //
            //--------------------------------------------------
            //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw)
            //you can create you own class to hold userGlyphPlans.***
            //2.1
            _reusableUnscaledGlyphPlanList.Clear();
            _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList);
            //2.2
            //and we can print the formatted glyph plan later.
            y_pos -= lineSpacing;//next line
            _currentTextPrinter.FillColor = Color.Red;

            _currentTextPrinter.DrawFromGlyphPlans(
                new GlyphPlanSequence(_reusableUnscaledGlyphPlanList),
                x_pos,
                y_pos
                );

            //Example 3: MeasureString
            UnscaledGlyphPlanList glyphPlans = new UnscaledGlyphPlanList();

            _currentTextPrinter.GlyphLayoutMan.GenerateUnscaledGlyphPlans(glyphPlans);
            MeasuredStringBox strBox = _currentTextPrinter.GlyphLayoutMan.LayoutAndMeasureString(
                textBuffer, 0, textBuffer.Length,
                _currentTextPrinter.FontSizeInPoints);

            int   j           = glyphPlans.Count;
            float backup_xpos = x_pos;

            for (int i = 0; i < j; ++i)
            {
                UnscaledGlyphPlan         glyphPlan = glyphPlans[i];
                Typography.OpenFont.Glyph glyph     = typeface.GetGlyphByIndex(glyphPlan.glyphIndex);
                //
                Typography.OpenFont.Bounds b = glyph.Bounds;
                //
                float xmin = b.XMin * pxscale;
                float ymin = b.YMin * pxscale;
                //
                float xmax = b.XMax * pxscale;
                float ymax = b.YMax * pxscale;
                //
                float glyph_x = x_pos + glyphPlan.OffsetX;
                g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin);
                x_pos += glyphPlan.AdvanceX * pxscale;
            }

            x_pos = backup_xpos;

            g.FillRectangle(Brushes.Red, new RectangleF(0, 0, 5, 5));//reference point(0,0)
            g.FillRectangle(Brushes.Green, new RectangleF(x_pos, y_pos, 3, 3));


            float x_pos2 = x_pos + strBox.width + 10;


            g.DrawRectangle(Pens.Black, x_pos, y_pos + strBox.DescendingInPx, strBox.width, strBox.ClipHeightInPx);
            g.DrawRectangle(Pens.Red, x_pos, y_pos + strBox.DescendingInPx, strBox.width, strBox.LineSpaceInPx);

            g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos);                                                  //baseline
            g.DrawLine(Pens.Green, x_pos, y_pos + strBox.DescendingInPx, x_pos2, y_pos + strBox.DescendingInPx); //descending
            g.DrawLine(Pens.Magenta, x_pos, y_pos + strBox.AscendingInPx, x_pos2, y_pos + strBox.AscendingInPx); //ascending


            ////------------
            ////draw another line (for reference)
            y_pos -= lineSpacing;//next line


            _currentTextPrinter.FillColor = Color.Black;

            _currentTextPrinter.DrawFromGlyphPlans(
                new GlyphPlanSequence(_reusableUnscaledGlyphPlanList),
                x_pos,
                y_pos
                );
            //transform back
            if (flipY)
            {
                g.ScaleTransform(1.0F, -1.0F);    // Flip the Y-Axis
                g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly
            }

            //---------

            //txtMsgInfo.Text = "choice:" + choice.ToString() + "=" + lineSpacing.ToString();
        }
Exemplo n.º 11
0
        public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y)
        {
            //if (_stencilBmp == null)
            //{
            //    //create a stencil bmp
            //    _stencilBmp = new ActualBitmap(p.Width, p.Height);
            //    _stencilBlender = new PixelProcessing.SubBitmapBlender(_stencilBmp, new PixelProcessing.PixelBlenderBGRA());
            //    _backPainter = AggPainter.Create(_stencilBmp);
            //    //------
            //}

            int j = buffer.Length;
            //create temp buffer span that describe the part of a whole char buffer
            var textBufferSpan = new Typography.Text.TextBufferSpan(buffer, startAt, len);

            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _txtClient.CreateGlyphPlanSeq(textBufferSpan, _font);

            ResolvedFont resolvedFont = _textServices.ResolveFont(_font);
            Typeface     typeface     = resolvedFont.Typeface;
            float        scale        = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints);

            int recommendLineSpacing = resolvedFont.LineSpacingInPixels;

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            y -= resolvedFont.LineSpacingInPixels;

            //
            float       scaleFromTexture = _finalTextureScale;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            float g_x   = 0;
            float g_y   = 0;
            int   baseY = (int)Math.Round(y);

            //-------------------------------------
            //load texture
            //_pcx.LoadTexture1(_glBmp);
            //-------------------------------------


            float acc_x = 0;
            float acc_y = 0;

            p.DrawImage(_fontBmp, 100, 100);

            int seqLen = glyphPlanSeq.Count;

            for (int i = 0; i < seqLen; ++i)
            {
                UnscaledGlyphPlan glyph = glyphPlanSeq[i];
                AtlasItem         glyphData;
                if (!_fontAtlas.TryGetItem(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                int srcX, srcY, srcW, srcH;
                glyphData.GetRect(out srcX, out srcY, out srcW, out srcH);

                float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale);
                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcH) * scaleFromTexture);

                acc_x += (float)Math.Round(glyph.AdvanceX * scale);
                //g_x = (float)Math.Round(g_x);
                g_y = (float)Math.Floor(g_y);


                p.DrawImage(_fontBmp, g_x, g_y, srcX, srcY, srcW, srcH);
            }
            //-------
            //we create vbo first
            //then render
        }
Exemplo n.º 12
0
        void RenderAndShowMeasureBox()
        {
            bool flipY = chkFlipY.Checked;


            //set some Gdi+ props...
            _g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            _g.Clear(Color.White);

            Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface;
            Typography.OpenFont.Extensions.TypefaceExtensions.UpdateAllCffGlyphBounds(typeface);


            float pxscale     = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints);
            int   lineSpacing = (int)System.Math.Ceiling((double)typeface.CalculateLineSpacing(LineSpacingChoice.TypoMetric) * pxscale);


            if (flipY)
            {
                //credit:
                //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control
                _g.ScaleTransform(1.0F, -1.0F);    // Flip the Y-Axis
                _g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly
            }


            //--------------------------------
            //textspan measurement sample
            //--------------------------------
            _currentTextPrinter.HintTechnique     = (HintTechnique)lstHintList.SelectedItem;
            _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem;
            _currentTextPrinter.UpdateGlyphLayoutSettings();

            //render at specific pos
            float x_pos = 0, y_pos = lineSpacing * 2;

            char[] textBuffer = txtInputChar.Text.ToCharArray();

            //Example 1: this is a basic draw sample
            _currentTextPrinter.FillColor      = Color.Black;
            _currentTextPrinter.TargetGraphics = _g;
            //_currentTextPrinter.DrawString(
            //    textBuffer,
            //     0,
            //     textBuffer.Length,
            //     x_pos,
            //     y_pos
            //    );
            //
            //--------------------------------------------------
            //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw)
            //you can create you own class to hold userGlyphPlans.***
            //2.1
            if (chkEnableMultiTypefaces.Checked)
            {
                _ftmGlyphPlansList.Clear();
                _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, _ftmGlyphPlansList);
                //2.2
                //and we can print the formatted glyph plan later.
                y_pos -= lineSpacing;//next line
                _currentTextPrinter.FillColor = Color.Red;

                _currentTextPrinter.DrawFromFormattedGlyphPlans(
                    _ftmGlyphPlansList,
                    x_pos,
                    y_pos
                    );


                //--------------------------------------------------
                //Example 3: MeasureString
                //3.1 use data in formatted_glyph_plan_list to measure string => OK, OR
                //3.2 use another 'light-weight' text printer to measure string (without drawing actual string)

                //3.1
                _currentTextPrinter.MeasureGlyphPlanList(_ftmGlyphPlansList, out int measureWidth);
                _g.DrawRectangle(Pens.Red, x_pos, y_pos, measureWidth, 30);


                float baseline = y_pos;

                //3.2 draw each glyph bounds
                {
                    int m = _ftmGlyphPlansList.Count;

                    for (int i = 0; i < m; ++i)
                    {
                        FormattedGlyphPlanSeq seq          = _ftmGlyphPlansList[i];
                        ResolvedFont          resolvedFont = seq.ResolvedFont;
                        Typeface localTypeface             = resolvedFont.Typeface;

                        pxscale = resolvedFont.GetScaleToPixelFromPointInSize();
                        GlyphPlanSequence glyph_seq = seq.Seq;
                        var snapToPxScale           = new GlyphPlanSequenceSnapPixelScaleLayout(seq.Seq, 0, glyph_seq.Count, pxscale);


                        x_pos += (resolvedFont.WhitespaceWidth * seq.PrefixWhitespaceCount);

                        int nn = 0;///
                        while (snapToPxScale.Read())
                        {
                            //float cx = (float)Math.Round(snapToPxScale.ExactX + x_pos);
                            //float cy = (float)Math.Floor(snapToPxScale.ExactY + baseline);

                            UnscaledGlyphPlan glyphPlan = glyph_seq[nn];
                            Glyph             glyph     = localTypeface.GetGlyph(glyphPlan.glyphIndex);

                            Bounds b = glyph.Bounds;
                            //
                            float xmin = b.XMin * pxscale;
                            float ymin = b.YMin * pxscale;
                            //
                            float xmax = b.XMax * pxscale;
                            float ymax = b.YMax * pxscale;
                            //
                            float glyph_x = x_pos + (glyphPlan.OffsetX * pxscale);
                            _g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin);

                            x_pos += glyphPlan.AdvanceX * pxscale;

                            nn++;
                        }

                        x_pos += (resolvedFont.WhitespaceWidth * seq.PostfixWhitespaceCount);
                    }
                }

                _ftmGlyphPlansList.Clear();
            }
            else
            {
                _reusableUnscaledGlyphPlanList.Clear();
                _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList);
                //2.2
                //and we can print the formatted glyph plan later.
                y_pos -= lineSpacing;//next line
                _currentTextPrinter.FillColor = Color.Red;


                //
                GlyphPlanSequence seq = new GlyphPlanSequence(_reusableUnscaledGlyphPlanList);

                _currentTextPrinter.DrawFromGlyphPlans(
                    seq,
                    x_pos,
                    y_pos
                    );

                //--------------------------------------------------
                //Example 3: MeasureString

                float descending_px    = _currentTextPrinter.FontDescedingPx;
                float ascending_px     = _currentTextPrinter.FontAscendingPx;
                float lineSpacing_px   = _currentTextPrinter.FontLineSpacingPx;
                float clippedHeight_px = _currentTextPrinter.FontClipHeightPx;

                _currentTextPrinter.MeasureGlyphPlanSeq(seq, out int textspanW);

                UnscaledGlyphPlanList glyphPlans = new UnscaledGlyphPlanList();
                _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, glyphPlans);


                int   j           = glyphPlans.Count;
                float backup_xpos = x_pos;
                for (int i = 0; i < j; ++i)
                {
                    UnscaledGlyphPlan glyphPlan = glyphPlans[i];
                    Glyph             glyph     = typeface.GetGlyph(glyphPlan.glyphIndex);
                    //
                    Bounds b = glyph.Bounds;
                    //
                    float xmin = b.XMin * pxscale;
                    float ymin = b.YMin * pxscale;
                    //
                    float xmax = b.XMax * pxscale;
                    float ymax = b.YMax * pxscale;
                    //
                    float glyph_x = x_pos + (glyphPlan.OffsetX * pxscale);
                    _g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin);
                    x_pos += glyphPlan.AdvanceX * pxscale;
                }

                x_pos = backup_xpos;

                _g.FillRectangle(Brushes.Red, new RectangleF(0, 0, 5, 5));//reference point(0,0)
                _g.FillRectangle(Brushes.Green, new RectangleF(x_pos, y_pos, 3, 3));


                float x_pos2 = x_pos + textspanW + 10;


                _g.DrawRectangle(Pens.Black, x_pos, y_pos + descending_px, textspanW, clippedHeight_px);
                _g.DrawRectangle(Pens.Red, x_pos, y_pos + descending_px, textspanW, lineSpacing_px);

                _g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos);                                  //baseline
                _g.DrawLine(Pens.Green, x_pos, y_pos + descending_px, x_pos2, y_pos + descending_px); //descending
                _g.DrawLine(Pens.Magenta, x_pos, y_pos + ascending_px, x_pos2, y_pos + ascending_px); //ascending


                ////------------
                ////draw another line (for reference)
                y_pos -= lineSpacing;//next line


                _currentTextPrinter.FillColor = Color.Black;

                _currentTextPrinter.DrawFromGlyphPlans(
                    new GlyphPlanSequence(_reusableUnscaledGlyphPlanList),
                    x_pos,
                    y_pos
                    );
            }



            //transform back
            if (flipY)
            {
                _g.ScaleTransform(1.0F, -1.0F);    // Flip the Y-Axis
                _g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly
            }

            //---------

            //txtMsgInfo.Text = "choice:" + choice.ToString() + "=" + lineSpacing.ToString();
        }
Exemplo n.º 13
0
        private void button3_Click(object sender, EventArgs e)
        {
            //it should be faster if we use 'mesh' cache
            //instead of read-transform it every time like code above(button2_click)

            LoadFont();

            float font_size_in_Point = 20;

            _glyphMeshStore.SetFont(_latinModernMathFont, font_size_in_Point);//20= font size
            _glyphMeshStore.FlipGlyphUpward = true;

            float px_scale = _latinModernMathFont.CalculateScaleToPixelFromPointSize(font_size_in_Point);

            using (Tools.BorrowAggPainter(_memBmp, out var p))
            {
                p.Clear(PixelFarm.Drawing.Color.White);

                float prevX = p.OriginX;
                float prevY = p.OriginY;


                int line_left = 10;
                int line_top  = 50;

                p.SetOrigin(line_left, line_top);//*** test

                //draw reference point
                p.FillRect(0, 0, 5, 5, PixelFarm.Drawing.Color.Red);

                char[] test_str    = "‽_x‾".ToCharArray();
                int    inline_left = 0;
                int    inline_top  = 0;

                //----------
                GlyphLayout glyphLayout = new GlyphLayout();
                glyphLayout.ScriptLang = new ScriptLang("math");
                glyphLayout.Typeface   = _latinModernMathFont;


                //temp fix for some typeface

                glyphLayout.SetGlyphIndexNotFoundHandler((glyph_layout, codepoint, next_codepoint) =>
                {
                    switch (codepoint)
                    {
                    //overline unicode
                    case 8254: return(2246);    //overline-combine, this will break into 3 parts in math layout process
                    }
                    return(0);
                });


                //
                glyphLayout.Layout(test_str, 0, test_str.Length);

                List <UnscaledGlyphPlan> glyphPlans = new List <UnscaledGlyphPlan>();

                foreach (UnscaledGlyphPlan glypyPlan in glyphLayout.GetUnscaledGlyphPlanIter())
                {
                    glyphPlans.Add(glypyPlan);
                }
                //--------
                for (int i = 0; i < glyphPlans.Count; ++i)
                {
                    //ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)test_str[i]);
                    ////do some glyph-substitution
                    //ushort advW = _latinModernMathFont.GetAdvanceWidth((int)test_str[i]);//unscale glyph width
                    //now scale it to specific font size

                    UnscaledGlyphPlan glyphPlan = glyphPlans[i];
                    int         advW_s          = (int)System.Math.Round(px_scale * glyphPlan.AdvanceX);
                    VertexStore v1 = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex);
                    p.SetOrigin(line_left + inline_left, line_top + inline_top);
                    p.Fill(v1, PixelFarm.Drawing.Color.Black);
                    inline_left += advW_s;//move
                }
                //restore
                p.SetOrigin(prevX, prevY);
            }

            //-----------
            CopyBitmapToScreen();
        }
Exemplo n.º 14
0
        public override void DrawFromGlyphPlans(GlyphPlanSequence glyphPlanSeq, int startAt, int len, float left, float top)
        {
            Typeface typeface = _textServices.ResolveTypeface(_font);

            float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints);
            int   recommendLineSpacing = (int)_font.LineSpacingInPixels;
            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again

            //

            TextureKind textureKind = _fontAtlas.TextureKind;

            float gx    = 0;
            float gy    = 0;
            int   baseY = (int)Math.Round(top);


            float acc_x = 0;
            float acc_y = 0;

            int lineHeight = (int)_font.LineSpacingInPixels;                              //temp

            PixelBlender32 prevPxBlender = _painter.DestBitmapBlender.OutputPixelBlender; //save

            _painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo;    //change to new blender

            bool fillGlyphByGlyph = true;

            if (fillGlyphByGlyph)
            {
                //test...
                //fill glyph-by-glyh

                var aaTech = this.AntialiasTech;
                int seqLen = glyphPlanSeq.Count;


                for (int i = 0; i < seqLen; ++i)
                {
                    UnscaledGlyphPlan   unscaledGlyphPlan = glyphPlanSeq[i];
                    TextureGlyphMapData glyphData;
                    if (!_fontAtlas.TryGetGlyphMapData(unscaledGlyphPlan.glyphIndex, out glyphData))
                    {
                        //if no glyph data, we should render a missing glyph ***
                        continue;
                    }
                    //--------------------------------------
                    //TODO: review precise height in float
                    //--------------------------------------
                    int srcX, srcY, srcW, srcH;
                    glyphData.GetRect(out srcX, out srcY, out srcW, out srcH);

                    float ngx = acc_x + (float)Math.Round(unscaledGlyphPlan.OffsetX * scale);
                    float ngy = acc_y + (float)Math.Round(unscaledGlyphPlan.OffsetY * scale);
                    //NOTE:
                    // -glyphData.TextureXOffset => restore to original pos
                    // -glyphData.TextureYOffset => restore to original pos
                    //--------------------------

                    //if (glyphData.TextureXOffset != 0)
                    //{
                    //}

                    gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x
                    gy = (float)(top + (ngy + glyphData.TextureYOffset - srcH + lineHeight));

                    acc_x += (float)Math.Round(unscaledGlyphPlan.AdvanceX * scale);
                    gy     = (float)Math.Floor(gy);// + lineHeight;

                    //clear with solid black color
                    //_maskBufferPainter.Clear(Color.Black);
                    //clear mask buffer at specific pos
                    _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black);
                    //draw 'stencil' glyph on mask-buffer
                    _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY + srcH), srcW, srcH);

                    switch (aaTech)
                    {
                    default:
                    {
                        //select component to render this need to render 3 times for lcd technique
                        //1. B
                        _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.B;
                        _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B;
                        _painter.FillRect(gx + 1, gy, srcW, srcH);
                        //2. G
                        _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.G;
                        _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G;
                        _painter.FillRect(gx + 1, gy, srcW, srcH);
                        //3. R
                        _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.R;
                        _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R;
                        _painter.FillRect(gx + 1, gy, srcW, srcH);
                    }
                    break;

                    case AntialiasTechnique.GreyscaleStencil:
                    {
                        //fill once
                        //we choose greeh channel (middle)
                        _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.G;
                        _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.EnableAll;
                        _painter.FillRect(gx + 1, gy, srcW, srcH);
                    }
                    break;
                    }
                }
            }
            else
            {
                //clear entire line
                _maskBufferPainter.FillRect(gx - 1, gy - 1, _maskBufferPainter.Width - gx + 2, lineHeight + 2, Color.Black);

                bool  isFirst = true;
                int   startX = 0, startY = 0;
                float lenW = 0;
                float lenH = 0;

                int seqLen = glyphPlanSeq.Count;
                for (int i = 0; i < seqLen; ++i)
                {
                    UnscaledGlyphPlan glyph = glyphPlanSeq[i];

                    TextureGlyphMapData glyphData;
                    if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData))
                    {
                        //if no glyph data, we should render a missing glyph ***
                        continue;
                    }
                    //--------------------------------------
                    //TODO: review precise height in float
                    //--------------------------------------
                    int srcX, srcY, srcW, srcH;
                    glyphData.GetRect(out srcX, out srcY, out srcW, out srcH);

                    float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale);
                    float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale);
                    //NOTE:
                    // -glyphData.TextureXOffset => restore to original pos
                    // -glyphData.TextureYOffset => restore to original pos
                    //--------------------------
                    gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x
                    gy = (float)(top + (ngy - glyphData.TextureYOffset - srcH + lineHeight));

                    acc_x += (float)Math.Round(glyph.AdvanceX * scale);
                    gy     = (float)Math.Floor(gy) + lineHeight;

                    if (isFirst)
                    {
                        startX  = (int)gx;
                        startY  = (int)gy;
                        isFirst = false;
                    }

                    _maskBufferPainter.DrawImage(_fontBmp, gx + 1, gy, srcX, _fontBmp.Height - (srcY), srcW + 1, srcH);

                    lenW = gx + srcW;
                    if (srcH > lenH)
                    {
                        lenH = srcH;
                    }
                }
                //--------------------------
                //fill color on 'stencil' mask
                {
                    //select component to render this need to render 3 times for lcd technique
                    //1. B
                    _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.B;
                    _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B;
                    _painter.FillRect(startX + 1, startY, lenW, lenH);
                    //2. G
                    _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.G;
                    _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G;
                    _painter.FillRect(startX + 1, startY, lenW, lenH);
                    //3. R
                    _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.R;
                    _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R;
                    _painter.FillRect(startX + 1, startY, lenW, lenH);
                }
            }

            //
            _painter.DestBitmapBlender.OutputPixelBlender = prevPxBlender;//restore back
        }
Exemplo n.º 15
0
        private void cmdMeasureTextSpan_Click(object sender, System.EventArgs e)
        {
            //set some Gdi+ props...
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.Clear(Color.White);
            //credit:
            //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control
            g.ScaleTransform(1.0F, -1.0F);           // Flip the Y-Axis
            g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly

            //--------------------------------
            //textspan measurement sample
            //--------------------------------
            _currentTextPrinter.HintTechnique     = (HintTechnique)lstHintList.SelectedItem;
            _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem;
            //render at specific pos
            float x_pos = 0, y_pos = 100;

            char[] textBuffer = txtInputChar.Text.ToCharArray();

            //Example 1: this is a basic draw sample
            _currentTextPrinter.FillColor      = Color.Black;
            _currentTextPrinter.TargetGraphics = g;
            _currentTextPrinter.DrawString(
                textBuffer,
                0,
                textBuffer.Length,
                x_pos,
                y_pos
                );
            //
            //--------------------------------------------------
            //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw)
            //you can create you own class to hold userGlyphPlans.***
            //2.1

            _reusableUnscaledGlyphPlanList.Clear();
            _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList);
            //2.2
            //and we can print the formatted glyph plan later.
            y_pos -= _currentTextPrinter.FontLineSpacingPx;
            _currentTextPrinter.FillColor = Color.Red;

            _currentTextPrinter.DrawFromGlyphPlans(
                new GlyphPlanSequence(_reusableUnscaledGlyphPlanList),
                x_pos,
                y_pos
                );

            //Example 3: MeasureString

            Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface;

            UnscaledGlyphPlanList userGlyphPlans = new UnscaledGlyphPlanList();

            _currentTextPrinter.GlyphLayoutMan.GenerateUnscaledGlyphPlans(userGlyphPlans);

            MeasuredStringBox strBox = new MeasuredStringBox();

            throw new System.NotSupportedException();

            //_currentTextPrinter.GlyphLayoutMan.LayoutAndMeasureString(
            //  textBuffer, 0, textBuffer.Length,
            //  _currentTextPrinter.FontSizeInPoints,
            //  true,
            //  userGlyphPlans);

            float x_pos2 = x_pos + strBox.width + 10;

            g.DrawRectangle(Pens.Red, x_pos, y_pos + strBox.descending, strBox.width, strBox.CalculateLineHeight());
            g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos);                                          //baseline
            g.DrawLine(Pens.Green, x_pos, y_pos + strBox.descending, x_pos2, y_pos + strBox.descending); //descending
            g.DrawLine(Pens.Magenta, x_pos, y_pos + strBox.ascending, x_pos2, y_pos + strBox.ascending); //ascending


            Typography.OpenFont.TypefaceExtension2.UpdateAllCffGlyphBounds(typeface);
            float pxscale = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints);

            int j = userGlyphPlans.Count;

            for (int i = 0; i < j; ++i)
            {
                UnscaledGlyphPlan         glyphPlan = userGlyphPlans[i];
                Typography.OpenFont.Glyph glyph     = typeface.GetGlyphByIndex(glyphPlan.glyphIndex);
                //
                Typography.OpenFont.Bounds b = glyph.Bounds;
                //
                float xmin = b.XMin * pxscale;
                float ymin = b.YMin * pxscale;
                //
                float xmax = b.XMax * pxscale;
                float ymax = b.YMax * pxscale;
                //
                float glyph_x = x_pos + glyphPlan.OffsetX;
                g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin);
            }


            //------------
            _currentTextPrinter.FillColor = Color.Black;
            //transform back
            g.ScaleTransform(1.0F, -1.0F);           // Flip the Y-Axis
            g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly
        }
Exemplo n.º 16
0
        public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan,
                                                     ILineSegmentList lineSegs, RequestFont font,
                                                     int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight)
        {
            //layout
            //from font
            //resolve for typeface
            //
            Typeface typeface = ResolveTypeface(font);

            _txtServices.SetCurrentFont(typeface, font.SizeInPoints);


            MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs;
            float             scale      = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            outputTotalW = 0;
            int j   = mylineSegs.Count;
            int pos = 0; //start at 0

            _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer());

            for (int i = 0; i < j; ++i)
            {
                //userGlyphPlanList.Clear();
                //userCharToGlyphMapList.Clear();
                //get each segment
                MyLineSegment lineSeg = mylineSegs.GetSegment(i);
                //each line seg may has different script lang
                _txtServices.CurrentScriptLang = lineSeg.scriptLang;
                //
                //CACHING ...., reduce number of GSUB/GPOS
                //
                //we cache used line segment for a while
                //we ask for caching context for a specific typeface and font size
                GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                  lineSeg.StartAt,
                                                                                  lineSeg.Length);


                //IMPORTANT
                //num of glyph may more or less than original user input char buffer
                //


                //float g_x = 0;
                //float g_y = 0;
                //int baseY = (int)Math.Round(y);
                //int n = glyphPlanSeq.len;
                //int endBefore = glyphPlanSeq.startAt + n;

                ////***
                //_glsx.SetAssociatedTextureInfo(_glBmp);

                //List<float> vboBufferList = new List<float>();
                //List<ushort> indexList = new List<ushort>();

                //for (int i = glyphPlanSeq.startAt; i < endBefore; ++i)
                //{
                //    GlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq);
                //    GlyphPlan glyph = glyphPlanList[i];

                //    Typography.Rendering.TextureGlyphMapData glyphData;
                //    if (!_fontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData))
                //    {
                //        //if no glyph data, we should render a missing glyph ***
                //        continue;
                //    }
                //    //if (scaleFromTexture != 1)
                //    //{

                //    //}
                //    //--------------------------------------
                //    //TODO: review precise height in float
                //    //--------------------------------------
                //    PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect);
                //    g_x = (float)(x + (glyph.ExactX * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                //    g_y = (float)(y + (glyph.ExactY * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);


                //    //for sharp glyph
                //    //we adjust g_x,g_y to integer value
                //    //float g_y2 = (float)Math.Floor(g_y);

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


                //    switch (textureKind)
                //    {
                //        case TextureKind.Msdf:

                //            _glsx.DrawSubImageWithMsdf(_glBmp,
                //                ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);

                //            break;
                //        case TextureKind.StencilGreyScale:

                //            //stencil gray scale with fill-color
                //            _glsx.DrawGlyphImageWithStecil(_glBmp,
                //             ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);

                //            break;
                //        case TextureKind.Bitmap:
                //            _glsx.DrawSubImage(_glBmp,
                //             ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);
                //            break;
                //        case TextureKind.StencilLcdEffect:
                //            _glsx.WriteVboToList(
                //              vboBufferList,
                //              indexList,
                //              ref srcRect,
                //              g_x,
                //              g_y,
                //              scaleFromTexture);
                //            break;
                //    }
                //}
                ////---------


                int seqLen = seq.Count;

                for (int s = 0; s < seqLen; ++s)
                {
                    UnscaledGlyphPlan glyphPlan = seq[s];

                    double actualAdvX = glyphPlan.AdvanceX;

                    outputTotalW +=
                        outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] +=
                            (int)Math.Round(actualAdvX * scale);
                }
                pos += lineSeg.Length;
            }

            //

            lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale);

            _reusableTextBuffer.SetRawCharBuffer(null);
        }
Exemplo n.º 17
0
 public void Append(UnscaledGlyphPlan glyphPlan)
 {
     _glyphPlans.Add(glyphPlan);
 }
Exemplo n.º 18
0
        public void PrepareStringForRenderVx(GLRenderVxFormattedString renderVxFormattedString, char[] buffer, int startAt, int len)
        {
            int top  = 0; //simulate top
            int left = 0; //simulate left

            _vboBuilder.Clear();
            _vboBuilder.SetTextureInfo(_glBmp.Width, _glBmp.Height, _glBmp.IsYFlipped, _pcx.OriginKind);

            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);

            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font);
            float             px_scale     = _px_scale;
            //--------------------------
            TextureKind textureKind = _fontAtlas.TextureKind;
            float       g_left      = 0;
            float       g_top       = 0;

            int   baseLine = (int)Math.Round((float)top + _font.AscentInPixels);
            int   bottom   = (int)Math.Round((float)top + _font.AscentInPixels - _font.DescentInPixels);
            float acc_x    = 0; //local accumulate x
            float acc_y    = 0; //local accumulate y

            int seqLen = glyphPlanSeq.Count;

            for (int i = 0; i < seqLen; ++i)
            {
                UnscaledGlyphPlan glyph = glyphPlanSeq[i];
                Typography.Rendering.TextureGlyphMapData glyphData;
                if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                //paint src rect
                //temp fix, glyph texture img is not flipped
                //but the associate info is flipped => so
                //we need remap exact Y from the image
                Rectangle srcRect =
                    new Rectangle(glyphData.Left,
                                  _glBmp.Height - (glyphData.Top + glyphData.Height),
                                  glyphData.Width,
                                  glyphData.Height);

                //offset length from 'base-line'
                float x_offset = acc_x + (float)Math.Round(glyph.OffsetX * px_scale - glyphData.TextureXOffset);
                float y_offset = acc_y + (float)Math.Round(glyph.OffsetY * px_scale - glyphData.TextureYOffset) + srcRect.Height; //***

                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------

                g_left = (float)(left + x_offset);
                g_top  = (float)(bottom - y_offset); //***

                acc_x += (float)Math.Round(glyph.AdvanceX * px_scale);
                //g_x = (float)Math.Round(g_x); //***
                g_top = (float)Math.Floor(g_top);//adjust to integer num ***
                //
                _vboBuilder.WriteVboToList(ref srcRect, g_left, g_top);
            }
            //---
            //copy vbo result and store into  renderVx
            float[]  vertexList = _vboBuilder._buffer.ToArray();
            ushort[] indexList  = _vboBuilder._indexList.ToArray();
            //---

            renderVxFormattedString.IndexArrayCount = _vboBuilder._indexList.Count;
            renderVxFormattedString.IndexArray      = _vboBuilder._indexList.ToArray();
            renderVxFormattedString.VertexCoords    = _vboBuilder._buffer.ToArray();
            _vboBuilder.Clear();
        }
Exemplo n.º 19
0
        public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y)
        {
            AggPainter painter = p as AggPainter;



            if (painter == null)
            {
                return;
            }
            //

            int width  = painter.Width;
            int height = painter.Height;

            if (!_pixelBlenderSetup)
            {
                SetupMaskPixelBlender(width, height);
                _pixelBlenderSetup = true;
            }

            int j = buffer.Length;
            //create temp buffer span that describe the part of a whole char buffer
            TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len);
            //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan)
            //with specific request font
            GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font);

            float scale = 1;// _fontAtlas.TargetTextureScale;
            int   recommendLineSpacing = (int)_font.LineSpacingInPixels;

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            y -= _font.LineSpacingInPixels;

            //
            float       scaleFromTexture = _finalTextureScale;
            TextureKind textureKind      = _fontAtlas.TextureKind;

            float gx    = 0;
            float gy    = 0;
            int   baseY = (int)Math.Round(y);

            float acc_x = 0;
            float acc_y = 0;

            int lineHeight = (int)_font.LineSpacingInPixels;//temp

            //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender
            painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender

            int seqLen = glyphPlanSeq.Count;

            for (int i = 0; i < seqLen; ++i)
            {
                UnscaledGlyphPlan   glyph = glyphPlanSeq[i];
                TextureGlyphMapData glyphData;
                if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData))
                {
                    //if no glyph data, we should render a missing glyph ***
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                int srcX, srcY, srcW, srcH;
                glyphData.GetRect(out srcX, out srcY, out srcW, out srcH);

                float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale);
                float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale);
                //NOTE:
                // -glyphData.TextureXOffset => restore to original pos
                // -glyphData.TextureYOffset => restore to original pos
                //--------------------------
                gx = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                gy = (float)(y + (ngy - glyphData.TextureYOffset - srcH + lineHeight) * scaleFromTexture);

                acc_x += (float)Math.Round(glyph.AdvanceX * scale);
                gy     = (float)Math.Floor(gy) + lineHeight;

                //clear with solid black color
                //_maskBufferPainter.Clear(Color.Black);
                _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black);
                //draw 'stencil' glyph on mask-buffer
                _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY), srcW, srcH);

                //select component to render this need to render 3 times for lcd technique
                //1. B
                _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.B;
                _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B;
                painter.FillRect(gx + 1, gy, srcW, srcH);
                //2. G
                _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.G;
                _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G;
                painter.FillRect(gx + 1, gy, srcW, srcH);
                //3. R
                _maskPixelBlenderPerCompo.SelectedMaskComponent      = PixelBlenderColorComponent.R;
                _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R;
                painter.FillRect(gx + 1, gy, srcW, srcH);
            }
        }
Exemplo n.º 20
0
        public override void DrawFromGlyphPlans(UnscaledGlyphPlanList glyphPlanList, int startAt, int len, float x, float y)
        {
            Painter painter = this.TargetCanvasPainter;

            if (StartDrawOnLeftTop)
            {
                //version 2
                //offset y down
                y += this.FontLineSpacingPx;
            }


            //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         = _currentTypeface.CalculateScaleToPixelFromPointSize(fontSizePoint);


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

            Typography.OpenFont.Tables.COLR colrTable = _currentTypeface.COLRTable;
            Typography.OpenFont.Tables.CPAL cpalTable = _currentTypeface.CPALTable;
            bool hasColorGlyphs = (colrTable != null) && (cpalTable != null);

            //---------------------------------------------------
            _glyphMeshStore.SetFont(_currentTypeface, fontSizePoint);
            //---------------------------------------------------

            float g_x   = 0;
            float g_y   = 0;
            float baseY = (int)y;

            if (!hasColorGlyphs)
            {
                bool           savedUseLcdMode   = painter.UseSubPixelLcdEffect; //save,restore later
                RenderQualtity savedRederQuality = painter.RenderQuality;
                painter.RenderQuality        = RenderQualtity.HighQuality;
                painter.UseSubPixelLcdEffect = true;

                Agg.Transform.Affine flipY = Agg.Transform.Affine.NewMatix(
                    Agg.Transform.AffinePlan.Scale(1, -1)); //flip Y
                VertexStore reusableVxs = new VertexStore();

                float acc_x = 0; //acummulate x
                float acc_y = 0; //acummulate y

                for (int i = startAt; i < endBefore; ++i)
                {   //-----------------------------------
                    //TODO: review here ***
                    //PERFORMANCE revisit here
                    //if we have create a vxs we can cache it for later use?
                    //-----------------------------------
                    UnscaledGlyphPlan glyphPlan = glyphPlanList[i];

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

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


                    g_x = ngx;
                    g_y = ngy;
                    painter.SetOrigin(g_x, g_y);

                    //-----------------------------------

                    //invert each glyph
                    //version 3:

                    reusableVxs.Clear();
                    VertexStore vxs = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex);
                    flipY.TransformToVxs(vxs, reusableVxs);
                    painter.Fill(reusableVxs);


                    //version2;
                    //VertexStore vsx = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex);
                    //_vxs1 = _invertY.TransformToVxs(vsx, _vxs1);
                    //painter.Fill(_vxs1);
                    //_vxs1.Clear();

                    //version1
                    //painter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex));
                }
                //restore
                painter.RenderQuality        = savedRederQuality;
                painter.UseSubPixelLcdEffect = savedUseLcdMode;
            }
            else
            {
                //-------------
                //this glyph has color information
                //-------------
                Color originalFillColor = painter.FillColor;

                float acc_x = 0;
                float acc_y = 0;
                for (int i = startAt; i < endBefore; ++i)
                {
                    UnscaledGlyphPlan glyphPlan = glyphPlanList[i];

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

                    g_x = ngx;
                    g_y = ngy;

                    acc_x += (float)Math.Round(glyphPlan.AdvanceX * scale);
                    painter.SetOrigin(g_x, g_y);


                    //-----------------------------------
                    ushort colorLayerStart;
                    if (colrTable.LayerIndices.TryGetValue(glyphPlan.glyphIndex, out colorLayerStart))
                    {
                        //TODO: optimize this
                        //we found color info for this glyph
                        ushort colorLayerCount = colrTable.LayerCounts[glyphPlan.glyphIndex];
                        byte   r, g, b, a;
                        for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c)
                        {
                            ushort gIndex = colrTable.GlyphLayers[c];

                            int palette = 0;                                              // FIXME: assume palette 0 for now
                            cpalTable.GetColor(
                                cpalTable.Palettes[palette] + colrTable.GlyphPalettes[c], //index
                                out r, out g, out b, out a);
                            //-----------
                            painter.FillColor = new Color(r, g, b);//? a component
                            painter.Fill(_glyphMeshStore.GetGlyphMesh(gIndex));
                        }
                    }
                    else
                    {
                        //-----------------------------------
                        //TODO: review here ***
                        //PERFORMANCE revisit here
                        //if we have create a vxs we can cache it for later use?
                        //-----------------------------------
                        painter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex));
                    }
                }
                painter.FillColor = originalFillColor; //restore color
            }
            //restore prev origin
            painter.SetOrigin(ox, oy);
        }