summaryrefslogtreecommitdiffhomepage
path: root/src/text.c
diff options
context:
space:
mode:
authorDavid Reid <[email protected]>2018-04-21 17:26:40 +1000
committerDavid Reid <[email protected]>2018-04-21 17:26:40 +1000
commitf5ebbfb6bc80e5d5555e84ee505ff794c2bc64b6 (patch)
tree800aeb61be9c2018d1a048da54d1f6ab746f11f1 /src/text.c
parent950f31e620a9239dc91230ad92bb243f149e6f2c (diff)
parent847bdaf68287f70fbeb5599361257b6f982e48c5 (diff)
downloadraylib-f5ebbfb6bc80e5d5555e84ee505ff794c2bc64b6.tar.gz
raylib-f5ebbfb6bc80e5d5555e84ee505ff794c2bc64b6.zip
Merge branch 'master' of https://github.com/raysan5/raylib into dr/mini_al
Diffstat (limited to 'src/text.c')
-rw-r--r--src/text.c189
1 files changed, 85 insertions, 104 deletions
diff --git a/src/text.c b/src/text.c
index 465e4546..1a9d386a 100644
--- a/src/text.c
+++ b/src/text.c
@@ -6,7 +6,7 @@
*
* #define SUPPORT_FILEFORMAT_FNT
* #define SUPPORT_FILEFORMAT_TTF
-* Selected desired fileformats to be supported for loading. Some of those formats are
+* Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
* #define SUPPORT_DEFAULT_FONT
@@ -17,7 +17,7 @@
*
* LICENSE: zlib/libpng
*
-* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5)
+* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@@ -36,12 +36,7 @@
*
**********************************************************************************************/
-// Default supported features
-//-------------------------------------
-#define SUPPORT_DEFAULT_FONT
-#define SUPPORT_FILEFORMAT_FNT
-#define SUPPORT_FILEFORMAT_TTF
-//-------------------------------------
+#include "config.h"
#include "raylib.h"
@@ -66,8 +61,8 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define MAX_FORMATTEXT_LENGTH 64
-#define MAX_SUBTEXT_LENGTH 64
+#define MAX_FORMATTEXT_LENGTH 256
+#define MAX_SUBTEXT_LENGTH 256
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -90,11 +85,9 @@ static SpriteFont defaultFont; // Default font provided by raylib
//----------------------------------------------------------------------------------
// 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)
#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)
#endif
#if defined(SUPPORT_FILEFORMAT_TTF)
static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
@@ -113,7 +106,7 @@ extern void UnloadDefaultFont(void);
// Load raylib default font
extern void LoadDefaultFont(void)
{
- #define BIT_CHECK(a,b) ((a) & (1 << (b)))
+ #define BIT_CHECK(a,b) ((a) & (1u << (b)))
// NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// http://www.utf8-chartable.de/unicode-utf8-table.pl
@@ -288,40 +281,14 @@ SpriteFont LoadSpriteFont(const char *fileName)
SpriteFont spriteFont = { 0 };
- // Check file extension
- if (IsFileExtension(fileName, ".rres"))
- {
- // TODO: Read multiple resource blocks from file (RRES_FONT_IMAGE, RRES_FONT_CHARDATA)
- RRES rres = LoadResource(fileName, 0);
-
- // Load sprite font texture
- if (rres[0].type == RRES_TYPE_FONT_IMAGE)
- {
- // NOTE: Parameters for RRES_FONT_IMAGE type are: width, height, format, mipmaps
- Image image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3);
- spriteFont.texture = LoadTextureFromImage(image);
- UnloadImage(image);
- }
-
- // Load sprite characters data
- if (rres[1].type == RRES_TYPE_FONT_CHARDATA)
- {
- // NOTE: Parameters for RRES_FONT_CHARDATA type are: fontSize, charsCount
- spriteFont.baseSize = rres[1].param1;
- spriteFont.charsCount = rres[1].param2;
- spriteFont.chars = rres[1].data;
- }
-
- // TODO: Do not free rres.data memory (chars info data!)
- //UnloadResource(rres[0]);
- }
#if defined(SUPPORT_FILEFORMAT_TTF)
- else if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
+ if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
+ else
#endif
#if defined(SUPPORT_FILEFORMAT_FNT)
- else if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
-#endif
+ if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName);
else
+#endif
{
Image image = LoadImage(fileName);
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
@@ -344,21 +311,20 @@ SpriteFont LoadSpriteFont(const char *fileName)
SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars)
{
SpriteFont spriteFont = { 0 };
+ int totalChars = 95; // Default charset [32..126]
#if defined(SUPPORT_FILEFORMAT_TTF)
if (IsFileExtension(fileName, ".ttf"))
{
- if ((fontChars == NULL) || (charsCount == 0))
+ if (charsCount != 0) totalChars = charsCount;
+
+ if (fontChars == NULL)
{
- int totalChars = 95; // Default charset [32..126]
-
- int *defaultFontChars = (int *)malloc(totalChars*sizeof(int));
-
- for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32]
-
- spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars);
+ fontChars = (int *)malloc(totalChars*sizeof(int));
+ for (int i = 0; i < totalChars; i++) fontChars[i] = i + 32; // Default first character: SPACE[32]
}
- else spriteFont = LoadTTF(fileName, fontSize, charsCount, fontChars);
+
+ spriteFont = LoadTTF(fileName, fontSize, totalChars, fontChars);
}
#endif
@@ -372,13 +338,13 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount,
}
// Unload SpriteFont from GPU memory (VRAM)
-void UnloadSpriteFont(SpriteFont spriteFont)
+void UnloadSpriteFont(SpriteFont font)
{
// 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);
- free(spriteFont.chars);
+ UnloadTexture(font.texture);
+ free(font.chars);
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
}
@@ -404,7 +370,7 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
// Draw text using SpriteFont
// 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 textOffsetX = 0; // Offset between characters
@@ -414,7 +380,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
unsigned char letter; // Current character
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
// written in C code files (codified by default as UTF-8)
@@ -424,7 +390,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
if ((unsigned char)text[i] == '\n')
{
// 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;
}
else
@@ -433,26 +399,29 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
{
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
letter = (unsigned char)text[i + 1];
- index = GetCharIndex(spriteFont, (int)letter);
+ index = GetGlyphIndex(font, (int)letter);
i++;
}
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
{
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
letter = (unsigned char)text[i + 1];
- index = GetCharIndex(spriteFont, (int)letter + 64);
+ index = GetGlyphIndex(font, (int)letter + 64);
i++;
}
- else index = GetCharIndex(spriteFont, (unsigned char)text[i]);
-
- DrawTexturePro(spriteFont.texture, spriteFont.chars[index].rec,
- (Rectangle){ position.x + textOffsetX + spriteFont.chars[index].offsetX*scaleFactor,
- position.y + textOffsetY + spriteFont.chars[index].offsetY*scaleFactor,
- spriteFont.chars[index].rec.width*scaleFactor,
- spriteFont.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
+ else index = GetGlyphIndex(font, (unsigned char)text[i]);
+
+ if ((unsigned char)text[i] != ' ')
+ {
+ DrawTexturePro(font.texture, font.chars[index].rec,
+ (Rectangle){ position.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
+ position.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
+ font.chars[index].rec.width*scaleFactor,
+ 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);
- else textOffsetX += (int)(spriteFont.chars[index].advanceX*scaleFactor + spacing);
+ if (font.chars[index].advanceX == 0) textOffsetX += (int)(font.chars[index].rec.width*scaleFactor + spacing);
+ else textOffsetX += (int)(font.chars[index].advanceX*scaleFactor + spacing);
}
}
}
@@ -514,7 +483,7 @@ int MeasureText(const char *text, int fontSize)
}
// 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 tempLen = 0; // Used to count longer text line num chars
@@ -523,8 +492,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
float textWidth = 0;
float tempTextWidth = 0; // Used to count longer text line width
- float textHeight = (float)spriteFont.baseSize;
- float scaleFactor = fontSize/(float)spriteFont.baseSize;
+ float textHeight = (float)font.baseSize;
+ float scaleFactor = fontSize/(float)font.baseSize;
for (int i = 0; i < len; i++)
{
@@ -532,17 +501,17 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
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;
- else textWidth += (spriteFont.chars[index].rec.width + spriteFont.chars[index].offsetX);
+ if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX;
+ else textWidth += (font.chars[index].rec.width + font.chars[index].offsetX);
}
else
{
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
lenCounter = 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;
@@ -557,6 +526,28 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i
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
// NOTE: Uses default font
void DrawFPS(int posX, int posY)
@@ -583,27 +574,6 @@ void DrawFPS(int posX, int posY)
// 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)
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
{
@@ -733,7 +703,7 @@ static SpriteFont LoadBMFont(const char *fileName)
int fontSize = 0;
int texWidth, texHeight;
- char texFileName[128];
+ char texFileName[129];
int charsCount = 0;
int base; // Useless data
@@ -872,14 +842,25 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
// NOTE: We try reading up to 16 MB of elements of 1 byte
fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile);
-
+
+ // Find font baseline (vertical origin of the font)
+ // NOTE: This value is required because y-offset depends on it!
+ stbtt_fontinfo fontInfo;
+ int ascent, baseline;
+ float scale;
+
+ stbtt_InitFont(&fontInfo, ttfBuffer, 0);
+ scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize);
+ stbtt_GetFontVMetrics(&fontInfo, &ascent, 0, 0);
+ baseline = (int)(ascent*scale);
+
if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
- // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image...
+ // NOTE: Using stb_truetype crappy packing method, no guarantee the font fits the image...
// TODO: Replace this function by a proper packing method and support random chars order,
// we already receive a list (fontChars) with the ordered expected characters
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData);
-
+
//if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font");
@@ -924,7 +905,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
font.chars[i].rec.height = (int)charData[i].y1 - (int)charData[i].y0;
font.chars[i].offsetX = charData[i].xoff;
- font.chars[i].offsetY = charData[i].yoff;
+ font.chars[i].offsetY = baseline + charData[i].yoff;
font.chars[i].advanceX = (int)charData[i].xadvance;
}