summaryrefslogtreecommitdiffhomepage
path: root/src/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/text.c')
-rw-r--r--src/text.c222
1 files changed, 116 insertions, 106 deletions
diff --git a/src/text.c b/src/text.c
index ec2480e3..c538ea56 100644
--- a/src/text.c
+++ b/src/text.c
@@ -34,7 +34,7 @@
// Following libs are used on LoadTTF()
#define STB_TRUETYPE_IMPLEMENTATION
-#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
+#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
// Rectangle packing functions (not used at the moment)
//#define STB_RECT_PACK_IMPLEMENTATION
@@ -43,8 +43,7 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define FONT_FIRST_CHAR 32
-#define MAX_FONTCHARS 128
+#define FONT_FIRST_CHAR 32 // NOTE: Expected first char for a sprite font
#define MAX_FORMATTEXT_LENGTH 64
#define MAX_SUBTEXT_LENGTH 64
@@ -72,7 +71,9 @@ static SpriteFont defaultFont; // Default font provided by raylib
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 LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
-static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required)
+
+// Generate a sprite font image from TTF data
+static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars);
extern void LoadDefaultFont(void);
extern void UnloadDefaultFont(void);
@@ -150,7 +151,7 @@ extern void LoadDefaultFont(void)
//----------------------------------------------------------------------
int imWidth = 128;
int imHeight = 128;
-
+
Color *imagePixels = (Color *)malloc(imWidth*imHeight*sizeof(Color));
for (int i = 0; i < imWidth*imHeight; i++) imagePixels[i] = BLANK; // Initialize array
@@ -173,7 +174,7 @@ extern void LoadDefaultFont(void)
//FILE *myimage = fopen("default_font.raw", "wb");
//fwrite(image.pixels, 1, 128*128*4, myimage);
//fclose(myimage);
-
+
Image image = LoadImageEx(imagePixels, imWidth, imHeight);
ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
@@ -184,13 +185,13 @@ extern void LoadDefaultFont(void)
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
//------------------------------------------------------------------------------
- defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int));
+ defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int));
defaultFont.charRecs = (Rectangle *)malloc(defaultFont.numChars*sizeof(Rectangle)); // Allocate space for our character rectangle data
// This memory should be freed at end! --> Done on CloseWindow()
-
+
defaultFont.charOffsets = (Vector2 *)malloc(defaultFont.numChars*sizeof(Vector2));
defaultFont.charAdvanceX = (int *)malloc(defaultFont.numChars*sizeof(int));
-
+
int currentLine = 0;
int currentPosX = charsDivisor;
int testPosX = charsDivisor;
@@ -198,9 +199,9 @@ extern void LoadDefaultFont(void)
for (int i = 0; i < defaultFont.numChars; i++)
{
defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32
-
+
defaultFont.charRecs[i].x = currentPosX;
- defaultFont.charRecs[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
+ defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
defaultFont.charRecs[i].width = charsWidth[i];
defaultFont.charRecs[i].height = charsHeight;
@@ -216,12 +217,12 @@ extern void LoadDefaultFont(void)
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
}
else currentPosX = testPosX;
-
+
// NOTE: On default font character offsets and xAdvance are not required
defaultFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
defaultFont.charAdvanceX[i] = 0;
}
-
+
defaultFont.size = defaultFont.charRecs[0].height;
TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
@@ -245,19 +246,23 @@ SpriteFont GetDefaultFont()
// Load a SpriteFont image into GPU memory
SpriteFont LoadSpriteFont(const char *fileName)
{
+ // Default hardcoded values for ttf file loading
+ #define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
+ #define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
+
SpriteFont spriteFont = { 0 };
// Check file extension
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
- else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, 32);
+ else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, DEFAULT_TTF_FONTSIZE, FONT_FIRST_CHAR, DEFAULT_TTF_NUMCHARS);
else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName);
else
{
Image image = LoadImage(fileName);
- if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, 32);
+ if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, FONT_FIRST_CHAR);
UnloadImage(image);
}
-
+
if (spriteFont.texture.id == 0)
{
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
@@ -292,14 +297,14 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
int defaultFontSize = 10; // Default Font chars height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
- int spacing = fontSize / defaultFontSize;
+ int spacing = fontSize/defaultFontSize;
- DrawTextEx(defaultFont, text, position, fontSize, spacing, color);
+ DrawTextEx(defaultFont, text, position, (float)fontSize, spacing, color);
}
// Draw text using SpriteFont
// NOTE: chars spacing is NOT proportional to fontSize
-void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int fontSize, int spacing, Color tint)
+void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
{
int length = strlen(text);
int textOffsetX = 0;
@@ -309,17 +314,17 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f
Rectangle rec;
- scaleFactor = (float)fontSize/spriteFont.size;
+ scaleFactor = fontSize/spriteFont.size;
- // 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)
-
- 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!
{
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
@@ -348,8 +353,8 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f
if (rec.x > 0)
{
- DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor,
- position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
+ DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor,
+ position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
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);
@@ -376,15 +381,15 @@ const char *SubText(const char *text, int position, int length)
{
static char buffer[MAX_SUBTEXT_LENGTH];
int textLength = strlen(text);
-
+
if (position >= textLength)
{
position = textLength - 1;
length = 0;
}
-
+
if (length >= textLength) length = textLength;
-
+
for (int c = 0 ; c < length ; c++)
{
*(buffer+c) = *(text+position);
@@ -403,7 +408,7 @@ int MeasureText(const char *text, int fontSize)
int defaultFontSize = 10; // Default Font chars height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
- int spacing = fontSize / defaultFontSize;
+ int spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(defaultFont, text, fontSize, spacing);
@@ -416,17 +421,17 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
int len = strlen(text);
int tempLen = 0; // Used to count longer text line num chars
int lenCounter = 0;
-
+
int textWidth = 0;
int tempTextWidth = 0; // Used to count longer text line width
-
+
int textHeight = spriteFont.size;
float scaleFactor;
for (int i = 0; i < len; i++)
{
lenCounter++;
-
+
if (text[i] != '\n')
{
if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR];
@@ -439,10 +444,10 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int
textWidth = 0;
textHeight += (spriteFont.size + spriteFont.size/2); // NOTE: Fixed line spacing of 1.5 lines
}
-
+
if (tempLen < lenCounter) tempLen = lenCounter;
}
-
+
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
if (fontSize <= spriteFont.size) scaleFactor = 1.0f;
@@ -491,24 +496,27 @@ void DrawFPS(int posX, int posY)
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
{
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
-
+
int charSpacing = 0;
int lineSpacing = 0;
int x = 0;
int y = 0;
- // We allocate a temporal arrays for chars data measures,
+ // Default number of characters expected supported
+ #define MAX_FONTCHARS 128
+
+ // We allocate a temporal arrays for chars data measures,
// once we get the actual number of chars, we copy data to a sized arrays
int tempCharValues[MAX_FONTCHARS];
Rectangle tempCharRecs[MAX_FONTCHARS];
-
+
Color *pixels = GetImageData(image);
// Parse image data to get charSpacing and lineSpacing
- for(y = 0; y < image.height; y++)
+ for (y = 0; y < image.height; y++)
{
- for(x = 0; x < image.width; x++)
+ for (x = 0; x < image.width; x++)
{
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
}
@@ -521,7 +529,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
int charHeight = 0;
int j = 0;
- while(!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
+ while (!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
charHeight = j;
@@ -531,20 +539,20 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
int xPosToRead = charSpacing;
// Parse image data to get rectangle sizes
- while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height)
+ while ((lineSpacing + lineToRead*(charHeight + lineSpacing)) < image.height)
{
- while((xPosToRead < image.width) &&
+ while ((xPosToRead < image.width) &&
!COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key))
{
tempCharValues[index] = firstChar + index;
-
+
tempCharRecs[index].x = xPosToRead;
- tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
+ tempCharRecs[index].y = lineSpacing + lineToRead*(charHeight + lineSpacing);
tempCharRecs[index].height = charHeight;
int charWidth = 0;
- while(!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++;
+ while (!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++;
tempCharRecs[index].width = charWidth;
@@ -556,14 +564,14 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
lineToRead++;
xPosToRead = charSpacing;
}
-
+
free(pixels);
-
+
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
-
+
// Create spritefont with all data parsed from image
SpriteFont spriteFont = { 0 };
-
+
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
spriteFont.numChars = index;
@@ -578,13 +586,15 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
{
spriteFont.charValues[i] = tempCharValues[i];
spriteFont.charRecs[i] = tempCharRecs[i];
-
+
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
spriteFont.charAdvanceX[i] = 0;
}
-
+
spriteFont.size = spriteFont.charRecs[0].height;
+
+ TraceLog(INFO, "Image file loaded correctly as SpriteFont");
return spriteFont;
}
@@ -623,7 +633,7 @@ static SpriteFont LoadRBMF(const char *fileName)
if (rbmfFile == NULL)
{
TraceLog(WARNING, "[%s] rBMF font file could not be opened, using default font", fileName);
-
+
spriteFont = GetDefaultFont();
}
else
@@ -634,15 +644,15 @@ static SpriteFont LoadRBMF(const char *fileName)
spriteFont.numChars = (int)rbmfHeader.numChars;
- int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32;
+ int numPixelBits = rbmfHeader.imgWidth*rbmfHeader.imgHeight/32;
- rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int));
+ rbmfFileData = (unsigned int *)malloc(numPixelBits*sizeof(unsigned int));
- for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
+ for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
- rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char));
+ rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars*sizeof(unsigned char));
- for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
+ for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
// Re-construct image from rbmfFileData
//-----------------------------------------
@@ -662,10 +672,10 @@ static SpriteFont LoadRBMF(const char *fileName)
counter++;
}
-
+
Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight);
ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
-
+
free(imagePixels);
TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
@@ -677,7 +687,7 @@ static SpriteFont LoadRBMF(const char *fileName)
//TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName);
// Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
- spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
+ spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle));
spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2));
spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int));
@@ -689,12 +699,12 @@ static SpriteFont LoadRBMF(const char *fileName)
for (int i = 0; i < spriteFont.numChars; i++)
{
spriteFont.charValues[i] = (int)rbmfHeader.firstChar + i;
-
+
spriteFont.charRecs[i].x = currentPosX;
- spriteFont.charRecs[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor);
+ spriteFont.charRecs[i].y = charsDivisor + currentLine*((int)rbmfHeader.charHeight + charsDivisor);
spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i];
spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight;
-
+
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
spriteFont.charAdvanceX[i] = 0;
@@ -704,15 +714,15 @@ static SpriteFont LoadRBMF(const char *fileName)
if (testPosX > spriteFont.texture.width)
{
currentLine++;
- currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i];
+ currentPosX = 2*charsDivisor + (int)rbmfCharWidthData[i];
testPosX = currentPosX;
spriteFont.charRecs[i].x = charsDivisor;
- spriteFont.charRecs[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor);
+ spriteFont.charRecs[i].y = charsDivisor + currentLine*(rbmfHeader.charHeight + charsDivisor);
}
else currentPosX = testPosX;
}
-
+
spriteFont.size = spriteFont.charRecs[0].height;
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
@@ -730,20 +740,20 @@ static SpriteFont LoadRBMF(const char *fileName)
static SpriteFont LoadBMFont(const char *fileName)
{
#define MAX_BUFFER_SIZE 256
-
+
SpriteFont font = { 0 };
font.texture.id = 0;
-
+
char buffer[MAX_BUFFER_SIZE];
char *searchPoint = NULL;
-
+
int fontSize = 0;
int texWidth, texHeight;
char texFileName[128];
int numChars = 0;
int base; // Useless data
-
+
FILE *fntFile;
fntFile = fopen(fileName, "rt");
@@ -758,42 +768,42 @@ static SpriteFont LoadBMFont(const char *fileName)
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
//searchPoint = strstr(buffer, "size");
//sscanf(searchPoint, "size=%i", &fontSize);
-
+
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
searchPoint = strstr(buffer, "lineHeight");
sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight);
-
+
TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize);
TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight);
-
+
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
searchPoint = strstr(buffer, "file");
sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName);
-
+
TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName);
-
+
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
searchPoint = strstr(buffer, "count");
sscanf(searchPoint, "count=%i", &numChars);
-
+
TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, numChars);
-
+
// Compose correct path using route of .fnt file (fileName) and texFileName
char *texPath = NULL;
char *lastSlash = NULL;
lastSlash = strrchr(fileName, '/');
-
+
// NOTE: We need some extra space to avoid memory corruption on next allocations!
texPath = malloc(strlen(fileName) - strlen(lastSlash) + strlen(texFileName) + 4);
-
+
// NOTE: strcat() and strncat() required a '\0' terminated string to work!
*texPath = '\0';
strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1);
strncat(texPath, texFileName, strlen(texFileName));
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
-
+
font.texture = LoadTexture(texPath);
font.size = fontSize;
font.numChars = numChars;
@@ -801,35 +811,35 @@ static SpriteFont LoadBMFont(const char *fileName)
font.charRecs = (Rectangle *)malloc(numChars*sizeof(Rectangle));
font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2));
font.charAdvanceX = (int *)malloc(numChars*sizeof(int));
-
+
free(texPath);
-
+
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
-
+
bool unorderedChars = false;
int firstChar = 0;
-
+
for (int i = 0; i < numChars; i++)
{
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);
-
+
if (i == 0) firstChar = charId;
else if (i != (charId - firstChar)) unorderedChars = true;
-
+
// Save data properly in sprite font
font.charValues[i] = charId;
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
font.charOffsets[i] = (Vector2){ (float)charOffsetX, (float)charOffsetY };
font.charAdvanceX[i] = charAdvanceX;
}
-
+
fclose(fntFile);
-
+
if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
-
+
// NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
{
@@ -843,22 +853,20 @@ static SpriteFont LoadBMFont(const char *fileName)
// Generate a sprite font from TTF file data (font size required)
// TODO: Review texture packing method and generation (use oversampling)
-static SpriteFont LoadTTF(const char *fileName, int fontSize)
+static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int numChars)
{
// NOTE: Generated font uses some hardcoded values
#define FONT_TEXTURE_WIDTH 512 // Font texture width
#define FONT_TEXTURE_HEIGHT 512 // Font texture height
- #define FONT_FIRST_CHAR 32 // Font first character (32 - space)
- #define FONT_NUM_CHARS 95 // ASCII 32..126 is 95 glyphs
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
unsigned char *dataBitmap = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)); // One channel bitmap returned!
- stbtt_bakedchar charData[FONT_NUM_CHARS]; // ASCII 32..126 is 95 glyphs
+ stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars);
SpriteFont font = { 0 };
-
+
FILE *ttfFile = fopen(fileName, "rb");
-
+
if (ttfFile == NULL)
{
TraceLog(WARNING, "[%s] FNT file could not be opened", fileName);
@@ -868,14 +876,14 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
fread(ttfBuffer, 1, 1<<25, ttfFile);
// NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image...
- stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, FONT_FIRST_CHAR, FONT_NUM_CHARS, charData);
+ stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, firstChar, numChars, charData);
free(ttfBuffer);
-
+
// Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA
unsigned char *dataGrayAlpha = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)*2); // Two channels
int k = 0;
-
+
for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++)
{
dataGrayAlpha[k] = 255;
@@ -883,9 +891,9 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
k += 2;
}
-
+
free(dataBitmap);
-
+
// Sprite font generation from TTF extracted data
Image image;
image.width = FONT_TEXTURE_WIDTH;
@@ -898,24 +906,26 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
UnloadImage(image); // Unloads dataGrayAlpha
font.size = fontSize;
- font.numChars = FONT_NUM_CHARS;
+ font.numChars = numChars;
font.charValues = (int *)malloc(font.numChars*sizeof(int));
font.charRecs = (Rectangle *)malloc(font.numChars*sizeof(Rectangle));
font.charOffsets = (Vector2 *)malloc(font.numChars*sizeof(Vector2));
font.charAdvanceX = (int *)malloc(font.numChars*sizeof(int));
-
+
for (int i = 0; i < font.numChars; i++)
{
- font.charValues[i] = i + FONT_FIRST_CHAR;
+ font.charValues[i] = i + firstChar;
font.charRecs[i].x = (int)charData[i].x0;
font.charRecs[i].y = (int)charData[i].y0;
font.charRecs[i].width = (int)charData[i].x1 - (int)charData[i].x0;
font.charRecs[i].height = (int)charData[i].y1 - (int)charData[i].y0;
-
+
font.charOffsets[i] = (Vector2){ charData[i].xoff, charData[i].yoff };
font.charAdvanceX[i] = (int)charData[i].xadvance;
}
+ free(charData);
+
return font;
} \ No newline at end of file