< Summary

Class:Imagini.Fonts.SpriteFontPage
Assembly:Imagini.Fonts
File(s):/home/razer/vscode-projects/project-grove/imagini/Imagini.Fonts/SpriteFontPage.cs
Covered lines:35
Uncovered lines:3
Coverable lines:38
Total lines:105
Line coverage:92.1% (35 of 38)
Covered branches:10
Total branches:10
Branch coverage:100% (10 of 10)

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
.ctor(...)1062.5%100%
RenderFontToTexture(...)80100%100%
HasGlyph(...)10100%100%
GetGlyph(...)20100%100%

File(s)

/home/razer/vscode-projects/project-grove/imagini/Imagini.Fonts/SpriteFontPage.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Drawing;
 4using System.Linq;
 5using SixLabors.Fonts;
 6using SixLabors.ImageSharp;
 7using SixLabors.ImageSharp.PixelFormats;
 8using SixLabors.ImageSharp.Processing;
 9using SixLabors.Shapes.Temp;
 10
 11using SPointF = SixLabors.Primitives.PointF;
 12
 13namespace Imagini.Fonts
 14{
 15    /// <summary>
 16    /// Represents a sprite font page with the texture atlas and glyph bounds data.
 17    /// </summary>
 18    public class SpriteFontPage
 19    {
 20        /// <summary>
 21        /// Returns the starting code point of this page.
 22        /// </summary>
 70123        public char Start { get; private set; }
 24        /// <summary>
 25        /// Returns the ending code point of this page.
 26        /// </summary>
 67627        public char End { get; private set; }
 28
 1829        private Dictionary<char, Rectangle> _glyphMap =
 030            new Dictionary<char, Rectangle>();
 31
 32        /// <summary>
 33        /// Returns the Image containing the glyphs of this page.
 34        /// </summary>
 35        /// <remarks>
 36        /// Intended for use by text renderers.
 37        /// Can be disposed and nullified by the renderer if it
 38        /// uses other surface type (GPU texture, for example).
 39        /// </remarks>
 67240        public Image<Rgba32> Texture { get; set; }
 41
 042        internal SpriteFontPage(Font font,
 043            ref ISet<char> requestedSymbols, int textureSize, int padding)
 44        {
 1845            Texture = new Image<Rgba32>(textureSize, textureSize);
 3646            Texture.Mutate(x => x.Fill(Rgba32.Transparent));
 1847            RenderFontToTexture(font, ref requestedSymbols, textureSize, padding);
 1848        }
 49
 50        private void RenderFontToTexture(Font font,
 51            ref ISet<char> requestedSymbols, int textureSize, int padding)
 52        {
 1853            var options = new RendererOptions(font);
 5454            int x = 0, y = 0, maxHeight = 0;
 55            do
 56            {
 60657                var glyphStr = $"{requestedSymbols.First()}";
 60658                var glyph = glyphStr[0];
 60659                var sizeF = TextMeasurer.Measure(glyphStr, options);
 60660                var size = new Size((int)Math.Ceiling(sizeF.Width), (int)Math.Ceiling(sizeF.Height));
 60661                maxHeight = Math.Max(maxHeight, size.Height);
 62
 60663                var dstRect = new Rectangle(x, y, size.Width, size.Height);
 60664                if (dstRect.Right >= textureSize)
 65                {
 66                    // jump onto the next line
 5267                    x = 0;
 5268                    y += maxHeight + padding;
 5269                    maxHeight = 0;
 5270                    dstRect.X = x;
 5271                    dstRect.Y = y;
 72                }
 60673                if (dstRect.Bottom >= textureSize)
 74                {
 75                    // we can't fit letters anymore
 76                    break;
 77                }
 78
 59779                var shapes = TextBuilder.GenerateGlyphs(glyphStr, new SPointF(x, y), options);
 119480                Texture.Mutate(m => m.Fill(Rgba32.White, shapes));
 59781                _glyphMap.Add(glyph, dstRect);
 59782                requestedSymbols.Remove(glyph);
 61483                if (Start == default(char)) Start = glyph;
 59784                End = glyph;
 85
 59786                x += size.Width + padding;
 59787            } while (requestedSymbols.Any());
 1888        }
 89
 90        /// <summary>
 91        /// Checks if this page contains the specified symbol.
 92        /// </summary>
 15793        public bool HasGlyph(char symbol) => _glyphMap.ContainsKey(symbol);
 94
 95        /// <summary>
 96        /// Returns the rectangle defining pixel region where the specified
 97        /// glyph is located. Returns empty rectangle if the glyph is not present.
 98        /// </summary>
 99        public Rectangle GetGlyph(char symbol)
 100        {
 168101            if (!HasGlyph(symbol)) return Rectangle.Empty;
 130102            return _glyphMap[symbol];
 103        }
 104    }
 105}