Some security checks on font loading
This commit is contained in:
parent
764766bfb2
commit
3b674cd281
164
src/text.c
164
src/text.c
@ -276,15 +276,7 @@ Font LoadFont(const char *fileName)
|
|||||||
Font font = { 0 };
|
Font font = { 0 };
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
if (IsFileExtension(fileName, ".ttf"))
|
if (IsFileExtension(fileName, ".ttf")) font = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, DEFAULT_TTF_NUMCHARS, NULL);
|
||||||
{
|
|
||||||
font.baseSize = DEFAULT_TTF_FONTSIZE;
|
|
||||||
font.charsCount = DEFAULT_TTF_NUMCHARS;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
@ -317,9 +309,13 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
|
|||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.charsCount = (charsCount > 0) ? charsCount : 95;
|
font.charsCount = (charsCount > 0) ? charsCount : 95;
|
||||||
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
|
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);
|
if (font.chars != NULL)
|
||||||
UnloadImage(atlas);
|
{
|
||||||
|
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
|
||||||
|
font.texture = LoadTextureFromImage(atlas);
|
||||||
|
UnloadImage(atlas);
|
||||||
|
}
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@ -335,91 +331,97 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
|||||||
#define SDF_PIXEL_DIST_SCALE 64.0f
|
#define SDF_PIXEL_DIST_SCALE 64.0f
|
||||||
|
|
||||||
#define BITMAP_ALPHA_THRESHOLD 80
|
#define BITMAP_ALPHA_THRESHOLD 80
|
||||||
|
|
||||||
// In case no chars count provided, default to 95
|
CharInfo *chars = NULL;
|
||||||
charsCount = (charsCount > 0) ? charsCount : 95;
|
|
||||||
|
|
||||||
CharInfo *chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo));
|
|
||||||
|
|
||||||
// Load font data (including pixel data) from TTF file
|
// Load font data (including pixel data) from TTF file
|
||||||
// NOTE: Loaded information should be enough to generate font image atlas,
|
// NOTE: Loaded information should be enough to generate font image atlas,
|
||||||
// using any packaging method
|
// using any packaging method
|
||||||
FILE *fontFile = fopen(fileName, "rb"); // Load font file
|
FILE *fontFile = fopen(fileName, "rb"); // Load font file
|
||||||
|
|
||||||
fseek(fontFile, 0, SEEK_END);
|
if (fontFile != NULL)
|
||||||
long size = ftell(fontFile); // Get file size
|
|
||||||
fseek(fontFile, 0, SEEK_SET); // Reset file pointer
|
|
||||||
|
|
||||||
unsigned char *fontBuffer = (unsigned char *)malloc(size);
|
|
||||||
|
|
||||||
fread(fontBuffer, size, 1, fontFile);
|
|
||||||
fclose(fontFile);
|
|
||||||
|
|
||||||
// Init font for data reading
|
|
||||||
stbtt_fontinfo fontInfo;
|
|
||||||
if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!");
|
|
||||||
|
|
||||||
// Calculate font scale factor
|
|
||||||
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
|
|
||||||
|
|
||||||
// Calculate font basic metrics
|
|
||||||
// NOTE: ascent is equivalent to font baseline
|
|
||||||
int ascent, descent, lineGap;
|
|
||||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
|
||||||
|
|
||||||
// Fill fontChars in case not provided externally
|
|
||||||
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
|
|
||||||
int genFontChars = false;
|
|
||||||
if (fontChars == NULL) genFontChars = true;
|
|
||||||
if (genFontChars)
|
|
||||||
{
|
{
|
||||||
fontChars = (int *)malloc(charsCount*sizeof(int));
|
fseek(fontFile, 0, SEEK_END);
|
||||||
for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
|
long size = ftell(fontFile); // Get file size
|
||||||
}
|
fseek(fontFile, 0, SEEK_SET); // Reset file pointer
|
||||||
|
|
||||||
// NOTE: Using simple packaging, one char after another
|
|
||||||
for (int i = 0; i < charsCount; i++)
|
|
||||||
{
|
|
||||||
int chw = 0, chh = 0; // Character width and height (on generation)
|
|
||||||
int ch = fontChars[i]; // Character value to get info for
|
|
||||||
chars[i].value = ch;
|
|
||||||
|
|
||||||
// Render a unicode codepoint to a bitmap
|
unsigned char *fontBuffer = (unsigned char *)malloc(size);
|
||||||
// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
|
|
||||||
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
|
|
||||||
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
|
|
||||||
|
|
||||||
if (type != FONT_SDF) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
fread(fontBuffer, size, 1, fontFile);
|
||||||
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);
|
fclose(fontFile);
|
||||||
|
|
||||||
if (type == FONT_BITMAP)
|
// Init font for data reading
|
||||||
|
stbtt_fontinfo fontInfo;
|
||||||
|
if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!");
|
||||||
|
|
||||||
|
// Calculate font scale factor
|
||||||
|
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
|
||||||
|
|
||||||
|
// Calculate font basic metrics
|
||||||
|
// NOTE: ascent is equivalent to font baseline
|
||||||
|
int ascent, descent, lineGap;
|
||||||
|
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||||
|
|
||||||
|
// In case no chars count provided, default to 95
|
||||||
|
charsCount = (charsCount > 0) ? charsCount : 95;
|
||||||
|
|
||||||
|
// Fill fontChars in case not provided externally
|
||||||
|
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
|
||||||
|
int genFontChars = false;
|
||||||
|
if (fontChars == NULL) genFontChars = true;
|
||||||
|
if (genFontChars)
|
||||||
{
|
{
|
||||||
// Aliased bitmap (black & white) font generation, avoiding anti-aliasing
|
fontChars = (int *)malloc(charsCount*sizeof(int));
|
||||||
// NOTE: For optimum results, bitmap font should be generated at base pixel size
|
for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
|
||||||
for (int p = 0; p < chw*chh; p++)
|
}
|
||||||
|
|
||||||
|
chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo));
|
||||||
|
|
||||||
|
// NOTE: Using simple packaging, one char after another
|
||||||
|
for (int i = 0; i < charsCount; i++)
|
||||||
|
{
|
||||||
|
int chw = 0, chh = 0; // Character width and height (on generation)
|
||||||
|
int ch = fontChars[i]; // Character value to get info for
|
||||||
|
chars[i].value = ch;
|
||||||
|
|
||||||
|
// Render a unicode codepoint to a bitmap
|
||||||
|
// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
|
||||||
|
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
|
||||||
|
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
if (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
|
// Aliased bitmap (black & white) font generation, avoiding anti-aliasing
|
||||||
else chars[i].data[p] = 255;
|
// 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);
|
||||||
|
|
||||||
|
// Get bounding box for character (may be 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);
|
||||||
|
|
||||||
|
TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
|
||||||
|
TraceLog(LOG_DEBUG, "Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
|
||||||
|
|
||||||
|
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||||
|
chars[i].advanceX *= scaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars[i].rec.width = (float)chw;
|
free(fontBuffer);
|
||||||
chars[i].rec.height = (float)chh;
|
if (genFontChars) free(fontChars);
|
||||||
chars[i].offsetY += (int)((float)ascent*scaleFactor);
|
|
||||||
|
|
||||||
// Get bounding box for character (may be 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);
|
|
||||||
|
|
||||||
TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
|
|
||||||
TraceLog(LOG_DEBUG, "Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
|
|
||||||
|
|
||||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
|
||||||
chars[i].advanceX *= scaleFactor;
|
|
||||||
}
|
}
|
||||||
|
else TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName);
|
||||||
free(fontBuffer);
|
|
||||||
if (genFontChars) free(fontChars);
|
|
||||||
|
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user