summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDongkun Lee <[email protected]>2023-12-16 02:32:01 +0900
committerGitHub <[email protected]>2023-12-15 18:32:01 +0100
commit9de79861ea289822ce965b63e565b04a46c0ec11 (patch)
tree51021acb648d70fd75bea34a7c22b32ad6c5e383
parente001f7e75e4535d3e3576b9d4d16a5ffb8b83dbe (diff)
downloadraylib-9de79861ea289822ce965b63e565b04a46c0ec11.tar.gz
raylib-9de79861ea289822ce965b63e565b04a46c0ec11.zip
BM Font Extender (#3536)
* loadbmfont * bmfontextender * bm font * Modify LoadBM Font * Delete loadbmfontex.diff * REVIEWED: `LoadBMFont()` PR * Update rtext.c * Update rtext.c --------- Co-authored-by: Dongkun Lee <[email protected]> Co-authored-by: Ray <[email protected]>
-rw-r--r--src/rtext.c116
1 files changed, 67 insertions, 49 deletions
diff --git a/src/rtext.c b/src/rtext.c
index a919fa4a..2a6aa127 100644
--- a/src/rtext.c
+++ b/src/rtext.c
@@ -2051,7 +2051,8 @@ static int GetLine(const char *origin, char *buffer, int maxLength)
// REQUIRES: strstr(), sscanf(), strrchr(), memcpy()
static Font LoadBMFont(const char *fileName)
{
- #define MAX_BUFFER_SIZE 256
+ #define MAX_BUFFER_SIZE 256
+ #define MAX_FONT_IMAGE_PAGES 8
Font font = { 0 };
@@ -2063,7 +2064,8 @@ static Font LoadBMFont(const char *fileName)
int imWidth = 0;
int imHeight = 0;
- char imFileName[129] = { 0 };
+ int pageCount = 1;
+ char imFileName[MAX_FONT_IMAGE_PAGES][129] = { 0 };
int base = 0; // Useless data
int readBytes = 0; // Data bytes read
@@ -2082,17 +2084,26 @@ static Font LoadBMFont(const char *fileName)
// Read line data
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "lineHeight");
- readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &imWidth, &imHeight);
+ readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i pages=%i", &fontSize, &base, &imWidth, &imHeight, &pageCount);
fileTextPtr += (readBytes + 1);
if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed
+
+ if (pageCount > MAX_FONT_IMAGE_PAGES)
+ {
+ TRACELOG(LOG_WARNING, "FONT: [%s] Font defines more pages than supported: %i/%i", fileName, pageCount, MAX_FONT_IMAGE_PAGES);
+ pageCount = MAX_FONT_IMAGE_PAGES;
+ }
- readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
- searchPoint = strstr(buffer, "file");
- readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName);
- fileTextPtr += (readBytes + 1);
+ for (int i = 0; i < pageCount; i++)
+ {
+ readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
+ searchPoint = strstr(buffer, "file");
+ readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName[i]);
+ fileTextPtr += (readBytes + 1);
- if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
+ if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
+ }
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "count");
@@ -2101,50 +2112,56 @@ static Font LoadBMFont(const char *fileName)
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
- // Compose correct path using route of .fnt file (fileName) and imFileName
- char *imPath = NULL;
- char *lastSlash = NULL;
+ // Load all required images for further compose
+ Image *imFonts = (Image *)RL_CALLOC(pageCount, sizeof(Image)); // Font atlases, multiple images
- lastSlash = strrchr(fileName, '/');
- if (lastSlash == NULL) lastSlash = strrchr(fileName, '\\');
-
- if (lastSlash != NULL)
+ for (int i = 0; i < pageCount; i++)
{
- // NOTE: We need some extra space to avoid memory corruption on next allocations!
- imPath = (char *)RL_CALLOC(TextLength(fileName) - TextLength(lastSlash) + TextLength(imFileName) + 4, 1);
- memcpy(imPath, fileName, TextLength(fileName) - TextLength(lastSlash) + 1);
- memcpy(imPath + TextLength(fileName) - TextLength(lastSlash) + 1, imFileName, TextLength(imFileName));
- }
- else imPath = imFileName;
+ imFonts[i] = LoadImage(TextFormat("%s/%s", GetDirectoryPath(fileName), imFileName[i]));
- TRACELOGD(" > Image loading path: %s", imPath);
+ if (imFonts[i].format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
+ {
+ // Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
+ Image imFontAlpha = {
+ .data = RL_CALLOC(imFonts[i].width*imFonts[i].height, 2),
+ .width = imFonts[i].width,
+ .height = imFonts[i].height,
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
+ };
+
+ for (int p = 0, pi = 0; p < (imFonts[i].width*imFonts[i].height*2); p += 2, pi++)
+ {
+ ((unsigned char *)(imFontAlpha.data))[p] = 0xff;
+ ((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFonts[i].data)[pi];
+ }
+
+ UnloadImage(imFonts[i]);
+ imFonts[i] = imFontAlpha;
+ }
+ }
- Image imFont = LoadImage(imPath);
+ Image fullFont = imFonts[0];
+ for (int i = 1; i < pageCount; i++) UnloadImage(imFonts[i]);
- if (imFont.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
+ // If multiple atlas, then merge atlas
+ // NOTE: WARNING: This process could be really slow!
+ if (pageCount > 1)
{
- // Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
- Image imFontAlpha = {
- .data = RL_CALLOC(imFont.width*imFont.height, 2),
- .width = imFont.width,
- .height = imFont.height,
- .mipmaps = 1,
- .format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
- };
+ // Resize font atlas to draw additional images
+ ImageResizeCanvas(&fullFont, imWidth, imHeight*pageCount, 0, 0, BLACK);
- for (int p = 0, i = 0; p < (imFont.width*imFont.height*2); p += 2, i++)
+ for (int i = 1; i < pageCount; i++)
{
- ((unsigned char *)(imFontAlpha.data))[p] = 0xff;
- ((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFont.data)[i];
+ Rectangle srcRec = { 0.0f, 0.0f, (float)imWidth, (float)imHeight };
+ Rectangle destRec = { 0.0f, (float)imHeight*(float)i, (float)imWidth, (float)imHeight };
+ ImageDraw(&fullFont, imFonts[i], srcRec, destRec, WHITE);
}
-
- UnloadImage(imFont);
- imFont = imFontAlpha;
}
+
+ RL_FREE(imFonts);
- font.texture = LoadTextureFromImage(imFont);
-
- if (lastSlash != NULL) RL_FREE(imPath);
+ font.texture = LoadTextureFromImage(fullFont);
// Fill font characters info data
font.baseSize = fontSize;
@@ -2153,19 +2170,19 @@ static Font LoadBMFont(const char *fileName)
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
- int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
+ int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX, pageID;
for (int i = 0; i < glyphCount; i++)
{
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
- readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
- &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
+ readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i page=%i",
+ &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX, &pageID);
fileTextPtr += (readBytes + 1);
- if (readVars == 8) // Make sure all char data has been properly read
+ if (readVars == 9) // Make sure all char data has been properly read
{
// Get character rectangle in the font atlas texture
- font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
+ font.recs[i] = (Rectangle){ (float)charX, (float)charY + (float)imHeight*pageID, (float)charWidth, (float)charHeight };
// Save data properly in sprite font
font.glyphs[i].value = charId;
@@ -2173,13 +2190,13 @@ static Font LoadBMFont(const char *fileName)
font.glyphs[i].offsetY = charOffsetY;
font.glyphs[i].advanceX = charAdvanceX;
- // Fill character image data from imFont data
- font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
+ // Fill character image data from full font data
+ font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]);
}
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
}
- UnloadImage(imFont);
+ UnloadImage(fullFont);
UnloadFileText(fileText);
if (font.texture.id == 0)
@@ -2192,6 +2209,7 @@ static Font LoadBMFont(const char *fileName)
return font;
}
+
#endif
#endif // SUPPORT_MODULE_RTEXT