Support UTF8 basic characters on ImageTextEx()
Supported UTF8 range equivalent to [128..255] (80h..FFh) Exposed and renamed text function GetGlyphIndex() Renamed spriteFont parameter name to simply font Small security check on transmission mission ending screen
This commit is contained in:
parent
50fc4f7164
commit
4492a70a4b
4 changed files with 86 additions and 58 deletions
|
@ -113,7 +113,7 @@ void InitEndingScreen(void)
|
||||||
|
|
||||||
strcpy(headline, title); // Base headline updated
|
strcpy(headline, title); // Base headline updated
|
||||||
|
|
||||||
free(title);
|
if (title != NULL) free(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -948,19 +948,20 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest
|
||||||
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
||||||
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
||||||
RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters
|
RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters
|
||||||
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM)
|
RLAPI void UnloadSpriteFont(SpriteFont font); // Unload SpriteFont from GPU memory (VRAM)
|
||||||
|
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS
|
||||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||||
RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
RLAPI void DrawTextEx(SpriteFont font, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
||||||
float fontSize, int spacing, Color tint);
|
float fontSize, int spacing, Color tint);
|
||||||
|
|
||||||
// Text misc. functions
|
// Text misc. functions
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
RLAPI Vector2 MeasureTextEx(SpriteFont font, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
||||||
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||||
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||||
|
RLAPI int GetGlyphIndex(SpriteFont font, int character); // Returns index position for a unicode character on sprite font
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||||
|
|
93
src/text.c
93
src/text.c
|
@ -90,8 +90,6 @@ 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)
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
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)
|
||||||
|
@ -345,13 +343,13 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload SpriteFont from GPU memory (VRAM)
|
// Unload SpriteFont from GPU memory (VRAM)
|
||||||
void UnloadSpriteFont(SpriteFont spriteFont)
|
void UnloadSpriteFont(SpriteFont font)
|
||||||
{
|
{
|
||||||
// NOTE: Make sure spriteFont is not default font (fallback)
|
// NOTE: Make sure spriteFont is not default font (fallback)
|
||||||
if (spriteFont.texture.id != GetDefaultFont().texture.id)
|
if (font.texture.id != GetDefaultFont().texture.id)
|
||||||
{
|
{
|
||||||
UnloadTexture(spriteFont.texture);
|
UnloadTexture(font.texture);
|
||||||
free(spriteFont.chars);
|
free(font.chars);
|
||||||
|
|
||||||
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
|
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
|
||||||
}
|
}
|
||||||
|
@ -377,7 +375,7 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
||||||
|
|
||||||
// Draw text using SpriteFont
|
// Draw text using SpriteFont
|
||||||
// NOTE: chars spacing is NOT proportional to fontSize
|
// NOTE: chars spacing is NOT proportional to fontSize
|
||||||
void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
void DrawTextEx(SpriteFont font, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
||||||
{
|
{
|
||||||
int length = strlen(text);
|
int length = strlen(text);
|
||||||
int textOffsetX = 0; // Offset between characters
|
int textOffsetX = 0; // Offset between characters
|
||||||
|
@ -387,7 +385,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
unsigned char letter; // Current character
|
unsigned char letter; // Current character
|
||||||
int index; // Index position in sprite font
|
int index; // Index position in sprite font
|
||||||
|
|
||||||
scaleFactor = fontSize/spriteFont.baseSize;
|
scaleFactor = fontSize/font.baseSize;
|
||||||
|
|
||||||
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
||||||
// written in C code files (codified by default as UTF-8)
|
// written in C code files (codified by default as UTF-8)
|
||||||
|
@ -397,7 +395,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
if ((unsigned char)text[i] == '\n')
|
if ((unsigned char)text[i] == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 lines
|
// NOTE: Fixed line spacing of 1.5 lines
|
||||||
textOffsetY += (int)((spriteFont.baseSize + spriteFont.baseSize/2)*scaleFactor);
|
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
|
||||||
textOffsetX = 0;
|
textOffsetX = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -406,29 +404,29 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
|
||||||
{
|
{
|
||||||
// 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];
|
||||||
index = GetCharIndex(spriteFont, (int)letter);
|
index = GetGlyphIndex(font, (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];
|
||||||
index = GetCharIndex(spriteFont, (int)letter + 64);
|
index = GetGlyphIndex(font, (int)letter + 64);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else index = GetCharIndex(spriteFont, (unsigned char)text[i]);
|
else index = GetGlyphIndex(font, (unsigned char)text[i]);
|
||||||
|
|
||||||
if ((unsigned char)text[i] != ' ')
|
if ((unsigned char)text[i] != ' ')
|
||||||
{
|
{
|
||||||
DrawTexturePro(spriteFont.texture, spriteFont.chars[index].rec,
|
DrawTexturePro(font.texture, font.chars[index].rec,
|
||||||
(Rectangle){ position.x + textOffsetX + spriteFont.chars[index].offsetX*scaleFactor,
|
(Rectangle){ position.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
|
||||||
position.y + textOffsetY + spriteFont.chars[index].offsetY*scaleFactor,
|
position.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
|
||||||
spriteFont.chars[index].rec.width*scaleFactor,
|
font.chars[index].rec.width*scaleFactor,
|
||||||
spriteFont.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
|
font.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spriteFont.chars[index].advanceX == 0) textOffsetX += (int)(spriteFont.chars[index].rec.width*scaleFactor + spacing);
|
if (font.chars[index].advanceX == 0) textOffsetX += (int)(font.chars[index].rec.width*scaleFactor + spacing);
|
||||||
else textOffsetX += (int)(spriteFont.chars[index].advanceX*scaleFactor + spacing);
|
else textOffsetX += (int)(font.chars[index].advanceX*scaleFactor + spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,7 +488,7 @@ int MeasureText(const char *text, int fontSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure string size for SpriteFont
|
// Measure string size for SpriteFont
|
||||||
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing)
|
Vector2 MeasureTextEx(SpriteFont font, const char *text, float fontSize, int spacing)
|
||||||
{
|
{
|
||||||
int len = strlen(text);
|
int len = strlen(text);
|
||||||
int tempLen = 0; // Used to count longer text line num chars
|
int tempLen = 0; // Used to count longer text line num chars
|
||||||
|
@ -499,8 +497,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
float textWidth = 0;
|
float textWidth = 0;
|
||||||
float tempTextWidth = 0; // Used to count longer text line width
|
float tempTextWidth = 0; // Used to count longer text line width
|
||||||
|
|
||||||
float textHeight = (float)spriteFont.baseSize;
|
float textHeight = (float)font.baseSize;
|
||||||
float scaleFactor = fontSize/(float)spriteFont.baseSize;
|
float scaleFactor = fontSize/(float)font.baseSize;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
|
@ -508,17 +506,17 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
|
|
||||||
if (text[i] != '\n')
|
if (text[i] != '\n')
|
||||||
{
|
{
|
||||||
int index = GetCharIndex(spriteFont, (int)text[i]);
|
int index = GetGlyphIndex(font, (int)text[i]);
|
||||||
|
|
||||||
if (spriteFont.chars[index].advanceX != 0) textWidth += spriteFont.chars[index].advanceX;
|
if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX;
|
||||||
else textWidth += (spriteFont.chars[index].rec.width + spriteFont.chars[index].offsetX);
|
else textWidth += (font.chars[index].rec.width + font.chars[index].offsetX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
lenCounter = 0;
|
lenCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)spriteFont.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempLen < lenCounter) tempLen = lenCounter;
|
if (tempLen < lenCounter) tempLen = lenCounter;
|
||||||
|
@ -533,6 +531,28 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns index position for a unicode character on spritefont
|
||||||
|
int GetGlyphIndex(SpriteFont font, int character)
|
||||||
|
{
|
||||||
|
#define UNORDERED_CHARSET
|
||||||
|
#if defined(UNORDERED_CHARSET)
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < font.charsCount; i++)
|
||||||
|
{
|
||||||
|
if (font.chars[i].value == character)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#else
|
||||||
|
return (character - 32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Shows current FPS on top-left corner
|
// Shows current FPS on top-left corner
|
||||||
// NOTE: Uses default font
|
// NOTE: Uses default font
|
||||||
void DrawFPS(int posX, int posY)
|
void DrawFPS(int posX, int posY)
|
||||||
|
@ -559,27 +579,6 @@ 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.charsCount; i++)
|
|
||||||
{
|
|
||||||
if (font.chars[i].value == 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1374,6 +1374,8 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||||
{
|
{
|
||||||
int length = strlen(text);
|
int length = strlen(text);
|
||||||
int posX = 0;
|
int posX = 0;
|
||||||
|
int index; // Index position in sprite font
|
||||||
|
unsigned char character; // Current character
|
||||||
|
|
||||||
Vector2 imSize = MeasureTextEx(font, text, font.baseSize, spacing);
|
Vector2 imSize = MeasureTextEx(font, text, font.baseSize, spacing);
|
||||||
|
|
||||||
|
@ -1389,14 +1391,40 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
CharInfo letter = font.chars[(int)text[i] - 32];
|
if ((unsigned char)text[i] == '\n')
|
||||||
|
{
|
||||||
|
// TODO: Support line break
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||||
|
character = (unsigned char)text[i + 1];
|
||||||
|
index = GetGlyphIndex(font, (int)character);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||||
|
character = (unsigned char)text[i + 1];
|
||||||
|
index = GetGlyphIndex(font, (int)character + 64);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else index = GetGlyphIndex(font, (unsigned char)text[i]);
|
||||||
|
|
||||||
|
CharInfo letter = font.chars[index];
|
||||||
|
|
||||||
|
if ((unsigned char)text[i] != ' ')
|
||||||
|
{
|
||||||
ImageDraw(&imText, imFont, letter.rec, (Rectangle){ posX + letter.offsetX,
|
ImageDraw(&imText, imFont, letter.rec, (Rectangle){ posX + letter.offsetX,
|
||||||
letter.offsetY, letter.rec.width, letter.rec.height });
|
letter.offsetY, letter.rec.width, letter.rec.height });
|
||||||
|
}
|
||||||
|
|
||||||
if (letter.advanceX == 0) posX += letter.rec.width + spacing;
|
if (letter.advanceX == 0) posX += letter.rec.width + spacing;
|
||||||
else posX += letter.advanceX + spacing;
|
else posX += letter.advanceX + spacing;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UnloadImage(imFont);
|
UnloadImage(imFont);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue