Esempio n. 1
0
        public override void DrawFromGlyphPlans(GlyphPlanSequence seq, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

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

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

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


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

            float cx = 0;
            float cy = 0;

            float baseline = y;

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

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

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


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

                g.TranslateTransform(cx, cy);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, foundPath);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, foundPath);
                }
                //and then we reset back ***
                g.TranslateTransform(-cx, -cy);
            }
        }
Esempio n. 2
0
        } // End Function GetExistingOrCreateGraphicsPath

        // public override void DrawFromGlyphPlans(GlyphPlanSequence glyphPlanList, int startAt, int len, float left, float top)
        public override void DrawFromGlyphPlans(GlyphPlanSequence seq, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

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

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


            Typeface typeface = this.Typeface;

            _glyphMeshCollections.SetCacheInfo(typeface, sizeInPoints, this.HintTechnique);


            //this draw a single line text span***
            SvgGraphics g        = this.TargetGraphics;
            float       baseline = y;
            GlyphPlanSequenceSnapPixelScaleLayout snapToPxScale =
                new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, pxscale);

            COLR colrTable = typeface.COLRTable;
            CPAL cpalTable = typeface.CPALTable;

            bool canUseColorGlyph = EnableColorGlyph && colrTable != null && cpalTable != null;

            while (snapToPxScale.Read())
            {
                ushort glyphIndex = snapToPxScale.CurrentGlyphIndex;

                if (canUseColorGlyph && colrTable.LayerIndices.TryGetValue(glyphIndex, out ushort colorLayerStart))
                {
                    ushort colorLayerCount = colrTable.LayerCounts[glyphIndex];

                    for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c)
                    {
                        SvgPath path = GetExistingOrCreateGraphicsPath(colrTable.GlyphLayers[c]);
                        if (path == null)
                        {
#if DEBUG
                            System.Diagnostics.Debug.WriteLine("gdi_printer: no path?");
#endif
                            continue;
                        } // End if (path == null)

                        //then move pen point to the position we want to draw a glyph
                        float cx = (float)System.Math.Round(snapToPxScale.ExactX + x);
                        float cy = (float)System.Math.Floor(snapToPxScale.ExactY + baseline);

                        int palette = 0;                                              // FIXME: assume palette 0 for now
                        cpalTable.GetColor(
                            cpalTable.Palettes[palette] + colrTable.GlyphPalettes[c], //index
                            out byte red, out byte green, out byte blue, out byte alpha);


                        g.TranslateTransform(cx, cy);

                        _fillBrush.Color = SvgColor.ToWebRgb(red, green, blue);

                        if (FillBackground)
                        {
                            g.FillPath(_fillBrush, path);
                        }

                        if (DrawOutline)
                        {
                            g.DrawPath(_outlinePen, path);
                        }

                        // and then we reset back
                        g.TranslateTransform(-cx, -cy);
                    } // Next c
                }
                else
                {
                    SvgPath path = GetExistingOrCreateGraphicsPath(glyphIndex);

                    if (path == null)
                    {
#if DEBUG
                        System.Diagnostics.Debug.WriteLine("gdi_printer: no path?");
#endif
                        continue;
                    }

                    //------
                    //then move pen point to the position we want to draw a glyph
                    float cx = (float)System.Math.Round(snapToPxScale.ExactX + x);
                    float cy = (float)System.Math.Floor(snapToPxScale.ExactY + baseline);

                    g.TranslateTransform(cx, cy);

                    if (FillBackground)
                    {
                        g.FillPath(_fillBrush, path);
                    }

                    if (DrawOutline)
                    {
                        g.DrawPath(_outlinePen, path);
                    }

                    // and then we reset back
                    g.TranslateTransform(-cx, -cy);
                } // End else
            }     // Whend
        }         // End Sub DrawFromGlyphPlans
Esempio n. 3
0
        public override void DrawFromGlyphPlans(GlyphPlanSequence seq, int startAt, int len, float left, float top)
        {
            if (StartDrawOnLeftTop)
            {
                //version 2
                //offset y down
                top += this.FontLineSpacingPx;
            }

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

            //4. render each glyph
            float ox = _painter.OriginX;
            float oy = _painter.OriginY;


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

            //---------------------------------------------------
            _glyphMeshStore.SetHintTechnique(this.HintTechnique);
            _glyphMeshStore.SetFont(_currentTypeface, fontSizePoint);
            _glyphMeshStore.SimulateOblique = this.SimulateSlant;
            //---------------------------------------------------


            if (_currentTypeface.HasSvgTable())
            {
                _glyphSvgStore.SetCurrentTypeface(_currentTypeface);
                int seqLen = seq.Count;
                if (len > seqLen)
                {
                    len = seqLen;
                }

                var snapToPx = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, scale);
                while (snapToPx.Read())
                {
                    _painter.SetOrigin((float)Math.Round(left + snapToPx.ExactX) + 0.33f, (float)Math.Floor(top + snapToPx.ExactY));

                    GlyphBitmap glyphBmp = _glyphSvgStore.GetGlyphBitmap(snapToPx.CurrentGlyphIndex);
                    //how to draw the image
                    //1.
                    if (glyphBmp != null)
                    {
                        _painter.DrawImage(glyphBmp.Bitmap);
                    }
                }
            }
            else if (_currentTypeface.IsBitmapFont)
            {
                //check if we have exported all the glyph bitmap
                //to some 'ready' form?
                //if not then create it
                _glyphBitmapStore.SetCurrentTypeface(_currentTypeface);

                int seqLen = seq.Count;

                if (len > seqLen)
                {
                    len = seqLen;
                }

                var snapToPx = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, scale);
                while (snapToPx.Read())
                {
                    _painter.SetOrigin((float)Math.Round(left + snapToPx.ExactX) + 0.33f, (float)Math.Floor(top + snapToPx.ExactY));
                    GlyphBitmap glyphBmp = _glyphBitmapStore.GetGlyphBitmap(snapToPx.CurrentGlyphIndex);
                    //how to draw the image
                    //1.
                    _painter.DrawImage(glyphBmp.Bitmap);
                }
            }
            else
            {
                if (!hasColorGlyphs)
                {
                    bool          savedUseLcdMode   = _painter.UseSubPixelLcdEffect; //save,restore later
                    RenderQuality savedRederQuality = _painter.RenderQuality;
                    _painter.RenderQuality        = RenderQuality.HighQuality;
                    _painter.UseSubPixelLcdEffect = true;

                    int seqLen = seq.Count;

                    if (len > seqLen)
                    {
                        len = seqLen;
                    }

                    var snapToPx = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, scale);
                    while (snapToPx.Read())
                    {
                        _painter.SetOrigin((float)Math.Round(left + snapToPx.ExactX) + 0.33f, (float)Math.Floor(top + snapToPx.ExactY));
                        _painter.Fill(_glyphMeshStore.GetGlyphMesh(snapToPx.CurrentGlyphIndex));
                    }

                    //restore
                    _painter.RenderQuality        = savedRederQuality;
                    _painter.UseSubPixelLcdEffect = savedUseLcdMode;
                }
                else
                {
                    //-------------
                    //this glyph has color information
                    //-------------
                    Color originalFillColor = _painter.FillColor;
                    int   seqLen            = seq.Count;

                    if (len > seqLen)
                    {
                        len = seqLen;
                    }

                    var snapToPx = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, scale);
                    while (snapToPx.Read())
                    {
                        _painter.SetOrigin((float)Math.Round(left + snapToPx.ExactX), (float)Math.Floor(top + snapToPx.ExactY));

                        ushort colorLayerStart;
                        if (colrTable.LayerIndices.TryGetValue(snapToPx.CurrentGlyphIndex, out colorLayerStart))
                        {
                            //TODO: optimize this
                            //we found color info for this glyph
                            ushort colorLayerCount = colrTable.LayerCounts[snapToPx.CurrentGlyphIndex];
                            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(snapToPx.CurrentGlyphIndex));
                        }
                    }

                    _painter.FillColor = originalFillColor; //restore color
                }
            }
            //restore prev origin
            _painter.SetOrigin(ox, oy);
        }
Esempio n. 4
0
        void RenderAndShowMeasureBox()
        {
            bool flipY = chkFlipY.Checked;


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

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


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


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


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

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

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

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

                _currentTextPrinter.DrawFromFormattedGlyphPlans(
                    _ftmGlyphPlansList,
                    x_pos,
                    y_pos
                    );


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

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


                float baseline = y_pos;

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

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

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


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

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

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

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

                            x_pos += glyphPlan.AdvanceX * pxscale;

                            nn++;
                        }

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

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


                //
                GlyphPlanSequence seq = new GlyphPlanSequence(_reusableUnscaledGlyphPlanList);

                _currentTextPrinter.DrawFromGlyphPlans(
                    seq,
                    x_pos,
                    y_pos
                    );

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

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

                _currentTextPrinter.MeasureGlyphPlanSeq(seq, out int textspanW);

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


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

                x_pos = backup_xpos;

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


                float x_pos2 = x_pos + textspanW + 10;


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

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


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


                _currentTextPrinter.FillColor = Color.Black;

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



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

            //---------

            //txtMsgInfo.Text = "choice:" + choice.ToString() + "=" + lineSpacing.ToString();
        }