From f36b7116e265444c371abd70e5807ce29708f4eb Mon Sep 17 00:00:00 2001 From: Fabian Giesen Date: Wed, 17 Sep 2014 22:54:16 -0700 Subject: [PATCH] Fix a few bugs with subpixel shifts, shift_y in particular. 1. In the presence of nonzero shift_x / shift_y, stbtt_GetGlyphBitmapBoxSubpixel would return a nonzero-sized bounding box for empty glyphs (e.g. spaces). Since such glyphs don't have any outlines, the rasterizer wouldn't do anything, resulting in a 1x1-pixel image with uninitialized memory. 2. GetGlyphBitmapBoxSubpixel added shift_y then flipped the y axis, whereas the rasterizer flipped the y axis then added shift_y. Consistently flip-then-add in both places. This also makes the pattern of floors/ceils in GetGlyphBitmapBoxSubpixel simpler. 3. The rasterizer added shift_y after multiplying by the vertical oversampling factor, instead of before. Vertical shifts now work much better, in my tests anyway. --- stb_truetype.h | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index f2efda8..ada4804 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1385,14 +1385,21 @@ void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { int x0,y0,x1,y1; - if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) - x0=y0=x1=y1=0; // e.g. space character - // now move to integral bboxes (treating pixels as little squares, what pixels get touched)? - if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x); - if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y); - if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x); - if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y); + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } } + void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); @@ -1639,9 +1646,9 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou a=j,b=k; } e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; ++n; } }