diff options
| author | Ray <[email protected]> | 2023-12-04 17:32:55 +0100 |
|---|---|---|
| committer | Ray <[email protected]> | 2023-12-04 17:32:55 +0100 |
| commit | 731b210f51cb273161bb7a8ba9cced11e0c4b9d2 (patch) | |
| tree | ba670711001fc59b831b2a4b6917482ef40a99bf /src | |
| parent | a016b4ded23f653da45679f36fcb5ffca6a5f6a0 (diff) | |
| download | raylib-731b210f51cb273161bb7a8ba9cced11e0c4b9d2.tar.gz raylib-731b210f51cb273161bb7a8ba9cced11e0c4b9d2.zip | |
REVIEWED: WARNING: `LoadFontData()` avoid fallback glyphs
This is a redesign on font loading, missing glyphs are skipped instead of falling back to font `.notdef` special character (usually "tofu" character).
It is changed because not all fonts support a fallback glyph.
One improvement could be allowing users to define a custom fallback character, for example `?` glyph.
Diffstat (limited to 'src')
| -rw-r--r-- | src/rtext.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/src/rtext.c b/src/rtext.c index 802b02b9..1ab45277 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -625,57 +625,67 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide - if (type != FONT_SDF) chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); - else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); - else chars[i].image.data = NULL; + // Check if a glyph is available in the font + // WARNING: if (index == 0), glyph not found, it could fallback to default .notdef glyph (if defined in font) + int index = stbtt_FindGlyphIndex(&fontInfo, ch); - if (chars[i].image.data != NULL) // Glyph data has been found in the font + if (index > 0) { - stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); - chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); + switch (type) + { + case FONT_DEFAULT: + case FONT_BITMAP: chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break; + case FONT_SDF: if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break; + default: break; + } - // Load characters images - chars[i].image.width = chw; - chars[i].image.height = chh; - chars[i].image.mipmaps = 1; - chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; + if (chars[i].image.data != NULL) // Glyph data has been found in the font + { + stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); + chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); - chars[i].offsetY += (int)((float)ascent*scaleFactor); - } + // Load characters images + chars[i].image.width = chw; + chars[i].image.height = chh; + chars[i].image.mipmaps = 1; + chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; - // NOTE: We create an empty image for space character, it could be further required for atlas packing - if (ch == 32) - { - Image imSpace = { - .data = RL_CALLOC(chars[i].advanceX*fontSize, 2), - .width = chars[i].advanceX, - .height = fontSize, - .mipmaps = 1, - .format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE - }; - - chars[i].image = imSpace; - } + chars[i].offsetY += (int)((float)ascent*scaleFactor); + } - if (type == FONT_BITMAP) - { - // Aliased bitmap (black & white) font generation, avoiding anti-aliasing - // NOTE: For optimum results, bitmap font should be generated at base pixel size - for (int p = 0; p < chw*chh; p++) + // NOTE: We create an empty image for space character, + // it could be further required for atlas packing + if (ch == 32) { - if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0; - else ((unsigned char *)chars[i].image.data)[p] = 255; + stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); + chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor); + + Image imSpace = { + .data = RL_CALLOC(chars[i].advanceX*fontSize, 2), + .width = chars[i].advanceX, + .height = fontSize, + .mipmaps = 1, + .format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE + }; + + chars[i].image = imSpace; } - } - - // Get bounding box for character (maybe offset to account for chars that dip above or below the line) - /* - int chX1, chY1, chX2, chY2; - stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2); - TRACELOGD("FONT: Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1); - TRACELOGD("FONT: Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1); - */ + if (type == FONT_BITMAP) + { + // Aliased bitmap (black & white) font generation, avoiding anti-aliasing + // NOTE: For optimum results, bitmap font should be generated at base pixel size + for (int p = 0; p < chw*chh; p++) + { + if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0; + else ((unsigned char *)chars[i].image.data)[p] = 255; + } + } + } + else + { + // TODO: Use some fallback glyph for codepoints not found in the font + } } } else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data"); |
