Esempio n. 1
0
        void LayoutWithoutHorizontalFitAlign(IGlyphPositions posStream, GlyphPlanList outputGlyphPlanList)
        {
            //the default OpenFont layout without fit-to-writing alignment
            int    finalGlyphCount = posStream.Count;
            float  pxscale         = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints);
            double cx = 0;
            short  cy = 0;

            for (int i = 0; i < finalGlyphCount; ++i)
            {
                short  offsetX, offsetY, advW; //all from pen-pos
                ushort glyphIndex = posStream.GetGlyph(i, out offsetX, out offsetY, out advW);

                float s_advW  = advW * pxscale;
                float exact_x = (float)(cx + offsetX * pxscale);
                float exact_y = (float)(cy + offsetY * pxscale);

                //outputGlyphPlanList.Append(new GlyphPlan(
                //   glyphIndex,
                //    exact_x,
                //    exact_y,
                //    advW)); //old?
                outputGlyphPlanList.Append(new GlyphPlan(
                                               glyphIndex,
                                               exact_x,
                                               exact_y,
                                               s_advW));

                cx += s_advW;
            }
        }
Esempio n. 2
0
 public OpenFontIFonts()
 {
     typefaceStore = new TypefaceStore();
     typefaceStore.FontCollection = InstalledFontCollection.GetSharedFontCollection(null);
     glyphLayout            = new GlyphLayout(); //create glyph layout with default value
     userGlyphPlanList      = new GlyphPlanList();
     userCharToGlyphMapList = new List <UserCharToGlyphIndexMap>();
 }
Esempio n. 3
0
        public override void DrawFromGlyphPlans(GlyphPlanList 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;

            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);
            }
        }
Esempio n. 4
0
        public GlyphPlanList StringToGlyphPlanList(string s, double font_size)
        {
            GlyphPlanList l = new GlyphPlanList();

            m_layout.Layout(s.ToCharArray(), 0, s.Length);
            var scale = m_openfont.CalculateScaleToPixelFromPointSize((float)font_size);

            GlyphLayoutExtensions.GenerateGlyphPlan(m_layout.ResultUnscaledGlyphPositions, scale,
                                                    snapToGrid: true, outputGlyphPlanList: l);
            return(l);
        }
Esempio n. 5
0
 public virtual void GenerateGlyphPlan(
     char[] textBuffer,
     int startAt,
     int len,
     GlyphPlanList outputGlyphPlanList,
     List <UserCharToGlyphIndexMap> charToGlyphMapList)
 {
     this.GlyphLayoutMan.Layout(textBuffer, startAt, len);
     GlyphLayoutExtensions.GenerateGlyphPlan(this.GlyphLayoutMan.ResultUnscaledGlyphPositions,
                                             this.Typeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints),
                                             false, outputGlyphPlanList);
 }
Esempio n. 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);
            }
        }
        GlyphPlanSequence CreateGlyphPlanSeq(GlyphLayout glyphLayout, TextBuffer buffer, int startAt, int len)
        {
            GlyphPlanList planList  = GlyphPlanBuffer.UnsafeGetGlyphPlanList(_glyphPlanBuffer);
            int           pre_count = planList.Count;

            glyphLayout.Typeface   = _typeface;
            glyphLayout.ScriptLang = _scLang;
            glyphLayout.Layout(
                TextBuffer.UnsafeGetCharBuffer(buffer),
                startAt,
                len);


            int post_count = planList.Count;

            return(new GlyphPlanSequence(_glyphPlanBuffer, pre_count, post_count - pre_count));
        }
Esempio n. 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;
        }
Esempio n. 9
0
 /// <summary>
 /// draw glyph plan list at (xpos,ypos) of baseline
 /// </summary>
 /// <param name="glyphPlanList"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 public abstract void DrawFromGlyphPlans(GlyphPlanList glyphPlanList, int startAt, int len, float x, float y);
Esempio n. 10
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);
        }
Esempio n. 11
0
        ////=========================================================================
        ////msdf texture generator example
        //private void cmdBuildMsdfTexture_Click(object sender, System.EventArgs e)
        //{
        //    string sampleFontFile = Path.Combine("..", "..", "..", "TestFonts", "tahoma.ttf");
        //    CreateSampleMsdfTextureFont(
        //        sampleFontFile,
        //        18,
        //        0,
        //        255,
        //        "d:\\WImageTest\\sample_msdf.png");
        //}
        //static void CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex, string outputFile)
        //{
        //    //sample
        //    var reader = new OpenFontReader();

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


        //        for (ushort n = startGlyphIndex; n <= endGlyphIndex; ++n)
        //        {
        //            //build glyph
        //            builder.BuildFromGlyphIndex(n, sizeInPoint);
        //            var glyphToContour = new GlyphTranslatorToContour();
        //            builder.ReadShapes(glyphToContour);
        //            //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours());

        //            GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour);
        //            atlasBuilder.AddGlyph(n, glyphImg);

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

        //        var glyphImg2 = atlasBuilder.BuildSingleImage();
        //        using (Bitmap bmp = new Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
        //        {
        //            var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height),
        //                System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
        //            int[] intBuffer = glyphImg2.GetImageBuffer();

        //            System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length);
        //            bmp.UnlockBits(bmpdata);
        //            bmp.Save("d:\\WImageTest\\a_total.png");
        //        }
        //        atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml");
        //    }
        //}
        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
            GlyphPlanList userGlyphPlans = new GlyphPlanList();

            _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, userGlyphPlans, null);
            //2.2
            //and we can print the formatted glyph plan later.
            y_pos -= _currentTextPrinter.FontLineSpacingPx;
            _currentTextPrinter.FillColor = Color.Red;
            _currentTextPrinter.DrawFromGlyphPlans(
                userGlyphPlans,
                x_pos,
                y_pos
                );
            //Example 3: MeasureString
            MeasuredStringBox strBox = _currentTextPrinter.MeasureString(textBuffer, 0, textBuffer.Length);
            //draw line mark

            float x_pos2 = x_pos + strBox.width + 10;

            g.DrawRectangle(Pens.Red, x_pos, y_pos, 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



            _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
        }
Esempio n. 12
0
 public void DrawFromGlyphPlans(GlyphPlanList glyphPlanList, float xpos, float ypos)
 {
     DrawFromGlyphPlans(glyphPlanList, 0, glyphPlanList.Count, xpos, ypos);
 }
Esempio n. 13
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;
                }
            }
        }
Esempio n. 14
0
 public void DrawFromGlyphPlans(GlyphPlanList glyphPlanList, float x, float y)
 {
     DrawFromGlyphPlans(glyphPlanList, 0, glyphPlanList.Count, x, y);
 }
 public static void GetGlyphPos(ActualFont actualFont, char[] buffer, int startAt, int len, GlyphPlanList properGlyphs)
 {
     defaultSharpingService.GetGlyphPosImpl(actualFont, buffer, startAt, len, properGlyphs);
 }
Esempio n. 16
0
        public void Layout(IGlyphPositions posStream, GlyphPlanList outputGlyphPlanList)
        {
            if (!UseWithLcdSubPixelRenderingTechnique)
            {
                //layout without fit to alignment direction
                LayoutWithoutHorizontalFitAlign(posStream, outputGlyphPlanList);
                return; //early exit
            }
            //------------------------------
            int   finalGlyphCount = posStream.Count;
            float pxscale         = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints);

#if DEBUG
            float dbug_onepx = 1 / pxscale;
#endif
            //
            int   cx = 0;
            short cy = 0;
            //
            //at this state, we need exact info at this specific pxscale
            //
            _hintedFontStore.SetFont(_typeface, this._fontSizeInPoints);
            FineABC current_ABC = new FineABC();
            FineABC prev_ABC    = new FineABC();

            for (int i = 0; i < finalGlyphCount; ++i)
            {
                short  offsetX, offsetY, advW; //all from pen-pos
                ushort glyphIndex = posStream.GetGlyph(i, out offsetX, out offsetY, out advW);
                GlyphControlParameters controlPars = _hintedFontStore.GetControlPars(glyphIndex);
                current_ABC.SetData(pxscale, controlPars, offsetX, offsetY, (ushort)advW);
                //-------------------------------------------------------------

                if (i > 0)
                {
                    //inter-glyph space
                    //ideal space
                    float ideal_space = prev_ABC.s_c + current_ABC.s_a;
                    //actual space
                    float actual_space = prev_ABC.m_c + current_ABC.m_a;

                    if (ideal_space < 0)
                    {
                        //f-f
                        //f-o
                        if (prev_ABC.s_c < 0)
                        {
                            ideal_space = 0 + current_ABC.s_a;
                        }
                        if (ideal_space < 0)
                        {
                            ideal_space = 0;
                        }
                    }
                    if (ideal_space >= 0)
                    {
                        //m-a
                        //i-i
                        //o-p
                        if (actual_space > 1.5 && actual_space - 0.5 > ideal_space)
                        {
                            cx--;
                        }
                        else
                        {
                            if (actual_space < ideal_space)
                            {
                                if (prev_ABC.final_advW + prev_ABC.m_c_adjust < prev_ABC.m_max)
                                {
                                    cx += current_ABC.m_a_adjust;
                                }
                            }
                            else
                            {
                                if (prev_ABC.final_advW - prev_ABC.m_c + prev_ABC.m_c_adjust > prev_ABC.m_max)
                                {
                                    cx += prev_ABC.m_c_adjust;
                                }
                            }
                        }
                    }
                    else
                    {
                        //this should not occur?
                    }
                }
                //-------------------------------------------------------------
                float exact_x = (float)(cx + current_ABC.s_offsetX);
                float exact_y = (float)(cy + current_ABC.s_offsetY);

                //check if the current position can create a sharp glyph
                int   exact_x_floor   = (int)exact_x;
                float x_offset_to_fit = current_ABC.s_avg_x_ToFit;

                float final_x = exact_x_floor + x_offset_to_fit;
                if (UseWithLcdSubPixelRenderingTechnique)
                {
                    final_x += 0.33f;
                }

                outputGlyphPlanList.Append(new GlyphPlan(
                                               glyphIndex,
                                               final_x,
                                               exact_y,
                                               current_ABC.final_advW));
                //
                //
                cx += current_ABC.final_advW;
                //-----------------------------------------------
                prev_ABC = current_ABC;//copy current to prev
#if DEBUG
                prev_ABC.dbugIsPrev = true;
#endif
                // Console.WriteLine(exact_x + "+" + (x_offset_to_fit) + "=>" + final_x);
            }
        }
Esempio n. 17
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);
        }
Esempio n. 18
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);
        }
 protected abstract void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, GlyphPlanList properGlyphs);