Exemple #1
0
        public static unsafe DrawableFontAtlas RenderFontStbPacked(byte[] ttf, float fontSize, Vector2 atlasSize, int numChars, Font f, out StbTrueType.stbtt_fontinfo fontInfo)
        {
            var atlasObj = new DrawableFontAtlas(f, fontSize);

            fontSize = atlasObj.FontSize;

            fontInfo = new StbTrueType.stbtt_fontinfo();
            fixed(byte *ttPtr = &ttf[0])
            {
                StbTrueType.stbtt_InitFont(fontInfo, ttPtr, 0);

                float scaleFactor = StbTrueType.stbtt_ScaleForMappingEmToPixels(fontInfo, fontSize);
                int   ascent, descent, lineGap;

                StbTrueType.stbtt_GetFontVMetrics(fontInfo, &ascent, &descent, &lineGap);

                atlasSize *= 3; // Needs to be big as the packing sucks, and glyphs getting cut out messes with the tests.
                var pixels = new byte[(int)atlasSize.X * (int)atlasSize.Y];

                var pc = new StbTrueType.stbtt_pack_context();

                fixed(byte *pixelsPtr = pixels)
                {
                    StbTrueType.stbtt_PackBegin(pc, pixelsPtr, (int)atlasSize.X, (int)atlasSize.Y, (int)atlasSize.X, 1, null);
                }

                var cd = new StbTrueType.stbtt_packedchar[numChars];

                fixed(StbTrueType.stbtt_packedchar *charPtr = cd)
                {
                    StbTrueType.stbtt_PackFontRange(pc, ttPtr, 0, -fontSize, 0, numChars, charPtr);
                }

                StbTrueType.stbtt_PackEnd(pc);
                for (var i = 0; i < cd.Length; ++i)
                {
                    var atlasGlyph = DrawableGlyph.CreateForTest(cd[i].xadvance, cd[i].xoff, cd[i].x1 - cd[i].x0, cd[i].y1 - cd[i].y0);
                    atlasGlyph.GlyphUV       = new Rectangle(cd[i].x0, cd[i].y0, atlasGlyph.Width, atlasGlyph.Height);
                    atlasObj.Glyphs[(char)i] = atlasGlyph;
                }
            }

            return(atlasObj);
        }
        public static TtfFontBakerResult Bake(byte[] ttf, float fontPixelHeight,
                                              int bitmapWidth, int bitmapHeight,
                                              IEnumerable <CharacterRange> characterRanges)
        {
            if (ttf == null || ttf.Length == 0)
            {
                throw new ArgumentNullException(nameof(ttf));
            }

            if (fontPixelHeight <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(fontPixelHeight));
            }

            if (bitmapWidth <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bitmapWidth));
            }

            if (bitmapHeight <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bitmapHeight));
            }

            if (characterRanges == null)
            {
                throw new ArgumentNullException(nameof(characterRanges));
            }

            if (!characterRanges.Any())
            {
                throw new ArgumentException("characterRanges must have a least one value.");
            }

            byte[] pixels;
            var    glyphs = new Dictionary <int, GlyphInfo>();

            fixed(byte *ttfPtr = ttf)
            {
                StbTrueType.stbtt_fontinfo fontInfo = new StbTrueType.stbtt_fontinfo();
                if (StbTrueType.stbtt_InitFont(fontInfo, ttfPtr, 0) == 0)
                {
                    throw new Exception("Failed to init font.");
                }

                float scaleFactor = StbTrueType.stbtt_ScaleForPixelHeight(fontInfo, fontPixelHeight);

                int ascent, descent, lineGap;

                StbTrueType.stbtt_GetFontVMetrics(fontInfo, &ascent, &descent, &lineGap);

                pixels = new byte[bitmapWidth * bitmapHeight];
                StbTrueType.stbtt_pack_context pc = new StbTrueType.stbtt_pack_context();
                fixed(byte *pixelsPtr = pixels)
                {
                    StbTrueType.stbtt_PackBegin(pc, pixelsPtr, bitmapWidth,
                                                bitmapHeight, bitmapWidth, 1, null);
                }

                foreach (var range in characterRanges)
                {
                    if (range.Start > range.End)
                    {
                        continue;
                    }

                    var cd = new StbTrueType.stbtt_packedchar[range.End - range.Start + 1];
                    fixed(StbTrueType.stbtt_packedchar *chardataPtr = cd)
                    {
                        StbTrueType.stbtt_PackFontRange(pc, ttfPtr, 0, fontPixelHeight,
                                                        range.Start,
                                                        range.End - range.Start + 1,
                                                        chardataPtr);
                    }

                    for (var i = 0; i < cd.Length; ++i)
                    {
                        var yOff = cd[i].yoff;
                        yOff += ascent * scaleFactor;

                        var glyphInfo = new GlyphInfo
                        {
                            X        = cd[i].x0,
                            Y        = cd[i].y0,
                            Width    = cd[i].x1 - cd[i].x0,
                            Height   = cd[i].y1 - cd[i].y0,
                            XOffset  = (int)cd[i].xoff,
                            YOffset  = (int)Math.Round(yOff),
                            XAdvance = (int)Math.Round(cd[i].xadvance)
                        };

                        glyphs[(char)(i + range.Start)] = glyphInfo;
                    }
                }
            }

            return(new TtfFontBakerResult(glyphs, fontPixelHeight, pixels, bitmapWidth, bitmapHeight));
        }
Exemple #3
0
        public void Add(byte[] ttf, float fontPixelHeight,
                        IEnumerable <CharacterRange> characterRanges)
        {
            if (ttf == null || ttf.Length == 0)
            {
                throw new ArgumentNullException(nameof(ttf));
            }

            if (fontPixelHeight <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(fontPixelHeight));
            }

            if (characterRanges == null)
            {
                throw new ArgumentNullException(nameof(characterRanges));
            }

            if (!characterRanges.Any())
            {
                throw new ArgumentException("characterRanges must have a least one value.");
            }

            var fontInfo = StbTrueType.CreateFont(ttf, 0);

            if (fontInfo == null)
            {
                throw new Exception("Failed to init font.");
            }

            var scaleFactor = StbTrueType.stbtt_ScaleForPixelHeight(fontInfo, fontPixelHeight);

            int ascent, descent, lineGap;

            StbTrueType.stbtt_GetFontVMetrics(fontInfo, &ascent, &descent, &lineGap);

            foreach (var range in characterRanges)
            {
                if (range.Start > range.End)
                {
                    continue;
                }

                var cd = new StbTrueType.stbtt_packedchar[range.End - range.Start + 1];
                fixed(StbTrueType.stbtt_packedchar *chardataPtr = cd)
                {
                    StbTrueType.stbtt_PackFontRange(_context, fontInfo.data, 0, fontPixelHeight,
                                                    range.Start,
                                                    range.End - range.Start + 1,
                                                    chardataPtr);
                }

                for (var i = 0; i < cd.Length; ++i)
                {
                    var yOff = cd[i].yoff;
                    yOff += ascent * scaleFactor;

                    var glyphInfo = new GlyphInfo
                    {
                        X        = cd[i].x0,
                        Y        = cd[i].y0,
                        Width    = cd[i].x1 - cd[i].x0,
                        Height   = cd[i].y1 - cd[i].y0,
                        XOffset  = (int)cd[i].xoff,
                        YOffset  = (int)Math.Round(yOff),
                        XAdvance = (int)Math.Round(cd[i].xadvance)
                    };

                    _glyphs[i + range.Start] = glyphInfo;
                }
            }
        }