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); } }