@ -171,7 +171,7 @@ extern void LoadFontDefault(void)
/ / NOTE : Using UTF - 8 encoding table for Unicode U + 0000. . U + 00FF Basic Latin + Latin - 1 Supplement
/ / Ref : http : / / www . utf8 - chartable . de / unicode - utf8 - table . pl
defaultFont . glyphCount = 224 ; / / Number of char s included in our default font
defaultFont . glyphCount = 224 ; / / Number of glyph s included in our default font
defaultFont . glyphPadding = 0 ; / / Characters padding
/ / Default font is directly defined here ( data generated from a sprite font image )
@ -365,7 +365,7 @@ Font LoadFont(const char *fileName)
# define FONT_TTF_DEFAULT_FIRST_CHAR 32 / / TTF font generation default first char for image sprite font (32-Space)
# endif
# ifndef FONT_TTF_DEFAULT_CHARS_PADDING
# define FONT_TTF_DEFAULT_CHARS_PADDING 4 / / TTF font generation default char s padding
# define FONT_TTF_DEFAULT_CHARS_PADDING 4 / / TTF font generation default glyph s padding
# endif
Font font = { 0 } ;
@ -404,7 +404,7 @@ Font LoadFont(const char *fileName)
/ / Load Font from TTF or BDF font file with generation parameters
/ / NOTE : You can pass an array with desired characters , those characters should be available in the font
/ / if array is NULL , default char set is selected 32. .126
Font LoadFontEx ( const char * fileName , int fontSize , int * codepoints , int codepointCount )
Font LoadFontEx ( const char * fileName , int fontSize , ">const int * codepoints , int codepointCount )
{
Font font = { 0 } ;
@ -440,8 +440,8 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
int x = 0 ;
int y = 0 ;
/ / We allocate a temporal arrays for char s data measures ,
/ / once we get the actual number of char s, we copy data to a sized arrays
/ / We allocate a temporal arrays for glyph s data measures ,
/ / once we get the actual number of glyph s, we copy data to a sized arrays
int tempCharValues [ MAX_GLYPHS_FROM_IMAGE ] = { 0 } ;
Rectangle tempCharRecs [ MAX_GLYPHS_FROM_IMAGE ] = { 0 } ;
@ -520,7 +520,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
font . glyphCount = index ;
font . glyphPadding = 0 ;
/ / We got tempCharValues and tempCharsRecs populated with char s data
/ / We got tempCharValues and tempCharsRecs populated with glyph s data
/ / Now we move temp data to sized charValues and charRecs arrays
font . glyphs = ( GlyphInfo * ) RL_MALLOC ( font . glyphCount * sizeof ( GlyphInfo ) ) ;
font . recs = ( Rectangle * ) RL_MALLOC ( font . glyphCount * sizeof ( Rectangle ) ) ;
@ -549,7 +549,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}
/ / Load font from memory buffer , fileType refers to extension : i . e . " .ttf "
Font LoadFontFromMemory ( const char * fileType , const unsigned char * fileData , int dataSize , int fontSize , int * codepoints , int codepointCount )
Font LoadFontFromMemory ( const char * fileType , const unsigned char * fileData , int dataSize , int fontSize , ">const int * codepoints , int codepointCount )
{
Font font = { 0 } ;
@ -557,21 +557,21 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
strncpy ( fileExtLower , TextToLower ( fileType ) , 16 - 1 ) ;
font . baseSize = fontSize ;
font . glyphCount = ( codepointCount > 0 ) ? codepointCount : 95 ;
font . glyphPadding = 0 ;
# if defined(SUPPORT_FILEFORMAT_TTF)
if ( TextIsEqual ( fileExtLower , " .ttf " ) | |
TextIsEqual ( fileExtLower , " .otf " ) )
{
font . glyphs = LoadFontData ( fileData , dataSize , font . baseSize , codepoints , font . glyphCount, FONT_DEFAULT ) ;
font . glyphs = LoadFontData ( fileData , dataSize , font . baseSize , codepoints , p">( codepointCount > 0 ) ? codepointCount : 95 , FONT_DEFAULT , & font . glyphCount ) ;
}
else
# endif
# if defined(SUPPORT_FILEFORMAT_BDF)
if ( TextIsEqual ( fileExtLower , " .bdf " ) )
{
font . glyphs = LoadFontDataBDF ( fileData , dataSize , codepoints , font . glyphCount , & font . baseSize ) ;
font . glyphs = LoadFontDataBDF ( fileData , dataSize , codepoints , ( codepointCount > 0 ) ? codepointCount : 95 , & font . baseSize ) ;
font . glyphCount = ( codepointCount > 0 ) ? codepointCount : 95 ;
}
else
# endif
@ -620,7 +620,7 @@ bool IsFontValid(Font font)
/ / Load font data for further use
/ / NOTE : Requires TTF font memory data and can generate SDF data
GlyphInfo * LoadFontData ( const unsigned char * fileData , int dataSize , int fontSize , int * codepoints , int codepointCount , int type )
GlyphInfo * LoadFontData ( const unsigned char * fileData , int dataSize , int fontSize , ">const int * codepoints , int codepointCount , int type, int * glyphCount )
{
/ / NOTE : Using some SDF generation default values ,
/ / trades off precision with ability to handle * smaller * sizes
@ -637,7 +637,8 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
# define FONT_BITMAP_ALPHA_THRESHOLD 80 / / Bitmap (B&W) font generation alpha threshold
# endif
GlyphInfo * chars = NULL ;
GlyphInfo * glyphs = NULL ;
int glyphCounter = 0 ;
# if defined(SUPPORT_FILEFORMAT_TTF)
/ / Load font data ( including pixel data ) from TTF memory file
@ -646,6 +647,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
{
bool genFontChars = false ;
stbtt_fontinfo fontInfo = { 0 } ;
int * requiredCodepoints = ( int * ) codepoints ;
if ( stbtt_InitFont ( & fontInfo , ( unsigned char * ) fileData , 0 ) ) / / Initialize font for data reading
{
@ -662,21 +664,29 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
/ / Fill fontChars in case not provided externally
/ / NOTE : By default we fill glyphCount consecutively , starting at 32 ( Space )
if ( c odepoints = = NULL )
if ( requiredC odepoints = = NULL )
{
c odepoints = ( int * ) RL_MALLOC ( codepointCount * sizeof ( int ) ) ;
for ( int i = 0 ; i < codepointCount ; i + + ) c odepoints[ i ] = i + 32 ;
requiredC odepoints = ( int * ) RL_MALLOC ( codepointCount * sizeof ( int ) ) ;
for ( int i = 0 ; i < codepointCount ; i + + ) requiredC odepoints[ i ] = i + 32 ;
genFontChars = true ;
}
chars = ( GlyphInfo * ) RL_CALLOC ( codepointCount , sizeof ( GlyphInfo ) ) ;
/ / Check available glyphs on provided font before loading them
for ( int i = 0 , index ; i < codepointCount ; i + + )
{
index = stbtt_FindGlyphIndex ( & fontInfo , requiredCodepoints [ i ] ) ;
if ( index > 0 ) glyphCounter + + ;
}
/ / NOTE : Using simple packaging , one char after another
/ / WARNING : Allocating space for maximum number of codepoints
glyphs = ( GlyphInfo * ) RL_CALLOC ( glyphCounter , sizeof ( GlyphInfo ) ) ;
glyphCounter = 0 ; / / Reset to reuse
int k = 0 ;
for ( int i = 0 ; i < codepointCount ; i + + )
{
int chw = 0 , chh = 0 ; / / Character width and height ( on generation )
int ch = codepoints [ i ] ; / / Character value to get info for
chars [ i ] . value = ch ;
int cpWidth = 0 , cpHeight = 0 ; / / Codepoint width and height ( on generation )
int cp = requiredCodepoints [ i ] ; / / Codepoint value to get info for
/ / Render a unicode codepoint to a bitmap
/ / stbtt_GetCodepointBitmap ( ) - - allocates and returns a bitmap
@ -685,76 +695,96 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
/ / Check if a glyph is available in the font
/ / WARNING : if ( index = = 0 ) , glyph not found , it could fallback to default . notdef glyph ( if defined in font )
int index = stbtt_FindGlyphIndex ( & fontInfo , ch ) ;
int index = stbtt_FindGlyphIndex ( & fontInfo , cp ) ;
if ( index > 0 )
{
/ / NOTE : Only storing glyphs for codepoints found in the font
glyphs [ k ] . value = cp ;
switch ( type )
{
case FONT_DEFAULT :
case FONT_BITMAP : chars [ i ] . image . data = stbtt_GetCodepointBitmap ( & fontInfo , scaleFactor , scaleFactor , ch , & chw , & chh , & chars [ i ] . offsetX , & chars [ i ] . offsetY ) ; break ;
case FONT_SDF : if ( ch ! = 32 ) chars [ i ] . image . data = stbtt_GetCodepointSDF ( & fontInfo , scaleFactor , ch , FONT_SDF_CHAR_PADDING , FONT_SDF_ON_EDGE_VALUE , FONT_SDF_PIXEL_DIST_SCALE , & chw , & chh , & chars [ i ] . offsetX , & chars [ i ] . offsetY ) ; break ;
case FONT_BITMAP : glyphs [ k ] . image . data = stbtt_GetCodepointBitmap ( & fontInfo , scaleFactor , scaleFactor , cp , & cpWidth , & cpHeight , & glyphs [ k ] . offsetX , & glyphs [ k ] . offsetY ) ; break ;
case FONT_SDF :
{
if ( cp ! = 32 )
{
glyphs [ k ] . image . data = stbtt_GetCodepointSDF ( & fontInfo , scaleFactor , cp ,
FONT_SDF_CHAR_PADDING , FONT_SDF_ON_EDGE_VALUE , FONT_SDF_PIXEL_DIST_SCALE ,
& cpWidth , & cpHeight , & glyphs [ k ] . offsetX , & glyphs [ k ] . offsetY ) ;
}
} break ;
/ / case FONT_MSDF :
default : break ;
}
if ( chars [ i ] . image . data ! = NULL ) / / Glyph data has been found in the font
if ( glyphs [ k ] . image . data ! = NULL ) / / Glyph data has been found in the font
{
stbtt_GetCodepointHMetrics ( & fontInfo , ch , & chars [ i ] . advanceX , NULL ) ;
chars [ i ] . advanceX = ( int ) ( ( float ) chars [ i ] . advanceX * scaleFactor ) ;
stbtt_GetCodepointHMetrics ( & fontInfo , cp , & glyphs [ k ] . advanceX , NULL ) ;
glyphs [ k ] . advanceX = ( int ) ( ( float ) glyphs [ k ] . advanceX * scaleFactor ) ;
if ( chh > fontSize ) TRACELOG ( LOG_WARNING , " FONT: Character [0x%08x] size is bigger than expected font size " , ch ) ;
if ( cpHeight > fontSize ) TRACELOG ( LOG_WARNING , " FONT: [0x%04x] Glyph height is bigger than requested font size: %i > %i " , cp , cpHeig ht , ( int ) fontSize ) ;
/ / Load characters images
chars [ i ] . image . width = chw ;
chars [ i ] . image . height = chh ;
chars [ i ] . image . mipmaps = 1 ;
chars [ i ] . image . format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ;
/ / Load glyph image
glyphs [ k ] . image . width = cpWidt h ;
glyphs [ k ] . image . height = cpHeight ;
glyphs [ k ] . image . mipmaps = 1 ;
glyphs [ k ] . image . format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ;
chars [ i ] . offsetY + = ( int ) ( ( float ) ascent * scaleFactor ) ;
glyphs [ k ] . offsetY + = ( int ) ( ( float ) ascent * scaleFactor ) ;
}
/ / else TRACELOG ( LOG_WARNING , " FONT: Glyph [0x%08x] has no image data available " , cp ) ; / / Only reported for 0x20 and 0x3000
/ / l">NOTE : We create an empty image for space character ,
/ / ">it could be further required for atlas packing
if ( ch = = i">32 )
/ / We create an empty image for Space character ( 0x20 ) , useful for sprite font generation
/ / l">NOTE : Another space to consider : 0x3000 ( CJK - Ideographic Space )
if ( p">( cp = = ">0x20 ) | | ( cp = = h">0x3000 ) )
{
stbtt_GetCodepointHMetrics ( & fontInfo , ch , & chars [ i ] . advanceX , NULL ) ;
chars [ i ] . advanceX = ( int ) ( ( float ) chars [ i ] . advanceX * scaleFactor ) ;
stbtt_GetCodepointHMetrics ( & fontInfo , cp , & glyphs [ k ] . advanceX , NULL ) ;
glyphs [ k ] . advanceX = ( int ) ( ( float ) glyphs [ k ] . advanceX * scaleFactor ) ;
Image imSpace = {
. data = RL_CALLOC ( chars [ i ] . advanceX * fontSize , 2 ) ,
. width = chars [ i ] . advanceX ,
. data = RL_CALLOC ( glyphs [ k ] . advanceX * fontSize , 2 ) ,
. width = glyphs [ k ] . advanceX ,
. height = fontSize ,
. mipmaps = 1 ,
. format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
} ;
chars [ i ] . image = imSpace ;
glyphs [ k ] . image = imSpace ;
}
if ( type = = FONT_BITMAP )
{
/ / Aliased bitmap ( black & white ) font generation , avoiding anti - aliasing
/ / NOTE : For optimum results , bitmap font should be generated at base pixel size
for ( int p = 0 ; p < chw * chh ; p + + )
for ( int p = 0 ; p < cpWidth * cpHeight ; p + + )
{
if ( ( ( unsigned char * ) chars [ i ] . image . data ) [ p ] < FONT_BITMAP_ALPHA_THRESHOLD ) ( ( unsigned char * ) chars [ i ] . image . data ) [ p ] = 0 ;
else ( ( unsigned char * ) chars [ i ] . image . data ) [ p ] = 255 ;
if ( ( ( unsigned char * ) glyphs [ k ] . image . data ) [ p ] < FONT_BITMAP_ALPHA_THRESHOLD )
( ( unsigned char * ) glyphs [ k ] . image . data ) [ p ] = 0 ;
else ( ( unsigned char * ) glyphs [ k ] . image . data ) [ p ] = 255 ;
}
}
k + + ;
glyphCounter + + ;
}
else
{
/ / TODO : Use some fallback glyph for codepoints not found in the font
/ / WARNING : Glyph not found on font , optionally use a fallback glyph
}
}
if ( glyphCounter < codepointCount ) TRACELOG ( LOG_WARNING , " FONT: Requested codepoints glyphs found: [%i/%i] " , k , codepointCount ) ;
}
else TRACELOG ( LOG_WARNING , " FONT: Failed to process TTF font data " ) ;
if ( genFontChars ) RL_FREE ( c odepoints) ;
if ( genFontChars ) RL_FREE ( requiredC odepoints) ;
}
# endif
return chars ;
* glyphCount = glyphCounter ;
return glyphs ;
}
/ / Generate image font atlas using chars info
@ -1239,7 +1269,7 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
( font . recs [ index ] . height + 2.0f * font . glyphPadding ) * scaleFactor } ;
/ / Character source rectangle from font texture atlas
/ / NOTE : We consider char s padding when drawing , it could be required for outline / glow shader effects
/ / NOTE : We consider glyph s padding when drawing , it could be required for outline / glow shader effects
Rectangle srcRec = { font . recs [ index ] . x - ( float ) font . glyphPadding , font . recs [ index ] . y - ( float ) font . glyphPadding ,
font . recs [ index ] . width + 2.0f * font . glyphPadding , font . recs [ index ] . height + 2.0f * font . glyphPadding } ;
@ -1292,7 +1322,7 @@ int MeasureText(const char *text, int fontSize)
/ / Check if default font has been loaded
if ( GetFontDefault ( ) . texture . id ! = 0 )
{
int defaultFontSize = 10 ; / / Default Font char s height in pixel
int defaultFontSize = 10 ; / / Default Font glyph s height in pixel
if ( fontSize < defaultFontSize ) fontSize = defaultFontSize ;
int spacing = fontSize / defaultFontSize ;
@ -2394,7 +2424,7 @@ static unsigned char HexToInt(char hex)
/ / Load font data for further use
/ / NOTE : Requires BDF font memory data
static GlyphInfo * LoadFontDataBDF ( const unsigned char * fileData , int dataSize , int * codepoints , int codepointCount , int * outFontSize )
static GlyphInfo * LoadFontDataBDF ( const unsigned char * fileData , int dataSize , ">const int * codepoints , int codepointCount , int * outFontSize )
{
# define MAX_BUFFER_SIZE 256
@ -2428,7 +2458,9 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
int charBByoff0 = 0 ; / / Character bounding box Y0 offset
int charDWidthX = 0 ; / / Character advance X
int charDWidthY = 0 ; / / Character advance Y ( unused )
GlyphInfo * charGlyphInfo = NULL ; / / Pointer to output glyph info ( NULL if not set )
GlyphInfo * glyphs = NULL ; / / Pointer to output glyph info ( NULL if not set )
int * requiredCodepoints = codepoints ;
if ( fileData = = NULL ) return glyphs ;
@ -2437,10 +2469,10 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
/ / Fill fontChars in case not provided externally
/ / NOTE : By default we fill glyphCount consecutively , starting at 32 ( Space )
if ( c odepoints = = NULL )
if ( requiredC odepoints = = NULL )
{
c odepoints = ( int * ) RL_MALLOC ( codepointCount * sizeof ( int ) ) ;
for ( int i = 0 ; i < codepointCount ; i + + ) c odepoints[ i ] = i + 32 ;
requiredC odepoints = ( int * ) RL_MALLOC ( codepointCount * sizeof ( int ) ) ;
for ( int i = 0 ; i < codepointCount ; i + + ) requiredC odepoints[ i ] = i + 32 ;
genFontChars = true ;
}
@ -2466,11 +2498,11 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
if ( charBitmapStarted )
{
if ( charGlyphInfo ! = NULL )
if ( glyphs ! = NULL )
{
int pixelY = charBitmapNextRow + + ;
if ( pixelY > = charGlyphInfo - > image . height ) break ;
if ( pixelY > = glyphs - > image . height ) break ;
for ( int x = 0 ; x < readBytes ; x + + )
{
@ -2480,9 +2512,9 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
{
int pixelX = ( ( x * 4 ) + bitX ) ;
if ( pixelX > = charGlyphInfo - > image . width ) break ;
if ( pixelX > = glyphs - > image . width ) break ;
if ( ( byte & ( 8 > > bitX ) ) > 0 ) ( ( unsigned char * ) charGlyphInfo - > image . data ) [ ( pixelY * charGlyphInfo - > image . width ) + pixelX ] = 255 ;
if ( ( byte & ( 8 > > bitX ) ) > 0 ) ( ( unsigned char * ) glyphs - > image . data ) [ ( pixelY * glyphs - > image . width ) + pixelX ] = 255 ;
}
}
}
@ -2514,30 +2546,30 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
if ( strstr ( buffer , " BITMAP " ) ! = NULL )
{
/ / Search for glyph index in codepoints
charGlyphInfo = NULL ;
glyphs = NULL ;
for ( int codepointIndex = 0 ; codepointIndex < codepointCount ; codepointIndex + + )
{
if ( codepoints [ codepointIndex ] = = charEncoding )
{
charGlyphInfo = & glyphs [ codepointIndex ] ;
glyphs = & glyphs [ codepointIndex ] ;
break ;
}
}
/ / Init glyph info
if ( charGlyphInfo ! = NULL )
if ( glyphs ! = NULL )
{
charGlyphInfo - > value = charEncoding ;
charGlyphInfo - > offsetX = charBBxoff0 + fontBByoff0 ;
charGlyphInfo - > offsetY = fontBBh - ( charBBh + charBByoff0 + fontBByoff0 + fontAscent ) ;
charGlyphInfo - > advanceX = charDWidthX ;
charGlyphInfo - > image . data = RL_CALLOC ( charBBw * charBBh , 1 ) ;
charGlyphInfo - > image . width = charBBw ;
charGlyphInfo - > image . height = charBBh ;
charGlyphInfo - > image . mipmaps = 1 ;
charGlyphInfo - > image . format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ;
glyphs - > value = charEncoding ;
glyphs - > offsetX = charBBxoff0 + fontBByoff0 ;
glyphs - > offsetY = fontBBh - ( charBBh + charBByoff0 + fontBByoff0 + fontAscent ) ;
glyphs - > advanceX = charDWidthX ;
glyphs - > image . data = RL_CALLOC ( charBBw * charBBh , 1 ) ;
glyphs - > image . width = charBBw ;
glyphs - > image . height = charBBh ;
glyphs - > image . mipmaps = 1 ;
glyphs - > image . format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE ;
}
charBitmapStarted = true ;
@ -2588,14 +2620,14 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
{
charStarted = true ;
charEncoding = - 1 ;
charGlyphInfo = NULL ;
glyphs = NULL ;
charBBw = 0 ;
charBBh = 0 ;
charBBxoff0 = 0 ;
charBByoff0 = 0 ;
charDWidthX = 0 ;
charDWidthY = 0 ;
charGlyphInfo = NULL ;
glyphs = NULL ;
charBitmapStarted = false ;
charBitmapNextRow = 0 ;
continue ;