mirror of https://github.com/raysan5/raylib
Support unordered charset, neither fixed first char
Still requires some testing...
This commit is contained in:
parent
3393fda384
commit
6d3b11ef91
79
src/text.c
79
src/text.c
|
@ -44,7 +44,6 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define FONT_FIRST_CHAR 32 // NOTE: Expected first char for a sprite font
|
|
||||||
#define MAX_FORMATTEXT_LENGTH 64
|
#define MAX_FORMATTEXT_LENGTH 64
|
||||||
#define MAX_SUBTEXT_LENGTH 64
|
#define MAX_SUBTEXT_LENGTH 64
|
||||||
|
|
||||||
|
@ -69,6 +68,8 @@ static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
static int GetCharIndex(SpriteFont font, int letter);
|
||||||
|
|
||||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
||||||
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
||||||
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
|
@ -197,7 +198,7 @@ extern void LoadDefaultFont(void)
|
||||||
|
|
||||||
for (int i = 0; i < defaultFont.numChars; i++)
|
for (int i = 0; i < defaultFont.numChars; i++)
|
||||||
{
|
{
|
||||||
defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32
|
defaultFont.charValues[i] = 32 + i; // First char is 32
|
||||||
|
|
||||||
defaultFont.charRecs[i].x = currentPosX;
|
defaultFont.charRecs[i].x = currentPosX;
|
||||||
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
|
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||||
|
@ -248,6 +249,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
// Default hardcoded values for ttf file loading
|
// Default hardcoded values for ttf file loading
|
||||||
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
|
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
|
||||||
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
|
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
|
||||||
|
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont
|
||||||
|
|
||||||
SpriteFont spriteFont = { 0 };
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
@ -258,7 +260,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Image image = LoadImage(fileName);
|
Image image = LoadImage(fileName);
|
||||||
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, FONT_FIRST_CHAR);
|
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +269,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
||||||
spriteFont = GetDefaultFont();
|
spriteFont = GetDefaultFont();
|
||||||
}
|
}
|
||||||
else SetTextureFilter(spriteFont.texture, FILTER_BILINEAR);
|
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||||
|
|
||||||
return spriteFont;
|
return spriteFont;
|
||||||
}
|
}
|
||||||
|
@ -356,22 +358,18 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
// TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR,
|
|
||||||
// this sytem can be improved to support any characters order and init value...
|
|
||||||
// An intermediate table could be created to link char values with predefined char position index in chars rectangle array
|
|
||||||
|
|
||||||
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||||
{
|
{
|
||||||
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||||
letter = (unsigned char)text[i + 1];
|
letter = (unsigned char)text[i + 1];
|
||||||
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR];
|
rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter)];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||||
{
|
{
|
||||||
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||||
letter = (unsigned char)text[i + 1];
|
letter = (unsigned char)text[i + 1];
|
||||||
rec = spriteFont.charRecs[letter - FONT_FIRST_CHAR + 64];
|
rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)letter + 64)];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -383,17 +381,19 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
rec.x = -1;
|
rec.x = -1;
|
||||||
}
|
}
|
||||||
else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR];
|
else rec = spriteFont.charRecs[GetCharIndex(spriteFont, (int)text[i])];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec.x >= 0)
|
if (rec.x >= 0)
|
||||||
{
|
{
|
||||||
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor,
|
int index = GetCharIndex(spriteFont, (int)text[i]);
|
||||||
position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
|
|
||||||
|
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor,
|
||||||
|
position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor,
|
||||||
rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
|
rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
|
|
||||||
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] == 0) textOffsetX += (rec.width*scaleFactor + spacing);
|
if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (rec.width*scaleFactor + spacing);
|
||||||
else textOffsetX += (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]*scaleFactor + spacing);
|
else textOffsetX += (spriteFont.charAdvanceX[index]*scaleFactor + spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,8 +473,10 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
|
||||||
|
|
||||||
if (text[i] != '\n')
|
if (text[i] != '\n')
|
||||||
{
|
{
|
||||||
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR];
|
int index = GetCharIndex(spriteFont, (int)text[i]);
|
||||||
else textWidth += (spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x);
|
|
||||||
|
if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index];
|
||||||
|
else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -531,6 +533,27 @@ void DrawFPS(int posX, int posY)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static int GetCharIndex(SpriteFont font, int letter)
|
||||||
|
{
|
||||||
|
//#define UNORDERED_CHARSET
|
||||||
|
#if defined(UNORDERED_CHARSET)
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < font.numChars; i++)
|
||||||
|
{
|
||||||
|
if (font.charValues[i] == letter)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#else
|
||||||
|
return (letter - 32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Load an Image font file (XNA style)
|
// Load an Image font file (XNA style)
|
||||||
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||||
{
|
{
|
||||||
|
@ -857,6 +880,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||||
if (imFont.format == UNCOMPRESSED_GRAYSCALE) ImageAlphaMask(&imFont, imFont);
|
if (imFont.format == UNCOMPRESSED_GRAYSCALE) ImageAlphaMask(&imFont, imFont);
|
||||||
|
|
||||||
font.texture = LoadTextureFromImage(imFont);
|
font.texture = LoadTextureFromImage(imFont);
|
||||||
|
|
||||||
font.size = fontSize;
|
font.size = fontSize;
|
||||||
font.numChars = numChars;
|
font.numChars = numChars;
|
||||||
font.charValues = (int *)malloc(numChars*sizeof(int));
|
font.charValues = (int *)malloc(numChars*sizeof(int));
|
||||||
|
@ -870,30 +894,12 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||||
|
|
||||||
bool unorderedChars = false;
|
|
||||||
int firstChar = 32;
|
|
||||||
|
|
||||||
for (int i = 0; i < numChars; i++)
|
for (int i = 0; i < numChars; i++)
|
||||||
{
|
{
|
||||||
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
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);
|
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
|
||||||
|
|
||||||
if ((i == 0) && (charId != FONT_FIRST_CHAR))
|
|
||||||
{
|
|
||||||
TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
|
|
||||||
firstChar = charId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ((i < (126 - FONT_FIRST_CHAR)) && (i != (charId - FONT_FIRST_CHAR)))
|
|
||||||
{
|
|
||||||
// NOTE: We expect the first 95 chars (32..126) to be ordered for quick drawing access,
|
|
||||||
// characters above are stored and we look for them (search algorythm) when drawing
|
|
||||||
TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
|
|
||||||
unorderedChars = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save data properly in sprite font
|
// Save data properly in sprite font
|
||||||
font.charValues[i] = charId;
|
font.charValues[i] = charId;
|
||||||
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
|
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
|
||||||
|
@ -903,8 +909,7 @@ static SpriteFont LoadBMFont(const char *fileName)
|
||||||
|
|
||||||
fclose(fntFile);
|
fclose(fntFile);
|
||||||
|
|
||||||
// NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
|
if (font.texture.id == 0)
|
||||||
if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
|
|
||||||
{
|
{
|
||||||
UnloadSpriteFont(font);
|
UnloadSpriteFont(font);
|
||||||
font = GetDefaultFont();
|
font = GetDefaultFont();
|
||||||
|
|
Loading…
Reference in New Issue