implement dynamic font atlas resizing in GenImageFontAtlas()

This commit is contained in:
iikare 2022-06-26 21:11:46 -07:00
parent e9fcc8a391
commit 6280b0a6ce
No known key found for this signature in database
GPG Key ID: 4906067E1F6AAB8C

View File

@ -690,6 +690,10 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
float guessSize = sqrtf(requiredArea)*1.4f;
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
int currentRepeatCount = 0;
const int maxRepeatCount = 2;
bool undersizedAtlasFlag = false;
atlas.width = imageSize; // Atlas bitmap width
atlas.height = imageSize; // Atlas bitmap height
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
@ -701,6 +705,25 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
if (packMethod == 0) // Use basic packing algorithm
{
// When the guesstimate of the atlas size is determined to be undersized,
// repeat the atlas generation process with an atlas data texture of a size
// that is double the previous size, up to a limit of `maxRepeatCount` times
while (currentRepeatCount < maxRepeatCount)
{
if (currentRepeatCount > 0)
{
// Recreate the atlas for the new, doubled size when all glyphs don't fit on the previous-sized atlas
// (but not on the first pass)
RL_FREE(atlas.data);
atlas.width = atlas.width*2; // Atlas bitmap width
atlas.height = atlas.height*2; // Atlas bitmap height
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
TRACELOG(LOG_INFO, "FONT: Font atlas undersized, expanding atlas to %ix%i", atlas.width, atlas.height);
undersizedAtlasFlag = false;
}
int offsetX = padding;
int offsetY = padding;
@ -736,9 +759,20 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
if (offsetY > (atlas.height - fontSize - padding))
{
// The current atlas is too small to hold all glyphs, so move to the next atlas size
currentRepeatCount++;
undersizedAtlasFlag = true;
// If the process repeats more times than the defined limit, abort and log the unpackaged characters
for(int j = i + 1; j < glyphCount; j++)
{
if (currentRepeatCount > maxRepeatCount)
{
TRACELOG(LOG_WARNING, "FONT: Failed to package character (%i)", j);
}
// make sure remaining recs contain valid data
recs[j].x = 0;
recs[j].y = 0;
@ -749,6 +783,12 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
}
}
}
// After any pass, if all the glyphs fit, immediately end the packing process
if (!undersizedAtlasFlag)
{
break;
}
}
}
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
{