Пример #1
0
        public int LoadFont(StbTrueType.stbtt_fontinfo font, byte *data, int dataSize)
        {
            var stbError = 0;

            font.userdata = this;
            stbError      = StbTrueType.stbtt_InitFont(font, data, 0);
            return(stbError);
        }
Пример #2
0
        public static StbTrueType.stbtt_fontinfo LoadFontStb(byte[] bytes)
        {
            var font = new StbTrueType.stbtt_fontinfo();

            unsafe
            {
                fixed(byte *fontDataPtr = &bytes[0])
                {
                    StbTrueType.stbtt_InitFont(font, fontDataPtr, 0);
                }
            }

            return(font);
        }
Пример #3
0
            static unsafe string GetName(StbTrueType.stbtt_fontinfo fontInfo, int nameID)
            {
                int length = 0;

                sbyte *ptr = StbTrueType.stbtt_GetFontNameString(fontInfo, &length,
                                                                 StbTrueType.STBTT_PLATFORM_ID_MICROSOFT,
                                                                 StbTrueType.STBTT_MS_EID_UNICODE_BMP,
                                                                 StbTrueType.STBTT_MS_LANG_ENGLISH,
                                                                 nameID);

                if (length > 0)
                {
                    return(new string(ptr, 0, length, Encoding.BigEndianUnicode));
                }

                return("Unknown");
            }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// Loads a Font from the byte array. The Font will use this buffer until it is disposed.
        /// </summary>
        public unsafe Font(byte[] buffer)
        {
            fontBuffer = buffer;
            fontHandle = GCHandle.Alloc(fontBuffer, GCHandleType.Pinned);
            fontInfo   = new StbTrueType.stbtt_fontinfo();

            StbTrueType.stbtt_InitFont(fontInfo, (byte *)(fontHandle.AddrOfPinnedObject().ToPointer()), 0);

            FamilyName = GetName(fontInfo, 1);
            StyleName  = GetName(fontInfo, 2);

            // properties
            int ascent, descent, linegap;

            StbTrueType.stbtt_GetFontVMetrics(fontInfo, &ascent, &descent, &linegap);
            Ascent     = ascent;
            Descent    = descent;
            LineGap    = linegap;
            Height     = Ascent - Descent;
            LineHeight = Height + LineGap;
Пример #6
0
        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));
        }
Пример #7
0
 public static float __tt_getPixelHeightScale(this StbTrueType.stbtt_fontinfo font, float size)
 {
     return((float)(StbTrueType.stbtt_ScaleForPixelHeight(font, (float)(size))));
 }
Пример #8
0
 public static void __tt_getFontVMetrics(this StbTrueType.stbtt_fontinfo font, int *ascent, int *descent, int *lineGap)
 {
     StbTrueType.stbtt_GetFontVMetrics(font, ascent, descent, lineGap);
 }
Пример #9
0
 public static int __tt_getGlyphKernAdvance(this StbTrueType.stbtt_fontinfo font, int glyph1, int glyph2)
 {
     return((int)(StbTrueType.stbtt_GetGlyphKernAdvance(font, (int)(glyph1), (int)(glyph2))));
 }
Пример #10
0
 public static void __tt_renderGlyphBitmap(this StbTrueType.stbtt_fontinfo font, byte *output, int outWidth, int outHeight, int outStride, float scaleX, float scaleY, int glyph)
 {
     StbTrueType.stbtt_MakeGlyphBitmap(font, output, (int)(outWidth), (int)(outHeight), (int)(outStride), (float)(scaleX), (float)(scaleY), (int)(glyph));
 }
Пример #11
0
 public static int __tt_buildGlyphBitmap(this StbTrueType.stbtt_fontinfo font, int glyph, float size, float scale, int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
 {
     StbTrueType.stbtt_GetGlyphHMetrics(font, (int)(glyph), advance, lsb);
     StbTrueType.stbtt_GetGlyphBitmapBox(font, (int)(glyph), (float)(scale), (float)(scale), x0, y0, x1, y1);
     return((int)(1));
 }
Пример #12
0
 public static int __tt_getGlyphIndex(this StbTrueType.stbtt_fontinfo font, int codepoint)
 {
     return((int)(StbTrueType.stbtt_FindGlyphIndex(font, (int)(codepoint))));
 }
Пример #13
0
        public static unsafe void CompareMetricsWithStb(Font f, DrawableFontAtlas atlas, StbTrueType.stbtt_fontinfo stbFont)
        {
            var pc = new StbTrueType.stbtt_pack_context();

            StbTrueType.stbtt_PackBegin(pc, (byte *)0, 512, 512, 512, 1, null);

            var cd = new StbTrueType.stbtt_packedchar[f.LastCharIndex + 1];

            StbTrueType.stbrp_rect[] rects;
            fixed(StbTrueType.stbtt_packedchar *charDataPtr = &cd[0])
            {
                var range = new StbTrueType.stbtt_pack_range
                {
                    first_unicode_codepoint_in_range = 0,
                    array_of_unicode_codepoints      = null,
                    num_chars          = (int)f.LastCharIndex + 1,
                    chardata_for_range = charDataPtr,
                    font_size          = -atlas.FontSize
                };

                rects = new StbTrueType.stbrp_rect[f.LastCharIndex + 1];
                fixed(StbTrueType.stbrp_rect *rectPtr = &rects[0])
                {
                    int n = StbTrueType.stbtt_PackFontRangesGatherRects(pc, stbFont, &range, 1, rectPtr);

                    StbTrueType.stbtt_PackFontRangesPackRects(pc, rectPtr, n);
                }
            }

            foreach ((char charIndex, DrawableGlyph atlasGlyph) in atlas.Glyphs)
            {
                FontGlyph glyph = atlasGlyph.FontGlyph;

                var advance = 0;
                var bearing = 0;
                StbTrueType.stbtt_GetCodepointHMetrics(stbFont, charIndex, &advance, &bearing);
                Assert.True(advance == glyph.AdvanceWidth);
                Assert.True(bearing == glyph.LeftSideBearing || glyph.LeftSideBearing == 0); // stb has junk data beyond valid

                var minX = 0;
                var maxX = 0;
                var minY = 0;
                var maxY = 0;
                StbTrueType.stbtt_GetCodepointBitmapBoxSubpixel(stbFont, charIndex, atlas.RenderScale, atlas.RenderScale, 0, 0, &minX, &minY, &maxX, &maxY);

                Rectangle bbox = glyph.GetBBox(atlas.RenderScale);

                Assert.Equal(minX, bbox.X);
                Assert.Equal(minY, bbox.Y);
                Assert.Equal(maxX, bbox.Width);
                Assert.Equal(maxY, bbox.Height);

                Rectangle drawBox = new Rectangle(0, 0, bbox.Width - bbox.X, bbox.Height - bbox.Y);
                drawBox.Size += Vector2.One; // Add padding from stb
                StbTrueType.stbrp_rect rect = rects[charIndex];
                Assert.Equal(rect.w, drawBox.Width);
                Assert.Equal(rect.h, drawBox.Height);
            }
        }
Пример #14
0
        public void Add(byte[] ttf, float fontPixelHeight,
                        List <CharRange> charRanges)
        {
            if (ttf == null || ttf.Length == 0)
            {
                throw new ArgumentNullException(nameof(ttf));
            }

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

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

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

            fixed(byte *ttfPtr = ttf)
            {
                var fontInfo = new StbTrueType.stbtt_fontinfo();

                if (StbTrueType.stbtt_InitFont(fontInfo, ttfPtr, 0) == 0)
                {
                    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 charRanges)
                {
                    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, 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[i + range.Start] = glyphInfo;
                    }
                }
            }
        }