@@ -2051,7 +2051,8 @@ static int GetLine(const char *origin, char *buffer, int maxLength)
20512051// REQUIRES: strstr(), sscanf(), strrchr(), memcpy()
20522052static Font LoadBMFont (const char * fileName )
20532053{
2054- #define MAX_BUFFER_SIZE 256
2054+ #define MAX_BUFFER_SIZE 256
2055+ #define MAX_FONT_IMAGE_PAGES 8
20552056
20562057 Font font = { 0 };
20572058
@@ -2063,7 +2064,8 @@ static Font LoadBMFont(const char *fileName)
20632064
20642065 int imWidth = 0 ;
20652066 int imHeight = 0 ;
2066- char imFileName [129 ] = { 0 };
2067+ int pageCount = 1 ;
2068+ char imFileName [MAX_FONT_IMAGE_PAGES ][129 ] = { 0 };
20672069
20682070 int base = 0 ; // Useless data
20692071 int readBytes = 0 ; // Data bytes read
@@ -2082,17 +2084,26 @@ static Font LoadBMFont(const char *fileName)
20822084 // Read line data
20832085 readBytes = GetLine (fileTextPtr , buffer , MAX_BUFFER_SIZE );
20842086 searchPoint = strstr (buffer , "lineHeight" );
2085- readVars = sscanf (searchPoint , "lineHeight=%i base=%i scaleW=%i scaleH=%i" , & fontSize , & base , & imWidth , & imHeight );
2087+ readVars = sscanf (searchPoint , "lineHeight=%i base=%i scaleW=%i scaleH=%i pages=%i " , & fontSize , & base , & imWidth , & imHeight , & pageCount );
20862088 fileTextPtr += (readBytes + 1 );
20872089
20882090 if (readVars < 4 ) { UnloadFileText (fileText ); return font ; } // Some data not available, file malformed
2091+
2092+ if (pageCount > MAX_FONT_IMAGE_PAGES )
2093+ {
2094+ TRACELOG (LOG_WARNING , "FONT: [%s] Font defines more pages than supported: %i/%i" , fileName , pageCount , MAX_FONT_IMAGE_PAGES );
2095+ pageCount = MAX_FONT_IMAGE_PAGES ;
2096+ }
20892097
2090- readBytes = GetLine (fileTextPtr , buffer , MAX_BUFFER_SIZE );
2091- searchPoint = strstr (buffer , "file" );
2092- readVars = sscanf (searchPoint , "file=\"%128[^\"]\"" , imFileName );
2093- fileTextPtr += (readBytes + 1 );
2098+ for (int i = 0 ; i < pageCount ; i ++ )
2099+ {
2100+ readBytes = GetLine (fileTextPtr , buffer , MAX_BUFFER_SIZE );
2101+ searchPoint = strstr (buffer , "file" );
2102+ readVars = sscanf (searchPoint , "file=\"%128[^\"]\"" , imFileName [i ]);
2103+ fileTextPtr += (readBytes + 1 );
20942104
2095- if (readVars < 1 ) { UnloadFileText (fileText ); return font ; } // No fileName read
2105+ if (readVars < 1 ) { UnloadFileText (fileText ); return font ; } // No fileName read
2106+ }
20962107
20972108 readBytes = GetLine (fileTextPtr , buffer , MAX_BUFFER_SIZE );
20982109 searchPoint = strstr (buffer , "count" );
@@ -2101,50 +2112,56 @@ static Font LoadBMFont(const char *fileName)
21012112
21022113 if (readVars < 1 ) { UnloadFileText (fileText ); return font ; } // No glyphCount read
21032114
2104- // Compose correct path using route of .fnt file (fileName) and imFileName
2105- char * imPath = NULL ;
2106- char * lastSlash = NULL ;
2115+ // Load all required images for further compose
2116+ Image * imFonts = (Image * )RL_CALLOC (pageCount , sizeof (Image )); // Font atlases, multiple images
21072117
2108- lastSlash = strrchr (fileName , '/' );
2109- if (lastSlash == NULL ) lastSlash = strrchr (fileName , '\\' );
2110-
2111- if (lastSlash != NULL )
2118+ for (int i = 0 ; i < pageCount ; i ++ )
21122119 {
2113- // NOTE: We need some extra space to avoid memory corruption on next allocations!
2114- imPath = (char * )RL_CALLOC (TextLength (fileName ) - TextLength (lastSlash ) + TextLength (imFileName ) + 4 , 1 );
2115- memcpy (imPath , fileName , TextLength (fileName ) - TextLength (lastSlash ) + 1 );
2116- memcpy (imPath + TextLength (fileName ) - TextLength (lastSlash ) + 1 , imFileName , TextLength (imFileName ));
2117- }
2118- else imPath = imFileName ;
2120+ imFonts [i ] = LoadImage (TextFormat ("%s/%s" , GetDirectoryPath (fileName ), imFileName [i ]));
21192121
2120- TRACELOGD (" > Image loading path: %s" , imPath );
2122+ if (imFonts [i ].format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE )
2123+ {
2124+ // Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
2125+ Image imFontAlpha = {
2126+ .data = RL_CALLOC (imFonts [i ].width * imFonts [i ].height , 2 ),
2127+ .width = imFonts [i ].width ,
2128+ .height = imFonts [i ].height ,
2129+ .mipmaps = 1 ,
2130+ .format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
2131+ };
2132+
2133+ for (int p = 0 , pi = 0 ; p < (imFonts [i ].width * imFonts [i ].height * 2 ); p += 2 , pi ++ )
2134+ {
2135+ ((unsigned char * )(imFontAlpha .data ))[p ] = 0xff ;
2136+ ((unsigned char * )(imFontAlpha .data ))[p + 1 ] = ((unsigned char * )imFonts [i ].data )[pi ];
2137+ }
2138+
2139+ UnloadImage (imFonts [i ]);
2140+ imFonts [i ] = imFontAlpha ;
2141+ }
2142+ }
21212143
2122- Image imFont = LoadImage (imPath );
2144+ Image fullFont = imFonts [0 ];
2145+ for (int i = 1 ; i < pageCount ; i ++ ) UnloadImage (imFonts [i ]);
21232146
2124- if (imFont .format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE )
2147+ // If multiple atlas, then merge atlas
2148+ // NOTE: WARNING: This process could be really slow!
2149+ if (pageCount > 1 )
21252150 {
2126- // Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
2127- Image imFontAlpha = {
2128- .data = RL_CALLOC (imFont .width * imFont .height , 2 ),
2129- .width = imFont .width ,
2130- .height = imFont .height ,
2131- .mipmaps = 1 ,
2132- .format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
2133- };
2151+ // Resize font atlas to draw additional images
2152+ ImageResizeCanvas (& fullFont , imWidth , imHeight * pageCount , 0 , 0 , BLACK );
21342153
2135- for (int p = 0 , i = 0 ; p < ( imFont . width * imFont . height * 2 ); p += 2 , i ++ )
2154+ for (int i = 1 ; i < pageCount ; i ++ )
21362155 {
2137- ((unsigned char * )(imFontAlpha .data ))[p ] = 0xff ;
2138- ((unsigned char * )(imFontAlpha .data ))[p + 1 ] = ((unsigned char * )imFont .data )[i ];
2156+ Rectangle srcRec = { 0.0f , 0.0f , (float )imWidth , (float )imHeight };
2157+ Rectangle destRec = { 0.0f , (float )imHeight * (float )i , (float )imWidth , (float )imHeight };
2158+ ImageDraw (& fullFont , imFonts [i ], srcRec , destRec , WHITE );
21392159 }
2140-
2141- UnloadImage (imFont );
2142- imFont = imFontAlpha ;
21432160 }
2161+
2162+ RL_FREE (imFonts );
21442163
2145- font .texture = LoadTextureFromImage (imFont );
2146-
2147- if (lastSlash != NULL ) RL_FREE (imPath );
2164+ font .texture = LoadTextureFromImage (fullFont );
21482165
21492166 // Fill font characters info data
21502167 font .baseSize = fontSize ;
@@ -2153,33 +2170,33 @@ static Font LoadBMFont(const char *fileName)
21532170 font .glyphs = (GlyphInfo * )RL_MALLOC (glyphCount * sizeof (GlyphInfo ));
21542171 font .recs = (Rectangle * )RL_MALLOC (glyphCount * sizeof (Rectangle ));
21552172
2156- int charId , charX , charY , charWidth , charHeight , charOffsetX , charOffsetY , charAdvanceX ;
2173+ int charId , charX , charY , charWidth , charHeight , charOffsetX , charOffsetY , charAdvanceX , pageID ;
21572174
21582175 for (int i = 0 ; i < glyphCount ; i ++ )
21592176 {
21602177 readBytes = GetLine (fileTextPtr , buffer , MAX_BUFFER_SIZE );
2161- readVars = sscanf (buffer , "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i" ,
2162- & charId , & charX , & charY , & charWidth , & charHeight , & charOffsetX , & charOffsetY , & charAdvanceX );
2178+ readVars = sscanf (buffer , "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i page=%i " ,
2179+ & charId , & charX , & charY , & charWidth , & charHeight , & charOffsetX , & charOffsetY , & charAdvanceX , & pageID );
21632180 fileTextPtr += (readBytes + 1 );
21642181
2165- if (readVars == 8 ) // Make sure all char data has been properly read
2182+ if (readVars == 9 ) // Make sure all char data has been properly read
21662183 {
21672184 // Get character rectangle in the font atlas texture
2168- font .recs [i ] = (Rectangle ){ (float )charX , (float )charY , (float )charWidth , (float )charHeight };
2185+ font .recs [i ] = (Rectangle ){ (float )charX , (float )charY + ( float ) imHeight * pageID , (float )charWidth , (float )charHeight };
21692186
21702187 // Save data properly in sprite font
21712188 font .glyphs [i ].value = charId ;
21722189 font .glyphs [i ].offsetX = charOffsetX ;
21732190 font .glyphs [i ].offsetY = charOffsetY ;
21742191 font .glyphs [i ].advanceX = charAdvanceX ;
21752192
2176- // Fill character image data from imFont data
2177- font .glyphs [i ].image = ImageFromImage (imFont , font .recs [i ]);
2193+ // Fill character image data from full font data
2194+ font .glyphs [i ].image = ImageFromImage (fullFont , font .recs [i ]);
21782195 }
21792196 else TRACELOG (LOG_WARNING , "FONT: [%s] Some characters data not correctly provided" , fileName );
21802197 }
21812198
2182- UnloadImage (imFont );
2199+ UnloadImage (fullFont );
21832200 UnloadFileText (fileText );
21842201
21852202 if (font .texture .id == 0 )
@@ -2192,6 +2209,7 @@ static Font LoadBMFont(const char *fileName)
21922209
21932210 return font ;
21942211}
2212+
21952213#endif
21962214
21972215#endif // SUPPORT_MODULE_RTEXT
0 commit comments