2
0
Эх сурвалжийг харах

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.
Ray 1 жил өмнө
parent
commit
731b210f51
1 өөрчлөгдсөн 52 нэмэгдсэн , 42 устгасан
  1. 52 42
      src/rtext.c

+ 52 - 42
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_GetCodepointBitmapBox()        -- how big the bitmap must be
                 //      stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide
                 //      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");
         else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");