summaryrefslogtreecommitdiffhomepage
path: root/src/text.c
diff options
context:
space:
mode:
authorraysan5 <[email protected]>2016-10-31 15:38:15 +0100
committerraysan5 <[email protected]>2016-10-31 15:38:15 +0100
commitcc917fbac6e7007fdb744afaf8f0879c984d95af (patch)
tree373b0a2681a12e894a0a492fdd5113b6b702d969 /src/text.c
parent16101ce3d8c601447f935056b09a36ea3afefe7d (diff)
downloadraylib-cc917fbac6e7007fdb744afaf8f0879c984d95af.tar.gz
raylib-cc917fbac6e7007fdb744afaf8f0879c984d95af.zip
Improve SpriteFont support
LoadSpriteFontTTF() - TTF font loading with custom parameters
Diffstat (limited to 'src/text.c')
-rw-r--r--src/text.c74
1 files changed, 53 insertions, 21 deletions
diff --git a/src/text.c b/src/text.c
index 5e978823..7707db7c 100644
--- a/src/text.c
+++ b/src/text.c
@@ -33,6 +33,7 @@
#include "utils.h" // Required for: GetExtension()
// Following libs are used on LoadTTF()
+//#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION
#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
@@ -268,20 +269,35 @@ SpriteFont LoadSpriteFont(const char *fileName)
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
spriteFont = GetDefaultFont();
}
+ else SetTextureFilter(spriteFont.texture, FILTER_BILINEAR);
return spriteFont;
}
-// Generate SpriteFont from TTF file
+// Load SpriteFont from TTF file with custom 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
-SpriteFont GenSpriteFont(const char *fileName, int fontSize, int *fontChars)
+SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
{
SpriteFont spriteFont = { 0 };
if (strcmp(GetExtension(fileName),"ttf") == 0)
{
- spriteFont = LoadTTF(fileName, fontSize, FONT_FIRST_CHAR, DEFAULT_TTF_NUMCHARS);
+ int firstChar = 0;
+ int totalChars = 0;
+
+ if ((fontChars == NULL) || (numChars == 0))
+ {
+ firstChar = 32; // Default first character: SPACE[32]
+ totalChars = 95; // Default charset [32..126]
+ }
+ else
+ {
+ firstChar = fontChars[0];
+ totalChars = numChars;
+ }
+
+ spriteFont = LoadTTF(fileName, fontSize, firstChar, totalChars);
}
if (spriteFont.texture.id == 0)
@@ -522,7 +538,7 @@ void DrawFPS(int posX, int posY)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
-// Load a Image font file (XNA style)
+// Load an Image font file (XNA style)
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))
@@ -595,15 +611,24 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
xPosToRead = charSpacing;
}
- free(pixels);
-
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
+
+ // NOTE: We need to remove key color borders from image to avoid weird
+ // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR
+ for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK;
+
+ // Create a new image with the processed color data (key color replaced by BLANK)
+ Image fontClear = LoadImageEx(pixels, image.width, image.height);
+
+ free(pixels); // Free pixels array memory
// Create spritefont with all data parsed from image
SpriteFont spriteFont = { 0 };
- spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
+ spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
spriteFont.numChars = index;
+
+ UnloadImage(fontClear); // Unload processed image once converted to texture
// We got tempCharValues and tempCharsRecs populated with chars data
// Now we move temp data to sized charValues and charRecs arrays
@@ -900,12 +925,15 @@ static SpriteFont LoadBMFont(const char *fileName)
// TODO: Review texture packing method and generation (use oversampling)
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
+ // NOTE: Font texture size is predicted (being as much conservative as possible)
+ // Predictive method consist of supposing same number of chars by line-column (sqrtf)
+ // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests...
+ int textureSize = GetNextPOT(ceil((float)fontSize*3/4)*ceil(sqrtf((float)numChars)));
+
+ TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
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!
+ unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars);
SpriteFont font = { 0 };
@@ -914,40 +942,44 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int
if (ttfFile == NULL)
{
- TraceLog(WARNING, "[%s] FNT file could not be opened", fileName);
+ TraceLog(WARNING, "[%s] TTF file could not be opened", fileName);
return font;
}
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, firstChar, numChars, charData);
+ // TODO: Replace this function by a proper packing method and support random chars order
+ int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, firstChar, numChars, charData);
+ //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
+ if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font");
+
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;
+ unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
- for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++)
+ for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2)
{
dataGrayAlpha[k] = 255;
dataGrayAlpha[k + 1] = dataBitmap[i];
-
- k += 2;
}
free(dataBitmap);
// Sprite font generation from TTF extracted data
Image image;
- image.width = FONT_TEXTURE_WIDTH;
- image.height = FONT_TEXTURE_HEIGHT;
+ image.width = textureSize;
+ image.height = textureSize;
image.mipmaps = 1;
image.format = UNCOMPRESSED_GRAY_ALPHA;
image.data = dataGrayAlpha;
-
+
font.texture = LoadTextureFromImage(image);
+
+ //WritePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2);
+
UnloadImage(image); // Unloads dataGrayAlpha
font.size = fontSize;