mirror of https://github.com/raysan5/raylib
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 <hope81dklee@outlook.com> Co-authored-by: Ray <raysan5@gmail.com>
This commit is contained in:
parent
e001f7e75e
commit
9de79861ea
94
src/rtext.c
94
src/rtext.c
|
@ -2052,6 +2052,7 @@ static int GetLine(const char *origin, char *buffer, int maxLength)
|
||||||
static Font LoadBMFont(const char *fileName)
|
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 };
|
Font font = { 0 };
|
||||||
|
|
||||||
|
@ -2063,7 +2064,8 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
int imWidth = 0;
|
int imWidth = 0;
|
||||||
int imHeight = 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 base = 0; // Useless data
|
||||||
int readBytes = 0; // Data bytes read
|
int readBytes = 0; // Data bytes read
|
||||||
|
@ -2082,17 +2084,26 @@ static Font LoadBMFont(const char *fileName)
|
||||||
// Read line data
|
// Read line data
|
||||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "lineHeight");
|
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);
|
fileTextPtr += (readBytes + 1);
|
||||||
|
|
||||||
if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < pageCount; i++)
|
||||||
|
{
|
||||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "file");
|
searchPoint = strstr(buffer, "file");
|
||||||
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName);
|
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName[i]);
|
||||||
fileTextPtr += (readBytes + 1);
|
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);
|
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||||
searchPoint = strstr(buffer, "count");
|
searchPoint = strstr(buffer, "count");
|
||||||
|
@ -2101,50 +2112,56 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
|
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
|
||||||
|
|
||||||
// Compose correct path using route of .fnt file (fileName) and imFileName
|
// Load all required images for further compose
|
||||||
char *imPath = NULL;
|
Image *imFonts = (Image *)RL_CALLOC(pageCount, sizeof(Image)); // Font atlases, multiple images
|
||||||
char *lastSlash = NULL;
|
|
||||||
|
|
||||||
lastSlash = strrchr(fileName, '/');
|
for (int i = 0; i < pageCount; i++)
|
||||||
if (lastSlash == NULL) lastSlash = strrchr(fileName, '\\');
|
|
||||||
|
|
||||||
if (lastSlash != NULL)
|
|
||||||
{
|
{
|
||||||
// NOTE: We need some extra space to avoid memory corruption on next allocations!
|
imFonts[i] = LoadImage(TextFormat("%s/%s", GetDirectoryPath(fileName), imFileName[i]));
|
||||||
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;
|
|
||||||
|
|
||||||
TRACELOGD(" > Image loading path: %s", imPath);
|
if (imFonts[i].format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
|
||||||
|
|
||||||
Image imFont = LoadImage(imPath);
|
|
||||||
|
|
||||||
if (imFont.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
|
|
||||||
{
|
{
|
||||||
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
|
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
|
||||||
Image imFontAlpha = {
|
Image imFontAlpha = {
|
||||||
.data = RL_CALLOC(imFont.width*imFont.height, 2),
|
.data = RL_CALLOC(imFonts[i].width*imFonts[i].height, 2),
|
||||||
.width = imFont.width,
|
.width = imFonts[i].width,
|
||||||
.height = imFont.height,
|
.height = imFonts[i].height,
|
||||||
.mipmaps = 1,
|
.mipmaps = 1,
|
||||||
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
|
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int p = 0, i = 0; p < (imFont.width*imFont.height*2); p += 2, i++)
|
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] = 0xff;
|
||||||
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFont.data)[i];
|
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFonts[i].data)[pi];
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFonts[i]);
|
||||||
imFont = imFontAlpha;
|
imFonts[i] = imFontAlpha;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
font.texture = LoadTextureFromImage(imFont);
|
Image fullFont = imFonts[0];
|
||||||
|
for (int i = 1; i < pageCount; i++) UnloadImage(imFonts[i]);
|
||||||
|
|
||||||
if (lastSlash != NULL) RL_FREE(imPath);
|
// If multiple atlas, then merge atlas
|
||||||
|
// NOTE: WARNING: This process could be really slow!
|
||||||
|
if (pageCount > 1)
|
||||||
|
{
|
||||||
|
// Resize font atlas to draw additional images
|
||||||
|
ImageResizeCanvas(&fullFont, imWidth, imHeight*pageCount, 0, 0, BLACK);
|
||||||
|
|
||||||
|
for (int i = 1; i < pageCount; 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RL_FREE(imFonts);
|
||||||
|
|
||||||
|
font.texture = LoadTextureFromImage(fullFont);
|
||||||
|
|
||||||
// Fill font characters info data
|
// Fill font characters info data
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
|
@ -2153,19 +2170,19 @@ static Font LoadBMFont(const char *fileName)
|
||||||
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
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++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
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",
|
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);
|
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX, &pageID);
|
||||||
fileTextPtr += (readBytes + 1);
|
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
|
// 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
|
// Save data properly in sprite font
|
||||||
font.glyphs[i].value = charId;
|
font.glyphs[i].value = charId;
|
||||||
|
@ -2173,13 +2190,13 @@ static Font LoadBMFont(const char *fileName)
|
||||||
font.glyphs[i].offsetY = charOffsetY;
|
font.glyphs[i].offsetY = charOffsetY;
|
||||||
font.glyphs[i].advanceX = charAdvanceX;
|
font.glyphs[i].advanceX = charAdvanceX;
|
||||||
|
|
||||||
// Fill character image data from imFont data
|
// Fill character image data from full font data
|
||||||
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
|
font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
|
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(fullFont);
|
||||||
UnloadFileText(fileText);
|
UnloadFileText(fileText);
|
||||||
|
|
||||||
if (font.texture.id == 0)
|
if (font.texture.id == 0)
|
||||||
|
@ -2192,6 +2209,7 @@ static Font LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SUPPORT_MODULE_RTEXT
|
#endif // SUPPORT_MODULE_RTEXT
|
||||||
|
|
Loading…
Reference in New Issue