Ejemplo n.º 1
0
        private const int HORIZONTAL_OFFSET = 2; //Reduces artifacts when scaling up

        /// <summary>
        /// Generate a font from a font file.
        /// </summary>
        /// <param name="fontFileName">Name of the font file</param>
        /// <param name="fontSize">Size of the bitmap font</param>
        /// <param name="lowerChar">The lowest character to render</param>
        /// <param name="upperChar">The hightest character</param>
        /// <returns>A description for the font</returns>
        public static FontDescription GenerateFont(string fontFileName, float fontSize, char lowerChar = (char)32, char upperChar = (char)127)
        {
            var font = new FontFace(File.OpenRead(fontFileName));

            var glyphs = new Dictionary <char, (GlyphLayout, Glyph)>();

            var currentX = 0;
            var currentY = 0;
            var maxY     = 0;

            for (char i = lowerChar; i < upperChar; i++)
            {
                var glyph = font.GetGlyph(new CodePoint(i), fontSize);
                int w     = glyph.RenderWidth;
                int h     = glyph.RenderHeight;

                //Glyph would be to big
                if (currentX + w + HORIZONTAL_OFFSET > MAX_BITMAP_WIDTH)
                {
                    currentY += maxY;
                    maxY      = 0;
                    currentX  = 0;
                }

                //Glyph is biggest in its line
                if (h > maxY)
                {
                    maxY = h;
                }

                IntRect?region;
                if (w == 0 || h == 0)
                {
                    //Glyph is invisible, so it has no region on the bitmap
                    region = null;
                }
                else
                {
                    region = new IntRect(currentX, currentY, w, h);
                }

                var layout = new GlyphLayout(i, region, new Vector2(glyph.Width, glyph.Height), glyph.HorizontalMetrics.Bearing, glyph.HorizontalMetrics.Advance);
                currentX += w + HORIZONTAL_OFFSET;

                glyphs.Add(i, (layout, glyph));
            }

            var finalHeight = currentY + maxY;

            var bitmap = new Image <Rgba32>(MAX_BITMAP_WIDTH, finalHeight);

            var glyphTable = new Dictionary <char, GlyphLayout>();

            bitmap.Mutate(ctx =>
            {
                foreach (var glyphEntry in glyphs)
                {
                    var(layout, glyph) = glyphEntry.Value;
                    if (layout.BitmapRegion.HasValue)
                    {
                        //Glyph is renderable
                        var region = layout.BitmapRegion.Value;
                        var pos    = new Point(region.X, region.Y);
                        var img    = RenderGlyph(glyph);
                        ctx.DrawImage(img, 1f, pos);
                    }
                    glyphTable[glyphEntry.Key] = layout;
                }
            });

            var metadata = new FontMetadata(
                font.Family,
                font.Subfamily,
                fontSize,
                FontMetadata.StyleFrom(font.Style),
                (int)font.Weight,
                FontMetadata.StretchFrom(font.Stretch));

            return(new FontDescription(metadata, bitmap, new Glyphs(glyphTable)));
        }
 public FontDescription(FontMetadata metadata, Image <Rgba32> bitmap, Glyphs glyphs)
 {
     Metadata = metadata;
     Bitmap   = bitmap;
     Glyphs   = glyphs;
 }