Beispiel #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GlyphMetric"/> struct.
 /// </summary>
 /// <param name="codePoint">Unicode codepoint of the character.</param>
 /// <param name="bounds">The bounds.</param>
 /// <param name="isControlCharacter">Whether the character is a control character.</param>
 public GlyphMetric(int codePoint, FontRectangle bounds, bool isControlCharacter)
 {
     this.Codepoint          = codePoint;
     this.Character          = char.ConvertFromUtf32(codePoint);
     this.Bounds             = bounds;
     this.IsControlCharacter = isControlCharacter;
 }
Beispiel #2
0
        internal FontRectangle BoundingBox(Vector2 dpi)
        {
            FontRectangle box = this.Glyph.BoundingBox(this.Location * dpi, dpi);

            if (this.IsWhiteSpace)
            {
                box = new FontRectangle(box.X, box.Y, this.Width * dpi.X, box.Height);
            }

            return(box);
        }
Beispiel #3
0
        internal static FontRectangle GetBounds(IReadOnlyList <GlyphLayout> glyphLayouts, Vector2 dpi)
        {
            if (glyphLayouts.Count == 0)
            {
                return(FontRectangle.Empty);
            }

            bool hasSize = false;

            float left   = int.MaxValue;
            float top    = int.MaxValue;
            float bottom = int.MinValue;
            float right  = int.MinValue;

            for (int i = 0; i < glyphLayouts.Count; i++)
            {
                GlyphLayout c = glyphLayouts[i];
                if (!c.IsControlCharacter)
                {
                    hasSize = true;
                    FontRectangle box = c.BoundingBox(dpi);
                    if (left > box.Left)
                    {
                        left = box.Left;
                    }

                    if (top > box.Top)
                    {
                        top = box.Top;
                    }

                    if (bottom < box.Bottom)
                    {
                        bottom = box.Bottom;
                    }

                    if (right < box.Right)
                    {
                        right = box.Right;
                    }
                }
            }

            if (!hasSize)
            {
                return(FontRectangle.Empty);
            }

            float width  = right - left;
            float height = bottom - top;

            return(new FontRectangle(left, top, width, height));
        }
Beispiel #4
0
        /// <summary>
        /// Renders the text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="options">The style.</param>
        public void RenderText(ReadOnlySpan <char> text, TextOptions options)
        {
            IReadOnlyList <GlyphLayout> glyphsToRender = this.layoutEngine.GenerateLayout(text, options);
            FontRectangle rect = TextMeasurer.GetBounds(glyphsToRender, options.Dpi);

            this.renderer.BeginText(rect);

            foreach (GlyphLayout g in glyphsToRender)
            {
                if (g.IsWhiteSpace())
                {
                    continue;
                }

                g.Glyph.RenderTo(this.renderer, g.Location, options);
            }

            this.renderer.EndText();
        }
        internal static FontRectangle GetBounds(IReadOnlyList <GlyphLayout> glyphLayouts, float dpi)
        {
            if (glyphLayouts.Count == 0)
            {
                return(FontRectangle.Empty);
            }

            float left   = int.MaxValue;
            float top    = int.MaxValue;
            float bottom = int.MinValue;
            float right  = int.MinValue;

            for (int i = 0; i < glyphLayouts.Count; i++)
            {
                FontRectangle box = glyphLayouts[i].BoundingBox(dpi);
                if (left > box.Left)
                {
                    left = box.Left;
                }

                if (top > box.Top)
                {
                    top = box.Top;
                }

                if (bottom < box.Bottom)
                {
                    bottom = box.Bottom;
                }

                if (right < box.Right)
                {
                    right = box.Right;
                }
            }

            return(FontRectangle.FromLTRB(left, top, right, bottom));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="GlyphBounds"/> struct.
 /// </summary>
 /// <param name="codePoint">The Unicode codepoint for the glyph.</param>
 /// <param name="bounds">The glyph bounds.</param>
 public GlyphBounds(CodePoint codePoint, FontRectangle bounds)
 {
     this.Codepoint = codePoint;
     this.Bounds    = bounds;
 }
Beispiel #7
0
        /// <summary>
        /// Renders the glyph to the render surface in font units relative to a bottom left origin at (0,0)
        /// </summary>
        /// <param name="surface">The surface.</param>
        /// <param name="pointSize">Size of the point.</param>
        /// <param name="location">The location.</param>
        /// <param name="dpi">The dpi.</param>
        /// <param name="lineHeight">The lineHeight the current glyph was draw agains to offset topLeft while calling out to IGlyphRenderer.</param>
        /// <exception cref="NotSupportedException">Too many control points</exception>
        public void RenderTo(IGlyphRenderer surface, float pointSize, Vector2 location, Vector2 dpi, float lineHeight)
        {
            location = location * dpi;

            Vector2 firstPoint = Vector2.Zero;

            Vector2 scaledPoint = dpi * pointSize;

            FontRectangle box = this.BoundingBox(location, scaledPoint);

            var paramaters = new GlyphRendererParameters(this, pointSize, dpi);

            if (surface.BeginGlyph(box, paramaters))
            {
                int startOfContor = 0;
                int endOfContor   = -1;
                for (int i = 0; i < this.endPoints.Length; i++)
                {
                    surface.BeginFigure();
                    startOfContor = endOfContor + 1;
                    endOfContor   = this.endPoints[i];

                    Vector2 prev = Vector2.Zero;
                    Vector2 curr = this.GetPoint(ref scaledPoint, endOfContor) + location;
                    Vector2 next = this.GetPoint(ref scaledPoint, startOfContor) + location;

                    if (this.onCurves[endOfContor])
                    {
                        surface.MoveTo(curr);
                    }
                    else
                    {
                        if (this.onCurves[startOfContor])
                        {
                            surface.MoveTo(next);
                        }
                        else
                        {
                            // If both first and last points are off-curve, start at their middle.
                            Vector2 startPoint = (curr + next) / 2;
                            surface.MoveTo(startPoint);
                        }
                    }

                    int length = (endOfContor - startOfContor) + 1;
                    for (int p = 0; p < length; p++)
                    {
                        prev = curr;
                        curr = next;
                        int currentIndex = startOfContor + p;
                        int nextIndex    = startOfContor + ((p + 1) % length);
                        int prevIndex    = startOfContor + (((length + p) - 1) % length);
                        next = this.GetPoint(ref scaledPoint, nextIndex) + location;

                        if (this.onCurves[currentIndex])
                        {
                            // This is a straight line.
                            surface.LineTo(curr);
                        }
                        else
                        {
                            Vector2 prev2 = prev;
                            Vector2 next2 = next;

                            if (!this.onCurves[prevIndex])
                            {
                                prev2 = (curr + prev) / 2;
                                surface.LineTo(prev2);
                            }

                            if (!this.onCurves[nextIndex])
                            {
                                next2 = (curr + next) / 2;
                            }

                            surface.LineTo(prev2);
                            surface.QuadraticBezierTo(curr, next2);
                        }
                    }

                    surface.EndFigure();
                }
            }

            surface.EndGlyph();
        }