示例#1
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();
                GlyphLayoutExtensions.GenerateGlyphPlans(
                    _glyphLayout.ResultUnscaledGlyphPositions,
                    pxscale,
                    true,
                    _reusableGlyphPlanList);
                //measure each glyph
                //limit at specific width
                int glyphCount = _reusableGlyphPlanList.Count;
                for (int i = 0; i < glyphCount; ++i)
                {
                    GlyphPlan glyphPlan = _reusableGlyphPlanList[i];
                    float     right     = glyphPlan.ExactRight * pxscale;
                    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;
        }
示例#2
0
        public override void DrawFromGlyphPlans(List <GlyphPlan> glyphPlanList, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

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

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

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


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

            Graphics g = this.TargetGraphics;

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

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

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

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

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

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

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

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

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

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

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

                outputTextRun.AddGlyph(
                    new GlyphRun(glyphPlan,
                                 processGlyph.tessData,
                                 processGlyph.tessNElements));
            }
        }
示例#4
0
        public void DrawString(char[] text, int startAt, int len, double x, double y)
        {
            float ox = canvasPainter.OriginX;
            float oy = canvasPainter.OriginY;

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

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

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

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

                    //TODO: review here,
                    //float pxScale = _glyphPathBuilder.GetPixelScale();
                    glyphVxs = new VertexStore();
                    _tovxs.WriteOutput(glyphVxs, _vxsPool);
                    //
                    hintGlyphCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, glyphVxs);
                }
                canvasPainter.SetOrigin((float)(glyphPlan.x * scale + x), (float)(glyphPlan.y * scale + y));
                canvasPainter.Fill(glyphVxs);
            }
            //restore prev origin
            canvasPainter.SetOrigin(ox, oy);
        }
示例#5
0
        public override void DrawGlyphPlanList(List <GlyphPlan> glyphPlanList, int startAt, int len, float xpos, float ypos)
        {
            CanvasPainter canvasPainter = this.TargetCanvasPainter;
            Typeface      typeface      = _glyphPathBuilder.Typeface;
            //3. layout glyphs with selected layout technique
            //TODO: review this again, we should use pixel?

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


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

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

                    //TODO: review here,
                    //float pxScale = _glyphPathBuilder.GetPixelScale();
                    glyphVxs = new VertexStore();
                    _tovxs.WriteOutput(glyphVxs, _vxsPool);
                    //
                    hintGlyphCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, glyphVxs);
                }
                canvasPainter.SetOrigin((float)(glyphPlan.x * scale + xpos), (float)(glyphPlan.y * scale + ypos));
                canvasPainter.Fill(glyphVxs);
            }
            //restore prev origin
            canvasPainter.SetOrigin(ox, oy);
        }
示例#6
0
        public void Draw()
        {
            GlyphPlanList glyphPlans = _line._glyphPlans;
            List <UserCharToGlyphIndexMap> userCharToGlyphIndexMap = _line._userCharToGlyphMap;

            if (_line.ContentChanged)
            {
                //re-calculate
                char[] textBuffer = _line._charBuffer.ToArray();
                glyphPlans.Clear();

                userCharToGlyphIndexMap.Clear();

                //read glyph plan and userCharToGlyphIndexMap

                _printer.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, glyphPlans, userCharToGlyphIndexMap);


                toPxScale            = _printer.Typeface.CalculateScaleToPixelFromPointSize(_printer.FontSizeInPoints);
                _line.ContentChanged = false;
            }

            if (glyphPlans.Count > 0)
            {
                _printer.DrawFromGlyphPlans(glyphPlans, X, Y);
                //draw caret
                //not blink in this version
                int caret_index = _line.CaretCharIndex;
                //find caret pos based on glyph plan
                //TODO: check when do gsub (glyph number may not match with user char number)

                if (caret_index == 0)
                {
                    _printer.DrawCaret(X, this.Y);
                }
                else
                {
                    UserCharToGlyphIndexMap map = userCharToGlyphIndexMap[caret_index - 1];
                    GlyphPlan p = glyphPlans[map.glyphIndexListOffset_plus1 + map.len - 2];
                    _printer.DrawCaret(X + p.ExactRight, this.Y);
                }
            }
            else
            {
                _printer.DrawCaret(X, this.Y);
            }
        }
        public void DoLeft()
        {
            int count = _charBuffer.Count;

            if (count == 0)
            {
                _caretCharIndex = 0;
                return;
            }
            else if (_caretCharIndex > 0)
            {
                //this is on the end
                _caretCharIndex--;

                //check if the caret can rest on this glyph?
                if (_caretCharIndex > 0)
                {
                    //find its mapping to glyph index
                    UserCharToGlyphIndexMap userCharToGlyphMap = _userCharToGlyphMap[_caretCharIndex];
                    int mapToGlyphIndex = userCharToGlyphMap.glyphIndexListOffset_plus1;
                    //
                    if (mapToGlyphIndex == 0)
                    {
                        //no map
                        DoLeft();   //recursive ***
                        return;
                    }
                    //-------------------------
                    //we -1 ***
                    GlyphPlan glyphPlan = _glyphPlans[userCharToGlyphMap.glyphIndexListOffset_plus1 - 1];
                    if (glyphPlan.advX <= 0)
                    {
                        //caret can't rest here
                        //so
                        DoLeft();   //recursive ***
                        return;
                    }
                    //---------------------
                    //
                }
            }
            else
            {
            }
        }
示例#8
0
        public static void CopyGlyphPlans(RenderVxFormattedString renderVx, GlyphPlanList glyphPlans, float scale)
        {
            int n = glyphPlans.Count;
            //copy
            var renderVxGlyphPlans = new RenderVxGlyphPlan[n];

            for (int i = 0; i < n; ++i)
            {
                GlyphPlan glyphPlan = glyphPlans[i];
                renderVxGlyphPlans[i] = new RenderVxGlyphPlan(
                    glyphPlan.glyphIndex,
                    glyphPlan.ExactX,
                    glyphPlan.ExactY,
                    glyphPlan.AdvanceX
                    );
            }
            renderVx.glyphList = renderVxGlyphPlans;
        }
示例#9
0
        public static void CopyGlyphPlans(RenderVxFormattedString renderVx, List <GlyphPlan> glyphPlans, float scale)
        {
            int n = glyphPlans.Count;
            //copy
            var renderVxGlyphPlans = new RenderVxGlyphPlan[n];

            for (int i = 0; i < n; ++i)
            {
                GlyphPlan glyphPlan = glyphPlans[i];
                renderVxGlyphPlans[i] = new RenderVxGlyphPlan(
                    glyphPlan.glyphIndex,
                    glyphPlan.x * scale,
                    glyphPlan.y * scale,
                    glyphPlan.advX * scale
                    );
            }
            renderVx.glyphList = renderVxGlyphPlans;
        }
        protected override void GetGlyphPosImpl(ActualFont actualFont, char[] buffer,
                                                int startAt, int len,
                                                List <GlyphPlan> glyphPlans)
        {
            NativeFont nativeFont = actualFont as NativeFont;

            if (nativeFont == null)
            {
                nativeFont = ResolveForNativeFont(actualFont);
            }

            unsafe
            {
                //TODO: review proper array size here
                int          lim = len * 2;
                ProperGlyph *properGlyphArray = stackalloc ProperGlyph[lim];
                fixed(char *head = &buffer[0])
                {
                    //we use font shaping engine here
                    NativeMyFontsLib.MyFtShaping(
                        nativeFont.NativeFontFace.HBFont,
                        head,
                        buffer.Length,
                        properGlyphArray);
                }

                //copy from proper glyph to
                //create glyph plan

                for (int i = 0; i < lim; ++i)
                {
                    ProperGlyph propGlyph = properGlyphArray[i];
                    if (propGlyph.codepoint == 0)
                    {
                        //finish , just return
                        return;
                    }
                    GlyphPlan plan = new GlyphPlan((ushort)propGlyph.codepoint);
                    plan.advX = propGlyph.x_advance;
                    glyphPlans.Add(plan);
                }
            }
        }
示例#11
0
        public void DoRight()
        {
            int count = _charBuffer.Count;

            if (count == 0)
            {
                return;
            }
            else if (_caretCharIndex < count)
            {
                //this is on the end
                _caretCharIndex++;

                //check if the caret can rest on this glyph?
                if (_caretCharIndex < count)
                {
                    //find its mapping to glyph index
                    UserCharToGlyphIndexMap userCharToGlyphMap = _userCharToGlyphMap[_caretCharIndex];
                    int mapToGlyphIndex = userCharToGlyphMap.glyphIndexListOffset_plus1;
                    //
                    if (mapToGlyphIndex == 0)
                    {
                        //no map
                        DoRight();   //recursive ***
                        return;
                    }
                    //-------------------------
                    //we -1 ***
                    GlyphPlan glyphPlan = _glyphPlans[userCharToGlyphMap.glyphIndexListOffset_plus1 - 1];
                    if (!glyphPlan.AdvanceMoveForward)
                    {
                        //caret can't rest here
                        //so
                        DoRight();   //recursive ***
                        return;
                    }
                }
            }
            else
            {
            }
        }
示例#12
0
        public override void DrawGlyphPlanList(List <GlyphPlan> glyphPlanList, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

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

            Graphics g = this.TargetGraphics;

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

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

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, path);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, path);
                }
            }
        }
示例#13
0
        public void DrawString(char[] text, double x, double y)
        {
            glyphPlanList.Clear();
            RequestFont currentFont = canvasPainter.CurrentFont;

            vxsTextPrinter.Print(currentFont.SizeInPoints, text, glyphPlanList);

            int glyphListLen = glyphPlanList.Count;

            float ox = canvasPainter.OriginX;
            float oy = canvasPainter.OriginY;

            for (int i = 0; i < glyphListLen; ++i)
            {
                GlyphPlan glyphPlan = glyphPlanList[i];
                canvasPainter.SetOrigin((float)(glyphPlan.x + x), (float)(glyphPlan.y + y));
                canvasPainter.Fill((VertexStore)glyphPlan.vxs);
            }
            canvasPainter.SetOrigin(ox, oy);
        }
示例#14
0
        List <ushort> inputGlyphs = new List <ushort>(); //not thread safe***
        public void Print(Typeface typeface, float size, char[] str, List <GlyphPlan> glyphPlanBuffer)
        {
            //1. layout
            _glyphLayout.Layout(typeface, size, str, glyphPlanBuffer);
            var glyphPathBuilder = new MyGlyphPathBuilder(typeface);
            int j = glyphPlanBuffer.Count;

            float pxScale = typeface.CalculateFromPointToPixelScale(size);

            for (int i = 0; i < j; ++i)
            {
                GlyphPlan glyphPlan = glyphPlanBuffer[i];
                //-----------------------------------
                //check if we static vxs/bmp for this glyph
                //if not, create and cache
                //-----------------------------------
                glyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, size);
                //-----------------------------------
                var vxsBuilder = new GlyphPathBuilderVxs();
                glyphPathBuilder.ReadShapes(vxsBuilder);
                glyphPlan.vxs = vxsBuilder.GetVxs(pxScale);
            }
        }
示例#15
0
        public override void DrawFromGlyphPlans(GlyphPlanList glyphPlanList, int startAt, int len, float x, float y)
        {
            CanvasPainter canvasPainter = this.TargetCanvasPainter;
            //Typeface typeface = _glyphPathBuilder.Typeface;
            //3. layout glyphs with selected layout technique
            //TODO: review this again, we should use pixel?

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


            //4. render each glyph
            float ox        = canvasPainter.OriginX;
            float oy        = canvasPainter.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)
            {
                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?
                    //-----------------------------------
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    g_x = glyphPlan.ExactX + x;
                    g_y = glyphPlan.ExactY + y;
                    canvasPainter.SetOrigin(g_x, g_y);
                    //-----------------------------------
                    canvasPainter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex));
                }
            }
            else
            {
                //-------------
                //this glyph has color information
                //-------------
                Color originalFillColor = canvasPainter.FillColor;

                for (int i = startAt; i < endBefore; ++i)
                {
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    g_x = glyphPlan.ExactX + x;
                    g_y = glyphPlan.ExactY + y;
                    canvasPainter.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);
                            //-----------
                            canvasPainter.FillColor = new Color(r, g, b);//? a component
                            canvasPainter.Fill(_glyphMeshStore.GetGlyphMesh(gIndex));
                        }
                    }
                    else
                    {
                        //-----------------------------------
                        //TODO: review here ***
                        //PERFORMANCE revisit here
                        //if we have create a vxs we can cache it for later use?
                        //-----------------------------------
                        canvasPainter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex));
                    }
                }
                canvasPainter.FillColor = originalFillColor; //restore color
            }
            //restore prev origin
            canvasPainter.SetOrigin(ox, oy);
        }
        public void DrawString(char[] buffer, int startAt, int len, double x, double y)
        {
            int j = buffer.Length;

            //resolve font from painter?
            glyphPlans.Clear();
            _glyphLayout.Layout(_typeface, buffer, startAt, len, glyphPlans);
            float scale = _typeface.CalculateToPixelScaleFromPointSize(font.SizeInPoints);

            //--------------------------
            //TODO:
            //if (x,y) is left top
            //we need to adjust y again
            y -= (_typeface.Ascender - _typeface.Descender + _typeface.LineGap) * scale;

            int n = glyphPlans.Count;

            EnsureLoadGLBmp();
            //
            float scaleFromTexture = _finalTextureScale;

            Typography.Rendering.TextureKind textureKind = simpleFontAtlas.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);
            //--------------------------
            GlyphPosPixelSnapKind x_snap = this.GlyphPosPixelSnapX;
            GlyphPosPixelSnapKind y_snap = this.GlyphPosPixelSnapY;
            float g_x   = 0;
            float g_y   = 0;
            int   baseY = (int)Math.Round(y);

            for (int i = 0; i < n; ++i)
            {
                GlyphPlan glyph = glyphPlans[i];
                Typography.Rendering.TextureFontGlyphData glyphData;
                if (!simpleFontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData))
                {
                    continue;
                }
                //--------------------------------------
                //TODO: review precise height in float
                //--------------------------------------
                PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect);
                switch (x_snap)
                {
                default: throw new NotSupportedException();

                case GlyphPosPixelSnapKind.Integer:
                {
                    g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture);         //ideal x
                    int floor_x = (int)g_x;

                    //round to int 0,1
                    if (g_x - floor_x >= (1f / 2f))
                    {
                        g_x = floor_x + 1;
                    }
                    else
                    {
                        g_x = floor_x;
                    }
                }
                break;

                case GlyphPosPixelSnapKind.Half:
                {
                    g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture);         //ideal x
                                                                                                                //adjust
                    int floor_x = (int)g_x;
                    //round to int 0, 0.5,1.0
                    if (g_x - floor_x >= (2f / 3f))
                    {
                        g_x = floor_x + 1;
                    }
                    else if (g_x - floor_x >= (1f / 3f))
                    {
                        g_x = floor_x + 0.5f;
                    }
                    else
                    {
                        g_x = floor_x;
                    }
                }
                break;

                case GlyphPosPixelSnapKind.None:
                    g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture);
                    break;
                }
                //
                switch (y_snap)
                {
                default: throw new NotSupportedException();

                case GlyphPosPixelSnapKind.Integer:
                    //use baseY not y
                {
                    g_y = (float)((glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);
                    int floor_y = (int)g_y;
                    //round to int 0,1
                    if (g_y - floor_y >= (1f / 2f))
                    {
                        g_y = floor_y + 1;
                    }
                    else
                    {
                        g_y = floor_y;
                    }
                    g_y = baseY + g_y;
                }
                break;

                case GlyphPosPixelSnapKind.Half:
                    //review here
                    //use baseY not y
                {
                    g_y = (float)((glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);
                    int floor_y = (int)g_y;
                    //round to int 0, 0.5,1.0
                    if (g_y - floor_y >= (2f / 3f))
                    {
                        g_y = floor_y + 1;
                    }
                    else if (g_x - floor_y >= (1f / 3f))
                    {
                        g_y = floor_y + 0.5f;
                    }
                    else
                    {
                        g_y = floor_y;
                    }
                    g_y = baseY + g_y;
                }
                break;

                case GlyphPosPixelSnapKind.None:
                    //use Y not baseY
                    g_y = (float)(y + (glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);
                    break;
                }

                switch (textureKind)
                {
                case Typography.Rendering.TextureKind.Msdf:

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

                    break;

                case Typography.Rendering.TextureKind.AggGrayScale:

                    canvas2d.DrawSubImage(_glBmp,
                                          ref srcRect,
                                          g_x,
                                          g_y,
                                          scaleFromTexture);

                    break;

                case Typography.Rendering.TextureKind.AggSubPixel:

                    canvas2d.DrawGlyphImageWithSubPixelRenderingTechnique(_glBmp,
                                                                          ref srcRect,
                                                                          g_x,
                                                                          g_y,
                                                                          scaleFromTexture);

                    break;
                }
            }
        }
示例#17
0
        void RenderWithTextPrinterAndMiniAgg(string fontfile, string str, float sizeInPoint, int resolution)
        {
            //1.
            if (printer2 == null)
            {
                printer2            = new TextPrinter();
                printer2.ScriptLang = ScriptLangs.Thai;
            }


            printer2.FontFile = fontfile;
            //
            printer2.EnableLigature    = this.chkGsubEnableLigature.Checked;
            printer2.PositionTechnique = (PositionTecnhique)cmbPositionTech.SelectedItem;
            //printer.EnableTrueTypeHint = this.chkTrueTypeHint.Checked;
            //printer.UseAggVerticalHinting = this.chkVerticalHinting.Checked;
            //
            int len = str.Length;
            //
            List <GlyphPlan> glyphPlanList = new List <GlyphPlan>(len);

            printer2.Print(sizeInPoint, str, glyphPlanList);
            //--------------------------

            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            p.Clear(PixelFarm.Drawing.Color.White);
            //---------------------------
            //TODO: review here
            //fake subpixel rendering
            //not correct

            p.UseSubPixelRendering = chkLcdTechnique.Checked;
            //---------------------------
            if (chkFillBackground.Checked)
            {
                //5.2
                p.FillColor = PixelFarm.Drawing.Color.Black;
                //5.3
                int glyphListLen = glyphPlanList.Count;

                float ox = p.OriginX;
                float oy = p.OriginY;
                float cx = 0;
                float cy = 10;
                for (int i = 0; i < glyphListLen; ++i)
                {
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    cx = glyphPlan.x;
                    cy = glyphPlan.y;
                    p.SetOrigin(cx, cy);
                    p.Fill((VertexStore)glyphPlan.vxs);
                }
                p.SetOrigin(ox, oy);
            }
            if (chkBorder.Checked)
            {
                //5.4
                p.StrokeColor = PixelFarm.Drawing.Color.Green;
                //user can specific border width here...
                //p.StrokeWidth = 2;
                //5.5
                int   glyphListLen = glyphPlanList.Count;
                float ox           = p.OriginX;
                float oy           = p.OriginY;
                float cx           = 0;
                float cy           = 10;
                for (int i = 0; i < glyphListLen; ++i)
                {
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    cx = glyphPlan.x;
                    p.SetOrigin(cx, cy);
                    p.Draw((VertexStore)glyphPlan.vxs);
                }
                p.SetOrigin(ox, oy);
            }
            //6. use this util to copy image from Agg actual image to System.Drawing.Bitmap
            PixelFarm.Agg.Imaging.BitmapHelper.CopyToGdiPlusBitmapSameSize(destImg, winBmp);
            //---------------
            //7. just render our bitmap
            g.Clear(Color.White);
            g.DrawImage(winBmp, new Point(10, 0));
            //--------------------------
        }
示例#18
0
        public override void DrawFromGlyphPlans(GlyphPlanList 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;
                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?
                    //-----------------------------------
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    g_x = glyphPlan.ExactX + x;
                    g_y = glyphPlan.ExactY + y;
                    painter.SetOrigin(g_x, g_y);
                    //-----------------------------------
                    //invert each glyph
                    //version 3:
                    painter.Fill(_glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex));
                    //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;

                for (int i = startAt; i < endBefore; ++i)
                {
                    GlyphPlan glyphPlan = glyphPlanList[i];
                    g_x = glyphPlan.ExactX + x;
                    g_y = glyphPlan.ExactY + y;
                    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);
        }
示例#19
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);

            _typographyTxtServices.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
                _typographyTxtServices.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 = _typographyTxtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                            lineSeg.StartAt,
                                                                                            lineSeg.Length);

                GlyphPlanList planList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(seq);
                //IMPORTANT
                //num of glyph may more or less than original user input char buffer
                //


                int endAt       = seq.startAt + seq.len;
                int seq_startAt = seq.startAt;

                for (int s = seq_startAt; s < endAt; ++s)
                {
                    GlyphPlan glyphPlan  = planList[s];
                    float     tx         = glyphPlan.ExactX;
                    float     ty         = glyphPlan.ExactY;
                    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);
        }
示例#20
0
        public void DrawString(char[] buffer, double x, double y)
        {
            int j        = buffer.Length;
            int buffsize = j * 2;

            //resolve font from painter?
            ActualFont fontImp = ff.GetFontAtPointsSize(font.SizeInPoints);
            var        tt      = (Typography.OpenFont.Typeface)ff.GetInternalTypeface();

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

            _glyphLayout.Layout(tt, font.SizeInPoints, buffer, glyphPlans);

            //
            //un-test version
            //ActualFont fontImp = nativeFontStore.GetResolvedNativeFont(painter.CurrentFont);
            //if (properGlyphs == null)
            //{
            //    properGlyphs = new ProperGlyph[buffsize];
            //    TextShapingService.GetGlyphPos(fontImp, buffer, 0, buffsize, properGlyphs);
            //}
            //TODO: implement msdf texture
            //double xpos = x;
            //for (int i = 0; i < buffsize; ++i)
            //{
            //    uint codepoint = properGlyphs[i].codepoint;
            //    if (codepoint == 0)
            //    {
            //        break;
            //    }

            //    //-------------------------------------------------------------
            //    FontGlyph glyph = fontImp.GetGlyphByIndex(codepoint);
            //    //glyph image32
            //    //-------------------------------------------------------------
            //    GLBitmap bmp = new GLBitmap(new LazyAggBitmapBufferProvider(glyph.glyphImage32));
            //    var left = glyph.glyphMatrix.img_horiBearingX;
            //    this.canvas2d.DrawImage(bmp,
            //        (float)(xpos + (left >> 6)),
            //        (float)(y + (glyph.glyphMatrix.bboxYmin >> 6)));
            //    int w = (glyph.glyphMatrix.advanceX) >> 6;
            //    xpos += (w);
            //    bmp.Dispose(); //temp here
            //    //-------------------------------------------------------------
            //}
            //-------------------------------------
            //msdf texture version
            double xpos = x;
            int    n    = glyphPlans.Count;

            Typography.Rendering.GlyphImage glyphImage = simpleFontAtlas.TotalGlyph;
            GLBitmap glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, glyphImage.GetImageBuffer(), false);

            float c_x = (float)x;
            float c_y = (float)y;

            //int left = ((int)(glyph.glyphMatrix.img_horiBearingX * scale) >> 6);
            int left = 0;
            //float baseline = c_y - 24;//eg line height= 24 //create a list
            float baseline = c_y - 24;//eg line height= 24 //create a list
            bool  isFlipY  = canvas2d.FlipY;

            if (!isFlipY)
            {
                canvas2d.FlipY = true;
            }
            for (int i = 0; i < n; ++i)
            {
                GlyphPlan glyph = glyphPlans[i];
                Typography.Rendering.TextureFontGlyphData glyphData;
                if (!simpleFontAtlas.GetRectByCodePoint(glyph.glyphIndex, out glyphData))
                {
                    //Rectangle r = glyphData.Rect;
                    //float x_min = glyphData.BBoxXMin / 64;
                    ////draw each glyph at specific position
                    ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
                    //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
                    ////c_x += r.Width - 10;
                    //c_x += (glyphData.AdvanceX / 64);
                    continue;
                }
                //found

                PixelFarm.Drawing.Rectangle r = ConvToRect(glyphData.Rect);
                //test draw full msdf gen img
                //canvas2d.DrawImage(glBmp, c_x + left, (float)(baseline + ((int)(glyphData.ImgHeight))));

                canvas2d.DrawSubImageWithMsdf(glBmp, ref r, c_x + left,
                                              (float)(baseline + ((int)(glyphData.ImgHeight))), 1.0f);

                c_x += glyph.advX;
            }

            canvas2d.FlipY = isFlipY;
            glBmp.Dispose();
            //temp here

            //draw with texture printer ***
            //char[] chars = text.ToCharArray();
            //int j = chars.Length;
            //int buffsize = j * 2;
            ////get kerning list

            ////get actual font for this canvas
            //TextureFont currentFont = _currentTextureFont;
            //SimpleFontAtlas fontAtlas = currentFont.FontAtlas;
            //ProperGlyph[] properGlyphs = new ProperGlyph[buffsize];
            //TextShapingService.GetGlyphPos(currentFont, chars, 0, buffsize, properGlyphs);
            //GLBitmap glBmp = (GLBitmap)currentFont.GLBmp;
            //if (glBmp == null)
            //{
            //    //create glbmp
            //    GlyphImage glyphImage = fontAtlas.TotalGlyph;
            //    int[] buffer = glyphImage.GetImageBuffer();
            //    glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, buffer, false);
            //}
            ////int j = chars.Length;
            ////
            //float c_x = (float)x;
            //float c_y = (float)y;

            ////TODO: review here ***
            ////-----------------
            ////1. layout each glyph before render ***
            ////
            //float baseline = c_y - 24;//eg line height= 24 //create a list

            ////--------------
            //List<float> coords = new List<float>();
            //float scale = 1f;
            //for (int i = 0; i < buffsize; ++i)
            //{
            //    ProperGlyph glyph1 = properGlyphs[i];
            //    uint codepoint = properGlyphs[i].codepoint;
            //    if (codepoint == 0)
            //    {
            //        break;
            //    }
            //    //--------------------------------
            //    //if (codepoint == 1173 && i > 1)
            //    //{
            //    //    //check prev code point
            //    //    codepoint = 1168;
            //    //}
            //    //--------------------------------
            //    TextureFontGlyphData glyphData;
            //    if (!fontAtlas.GetRectByCodePoint((int)codepoint, out glyphData))
            //    {
            //        //Rectangle r = glyphData.Rect;
            //        //float x_min = glyphData.BBoxXMin / 64;
            //        ////draw each glyph at specific position
            //        ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
            //        //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
            //        ////c_x += r.Width - 10;
            //        //c_x += (glyphData.AdvanceX / 64);
            //        continue;
            //    }



            //    FontGlyph glyph = currentFont.GetGlyphByIndex(codepoint);
            //    int left = ((int)(glyph.glyphMatrix.img_horiBearingX * scale) >> 6);
            //    Rectangle r = glyphData.Rect;
            //    int adjustX = 0;
            //    int bboxYMin = glyph.glyphMatrix.bboxYmin >> 6;
            //    if (bboxYMin > 1 || bboxYMin < -1)
            //    {
            //        //  adjustX = 3;
            //    }
            //    //scale down 0.8;
            //    //_canvas.DrawSubImageWithMsdf(glBmp, ref r, adjustX + c_x + left,
            //    //    (float)(baseline + ((int)(glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) >> 6)), 1.1f);

            //    coords.Add(r.Left);
            //    coords.Add(r.Top);
            //    coords.Add(r.Width);
            //    coords.Add(r.Height);
            //    //-------------------------
            //    coords.Add(adjustX + c_x + left);
            //    //coords.Add(baseline + ((int)((glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) * scale) >> 6));
            //    coords.Add(baseline + ((int)((glyphData.ImgHeight + glyphData.BBoxYMin) * scale) >> 6));
            //    //int w = (int)(glyph.glyphMatrix.advanceX * scale) >> 6;
            //    int w = (int)(glyph.horiz_adv_x * scale) >> 6;
            //    c_x += w;
            //}
            //_canvas.DrawSubImageWithMsdf(glBmp, coords.ToArray(), scale);

            //-----------------------
            //public override void DrawString(string text, double x, double y)
            //{

            //    char[] chars = text.ToCharArray();
            //    int j = chars.Length;
            //    int buffsize = j * 2;
            //    //get kerning list
            //    TextureFont currentFont = this.CurrentFont as TextureFont;
            //    SimpleFontAtlas fontAtlas = currentFont.FontAtlas;
            //    ProperGlyph[] properGlyphs = new ProperGlyph[buffsize];
            //    currentFont.GetGlyphPos(chars, 0, buffsize, properGlyphs);
            //    GLBitmap glBmp = currentFont.GLBmp;
            //    if (glBmp == null)
            //    {
            //        //create glbmp
            //        GlyphImage glyphImage = fontAtlas.TotalGlyph;
            //        int[] buffer = glyphImage.GetImageBuffer();
            //        glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, buffer, false);
            //    }
            //    //int j = chars.Length;
            //    //
            //    float c_x = (float)x;
            //    float c_y = (float)y;

            //    //TODO: review here
            //    //-----------------
            //    //1. layout each glyph before render ***
            //    float baseline = c_y - 24;//eg line height= 24
            //                              //create a list

            //    for (int i = 0; i < buffsize; ++i)
            //    {
            //        ProperGlyph glyph1 = properGlyphs[i];
            //        uint codepoint = properGlyphs[i].codepoint;
            //        if (codepoint == 0)
            //        {
            //            break;
            //        }
            //        if (codepoint == 1173 && i > 1)
            //        {
            //            //check prev code point
            //            codepoint = 1168;
            //        }
            //        TextureFontGlyphData glyphData;
            //        if (!fontAtlas.GetRect((int)codepoint, out glyphData))
            //        {
            //            //Rectangle r = glyphData.Rect;
            //            //float x_min = glyphData.BBoxXMin / 64;
            //            ////draw each glyph at specific position
            //            ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
            //            //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height));
            //            ////c_x += r.Width - 10;
            //            //c_x += (glyphData.AdvanceX / 64);
            //            continue;
            //        }

            //        //-------------------------------------------------------------
            //        //FontGlyph glyph = this.currentFont.GetGlyphByIndex(codepoint);
            //        FontGlyph glyph = currentFont.GetGlyphByIndex(codepoint);
            //        int left = (glyph.glyphMatrix.img_horiBearingX >> 6);
            //        Rectangle r = glyphData.Rect;
            //        int adjustX = 0;
            //        int bboxYMin = glyph.glyphMatrix.bboxYmin >> 6;
            //        if (bboxYMin > 1 || bboxYMin < -1)
            //        {
            //            //  adjustX = 3;
            //        }
            //        //scale down 0.8;
            //        _canvas.DrawSubImageWithMsdf(glBmp, ref r, adjustX + c_x + left,
            //            (float)(baseline + ((int)(glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) >> 6)), 1.1f);
            //        int w = (glyph.glyphMatrix.advanceX) >> 6;
            //        c_x += (w);
            //    }
            //}
            //        public override void DrawString(string text, double x, double y)
            //        {
            //            ////in this version we draw string to image
            //            ////and the write the image back to gl surface
            //            //_winGfx.Clear(System.Drawing.Color.White);
            //            //_winGfx.DrawString(text, _winFont, _winGfxBrush, 0, 0);
            //            ////_winGfxBackBmp.Save("d:\\WImageTest\\a00123.png");

            //            //System.Drawing.SizeF textAreaSize = _winGfx.MeasureString(text, _winFont);
            //            //var bmpData = _winGfxBackBmp.LockBits(new System.Drawing.Rectangle(0, 0, _winGfxBackBmp.Width, _winGfxBackBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, _winGfxBackBmp.PixelFormat);
            //            //int width = (int)textAreaSize.Width;
            //            //int height = (int)textAreaSize.Height;

            //            //ActualImage actualImg = new ActualImage(width, height, Agg.Image.PixelFormat.ARGB32);
            //            ////------------------------------------------------------
            //            ////copy bmp from specific bmp area
            //            ////and convert to GLBmp
            //            //int stride = bmpData.Stride;
            //            //byte[] buffer = actualImg.GetBuffer();
            //            //unsafe
            //            //{
            //            //    byte* header = (byte*)bmpData.Scan0;
            //            //    fixed (byte* dest0 = &buffer[0])
            //            //    {
            //            //        byte* dest = dest0;
            //            //        byte* rowHead = header;
            //            //        int rowLen = width * 4;
            //            //        for (int h = 0; h < height; ++h)
            //            //        {

            //            //            header = rowHead;
            //            //            for (int n = 0; n < rowLen;)
            //            //            {
            //            //                //move next
            //            //                *(dest + 0) = *(header + 0);
            //            //                *(dest + 1) = *(header + 1);
            //            //                *(dest + 2) = *(header + 2);
            //            //                *(dest + 3) = *(header + 3);
            //            //                header += 4;
            //            //                dest += 4;
            //            //                n += 4;
            //            //            }
            //            //            //finish one row
            //            //            rowHead += stride;
            //            //        }
            //            //    }
            //            //}
            //            //_winGfxBackBmp.UnlockBits(bmpData);
            //            ////------------------------------------------------------
            //            //GLBitmap glBmp = new GLBitmap(width, height, buffer, false);
            //            //_canvas.DrawImageWithWhiteTransparent(glBmp, (float)x, (float)y);
            //            //glBmp.Dispose();
            //        }
        }
示例#21
0
        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;

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

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

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

                Typography.Rendering.TextureFontGlyphData glyphData;
                if (!_fontAtlas.TryGetGlyphDataByCodePoint(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);
                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
                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.DrawGlyphImageWithSubPixelRenderingTechnique(_glBmp,
                                                                       ref srcRect,
                                                                       g_x,
                                                                       g_y,
                                                                       scaleFromTexture);

                    break;
                }
            }
        }