stb_truetype: limit to 1 missing glyph in texture

When calling stbtt_PackFontRanges, multiple missing glyphs in the range
of codepoints will create multiple copies of the font's missing glyph to
be added to the pixel buffer.  Instead, the first codepoint that maps to the missing glyph will add it to the pixel buffer, and all subsequent glyphs will simply copy the stbtt_packedchar data to reference the same region of the buffer.

This does NOT prevent duplication in multiple calls to stbtt_PackFontRange(s) - that would require modifying the packing context, which could be nice but is a bit more intrusive.
This commit is contained in:
rgriege 2019-03-07 19:32:19 -06:00
parent 2c2908f505
commit 8ac257b00f

View File

@ -3968,6 +3968,7 @@ static float stbtt__oversample_shift(int oversample)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{
int i,j,k;
int missing_glyph_added = 0;
k=0;
for (i=0; i < num_ranges; ++i) {
@ -3979,7 +3980,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
int x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint);
if (glyph == 0 && spc->skip_missing) {
if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
rects[k].w = rects[k].h = 0;
} else {
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
@ -3989,6 +3990,8 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
&x0,&y0,&x1,&y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
if (glyph == 0)
missing_glyph_added = 1;
}
++k;
}
@ -4023,7 +4026,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
// rects array must be big enough to accommodate all characters in the given ranges
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{
int i,j,k, return_value = 1;
int i,j,k, missing_glyph = -1, return_value = 1;
// save current values
int old_h_over = spc->h_oversample;
@ -4088,6 +4091,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
bc->yoff = (float) y0 * recip_v + sub_y;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
if (glyph == 0)
missing_glyph = j;
} else if (spc->skip_missing) {
return_value = 0;
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
} else {
return_value = 0; // if any fail, report failure
}