Browse Source

Support aliased font texture generation

Useful for bitmaps pixelated fonts where anti-aliasing is not desired!
Change also enables additional font generation mechanisms in a future (cleartype, hinting...).
Ray 7 years ago
parent
commit
dfb8837c46
3 changed files with 28 additions and 9 deletions
  1. 2 3
      examples/text/text_font_sdf.c
  2. 8 1
      src/raylib.h
  3. 18 5
      src/text.c

+ 2 - 3
examples/text/text_font_sdf.c

@@ -29,19 +29,18 @@ int main()
     fontDefault.baseSize = 16;
     fontDefault.charsCount = 95;
     // Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array)
-    fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, false);
+    fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, FONT_DEFAULT);
     // Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default)
     Image atlas = GenImageFontAtlas(fontDefault.chars, 95, 16, 4, 0);
     fontDefault.texture = LoadTextureFromImage(atlas);
     UnloadImage(atlas);
     
     // SDF font generation from TTF font
-    // NOTE: SDF chars data is generated with LoadFontData(), it's just a bool option
     Font fontSDF = { 0 };
     fontSDF.baseSize = 16;
     fontSDF.charsCount = 95;
     // Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95)
-    fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, true);
+    fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, FONT_SDF);
     // Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm)
     atlas = GenImageFontAtlas(fontSDF.chars, 95, 16, 0, 1);
     fontSDF.texture = LoadTextureFromImage(atlas);

+ 8 - 1
src/raylib.h

@@ -721,6 +721,13 @@ typedef enum {
     WRAP_MIRROR
 } TextureWrapMode;
 
+// Font type, defines generation method
+typedef enum {
+    FONT_DEFAULT = 0,   // Default font generation, anti-aliased
+    FONT_BITMAP,        // Bitmap font generation, no anti-aliasing
+    FONT_SDF            // SDF font generation, requires external shader
+} FontType;
+
 // Color blending modes (pre-defined)
 typedef enum {
     BLEND_ALPHA = 0,
@@ -1056,7 +1063,7 @@ RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle
 RLAPI Font GetFontDefault(void);                                                            // Get the default Font
 RLAPI Font LoadFont(const char *fileName);                                                  // Load font from file into GPU memory (VRAM)
 RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars);  // Load font from file with extended parameters
-RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use
+RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
 RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod);  // Generate image font atlas using chars info
 RLAPI void UnloadFont(Font font);                                                           // Unload Font from GPU memory (VRAM)
 

+ 18 - 5
src/text.c

@@ -283,7 +283,7 @@ Font LoadFont(const char *fileName)
     {
         font.baseSize = DEFAULT_TTF_FONTSIZE;
         font.charsCount = DEFAULT_TTF_NUMCHARS;
-        font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false);
+        font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, FONT_DEFAULT);
         Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0);
         font.texture = LoadTextureFromImage(atlas);
         UnloadImage(atlas);
@@ -319,8 +319,8 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
     
     font.baseSize = fontSize;
     font.charsCount = (charsCount > 0) ? charsCount : 95;
-    font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, false);
-    Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0, 0);
+    font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
+    Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
     font.texture = LoadTextureFromImage(atlas);
     UnloadImage(atlas);
     
@@ -329,7 +329,7 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
 
 // Load font data for further use
 // NOTE: Requires TTF font and can generate SDF data
-CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf)
+CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, int type)
 {
     // NOTE: Using some SDF generation default values,
     // trades off precision with ability to handle *smaller* sizes
@@ -337,6 +337,8 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
     #define SDF_ON_EDGE_VALUE         128
     #define SDF_PIXEL_DIST_SCALE     64.0f
     
+    #define BITMAP_ALPHA_THRESHOLD     80
+    
     // In case no chars count provided, default to 95
     charsCount = (charsCount > 0) ? charsCount : 95;
     
@@ -390,9 +392,20 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
         //      stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be
         //      stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide
         
-        if (!sdf) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+        if (type != FONT_SDF) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
         else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
         
+        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 (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
+                else chars[i].data[p] = 255;
+            }
+        }
+        
         chars[i].rec.width = (float)chw;
         chars[i].rec.height = (float)chh;
         chars[i].offsetY += (int)((float)ascent*scaleFactor);