summaryrefslogtreecommitdiffhomepage
path: root/src/text.c
diff options
context:
space:
mode:
authorMurray Campbell <[email protected]>2018-10-24 14:33:53 -0500
committerGitHub <[email protected]>2018-10-24 14:33:53 -0500
commit03fb5499a0f2c4b45ed1b2655a6e1e77221ed46a (patch)
tree346e60c85c667b4e7650b7d3cd1c7ee3c8a54be5 /src/text.c
parent9c6a98aa61b0a43c0d85347b3da26f90dd5c42fc (diff)
parent72431c6c36a166b00e52527962ab4d978ab0111d (diff)
downloadraylib-03fb5499a0f2c4b45ed1b2655a6e1e77221ed46a.tar.gz
raylib-03fb5499a0f2c4b45ed1b2655a6e1e77221ed46a.zip
Merge pull request #7 from raysan5/master
pull
Diffstat (limited to 'src/text.c')
-rw-r--r--src/text.c325
1 files changed, 183 insertions, 142 deletions
diff --git a/src/text.c b/src/text.c
index 3dbb261b..a010666e 100644
--- a/src/text.c
+++ b/src/text.c
@@ -276,15 +276,7 @@ Font LoadFont(const char *fileName)
Font font = { 0 };
#if defined(SUPPORT_FILEFORMAT_TTF)
- if (IsFileExtension(fileName, ".ttf"))
- {
- font.baseSize = DEFAULT_TTF_FONTSIZE;
- font.charsCount = DEFAULT_TTF_NUMCHARS;
- font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, FONT_DEFAULT);
- Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0);
- font.texture = LoadTextureFromImage(atlas);
- UnloadImage(atlas);
- }
+ if (IsFileExtension(fileName, ".ttf")) font = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, DEFAULT_TTF_NUMCHARS, NULL);
else
#endif
#if defined(SUPPORT_FILEFORMAT_FNT)
@@ -317,9 +309,14 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
font.baseSize = fontSize;
font.charsCount = (charsCount > 0) ? charsCount : 95;
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
- Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
- font.texture = LoadTextureFromImage(atlas);
- UnloadImage(atlas);
+
+ if (font.chars != NULL)
+ {
+ Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
+ font.texture = LoadTextureFromImage(atlas);
+ UnloadImage(atlas);
+ }
+ else font = GetFontDefault();
return font;
}
@@ -335,91 +332,97 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
#define SDF_PIXEL_DIST_SCALE 64.0f
#define BITMAP_ALPHA_THRESHOLD 80
-
- // In case no chars count provided, default to 95
- charsCount = (charsCount > 0) ? charsCount : 95;
-
- CharInfo *chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo));
-
+
+ CharInfo *chars = NULL;
+
// Load font data (including pixel data) from TTF file
// NOTE: Loaded information should be enough to generate font image atlas,
// using any packaging method
FILE *fontFile = fopen(fileName, "rb"); // Load font file
- fseek(fontFile, 0, SEEK_END);
- long size = ftell(fontFile); // Get file size
- fseek(fontFile, 0, SEEK_SET); // Reset file pointer
-
- unsigned char *fontBuffer = (unsigned char *)malloc(size);
-
- fread(fontBuffer, size, 1, fontFile);
- fclose(fontFile);
-
- // Init font for data reading
- stbtt_fontinfo fontInfo;
- if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!");
+ if (fontFile != NULL)
+ {
+ fseek(fontFile, 0, SEEK_END);
+ long size = ftell(fontFile); // Get file size
+ fseek(fontFile, 0, SEEK_SET); // Reset file pointer
+
+ unsigned char *fontBuffer = (unsigned char *)malloc(size);
+
+ fread(fontBuffer, size, 1, fontFile);
+ fclose(fontFile);
- // Calculate font scale factor
- float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
+ // Init font for data reading
+ stbtt_fontinfo fontInfo;
+ if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!");
- // Calculate font basic metrics
- // NOTE: ascent is equivalent to font baseline
- int ascent, descent, lineGap;
- stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
-
- // Fill fontChars in case not provided externally
- // NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
- int genFontChars = false;
- if (fontChars == NULL) genFontChars = true;
- if (genFontChars)
- {
- fontChars = (int *)malloc(charsCount*sizeof(int));
- for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
- }
-
- // NOTE: Using simple packaging, one char after another
- for (int i = 0; i < charsCount; i++)
- {
- int chw = 0, chh = 0; // Character width and height (on generation)
- int ch = fontChars[i]; // Character value to get info for
- chars[i].value = ch;
+ // Calculate font scale factor
+ float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
+
+ // Calculate font basic metrics
+ // NOTE: ascent is equivalent to font baseline
+ int ascent, descent, lineGap;
+ stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
- // Render a unicode codepoint to a bitmap
- // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
- // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
- // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
+ // In case no chars count provided, default to 95
+ charsCount = (charsCount > 0) ? charsCount : 95;
- if (type != FONT_SDF) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
- else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+ // Fill fontChars in case not provided externally
+ // NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
+ int genFontChars = false;
+ if (fontChars == NULL)
+ {
+ fontChars = (int *)malloc(charsCount*sizeof(int));
+ for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32;
+ genFontChars = true;
+ }
+
+ chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo));
- if (type == FONT_BITMAP)
+ // NOTE: Using simple packaging, one char after another
+ for (int i = 0; i < charsCount; i++)
{
- // Aliased bitmap (black & white) font generation, avoiding anti-aliasing
- // NOTE: For optimum results, bitmap font should be generated at base pixel size
- for (int p = 0; p < chw*chh; p++)
+ int chw = 0, chh = 0; // Character width and height (on generation)
+ int ch = fontChars[i]; // Character value to get info for
+ chars[i].value = ch;
+
+ // Render a unicode codepoint to a bitmap
+ // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
+ // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
+ // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
+
+ if (type != FONT_SDF) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+ else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+
+ if (type == FONT_BITMAP)
{
- if (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
- else chars[i].data[p] = 255;
+ // Aliased bitmap (black & white) font generation, avoiding anti-aliasing
+ // NOTE: For optimum results, bitmap font should be generated at base pixel size
+ for (int p = 0; p < chw*chh; p++)
+ {
+ if (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
+ else chars[i].data[p] = 255;
+ }
}
- }
-
- chars[i].rec.width = (float)chw;
- chars[i].rec.height = (float)chh;
- chars[i].offsetY += (int)((float)ascent*scaleFactor);
-
- // Get bounding box for character (may be offset to account for chars that dip above or below the line)
- int chX1, chY1, chX2, chY2;
- stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
+
+ chars[i].rec.width = (float)chw;
+ chars[i].rec.height = (float)chh;
+ chars[i].offsetY += (int)((float)ascent*scaleFactor);
- TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
- TraceLog(LOG_DEBUG, "Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
+ // Get bounding box for character (may be offset to account for chars that dip above or below the line)
+ int chX1, chY1, chX2, chY2;
+ stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
+
+ TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
+ TraceLog(LOG_DEBUG, "Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
- stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
- chars[i].advanceX *= scaleFactor;
+ stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
+ chars[i].advanceX *= scaleFactor;
+ }
+
+ free(fontBuffer);
+ if (genFontChars) free(fontChars);
}
-
- free(fontBuffer);
- if (genFontChars) free(fontChars);
+ else TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName);
return chars;
}
@@ -527,6 +530,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
else TraceLog(LOG_WARNING, "Character could not be packed: %i", i);
}
+ free(rects);
free(nodes);
free(context);
}
@@ -563,6 +567,28 @@ void UnloadFont(Font font)
}
}
+// Shows current FPS on top-left corner
+// NOTE: Uses default font
+void DrawFPS(int posX, int posY)
+{
+ // NOTE: We are rendering fps every second for better viewing on high framerates
+
+ static int fps = 0;
+ static int counter = 0;
+ static int refreshRate = 20;
+
+ if (counter < refreshRate) counter++;
+ else
+ {
+ fps = GetFPS();
+ refreshRate = fps;
+ counter = 0;
+ }
+
+ // NOTE: We have rounding errors every frame, so it oscillates a lot
+ DrawText(FormatText("%2i FPS", fps), posX, posY, 20, LIME);
+}
+
// Draw text (using default font)
// NOTE: fontSize work like in any drawing program but if fontSize is lower than font-base-size, then font-base-size is used
// NOTE: chars spacing is proportional to fontSize
@@ -588,10 +614,10 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
int length = strlen(text);
int textOffsetX = 0; // Offset between characters
int textOffsetY = 0; // Required for line break!
- float scaleFactor;
+ float scaleFactor = 0.0f;
- unsigned char letter; // Current character
- int index; // Index position in sprite font
+ unsigned char letter = 0; // Current character
+ int index = 0; // Index position in sprite font
scaleFactor = fontSize/font.baseSize;
@@ -639,44 +665,6 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
}
}
-// Formatting of text with variables to 'embed'
-const char *FormatText(const char *text, ...)
-{
- static char buffer[MAX_FORMATTEXT_LENGTH];
-
- va_list args;
- va_start(args, text);
- vsprintf(buffer, text, args);
- va_end(args);
-
- return buffer;
-}
-
-// Get a piece of a text string
-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);
- text++;
- }
-
- *(buffer + length) = '\0';
-
- return buffer;
-}
-
// Measure string width for default font
int MeasureText(const char *text, int fontSize)
{
@@ -702,8 +690,8 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
int tempLen = 0; // Used to count longer text line num chars
int lenCounter = 0;
- float textWidth = 0;
- float tempTextWidth = 0; // Used to count longer text line width
+ float textWidth = 0.0f;
+ float tempTextWidth = 0.0f; // Used to count longer text line width
float textHeight = (float)font.baseSize;
float scaleFactor = fontSize/(float)font.baseSize;
@@ -761,26 +749,78 @@ int GetGlyphIndex(Font font, int character)
#endif
}
-// Shows current FPS on top-left corner
-// NOTE: Uses default font
-void DrawFPS(int posX, int posY)
+// Formatting of text with variables to 'embed'
+const char *FormatText(const char *text, ...)
{
- // NOTE: We are rendering fps every second for better viewing on high framerates
+ static char buffer[MAX_FORMATTEXT_LENGTH];
- static int fps = 0;
- static int counter = 0;
- static int refreshRate = 20;
+ va_list args;
+ va_start(args, text);
+ vsprintf(buffer, text, args);
+ va_end(args);
- if (counter < refreshRate) counter++;
- else
+ return buffer;
+}
+
+// Get a piece of a text string
+const char *SubText(const char *text, int position, int length)
+{
+ static char buffer[MAX_SUBTEXT_LENGTH] = { 0 };
+ int textLength = strlen(text);
+
+ if (position >= textLength)
{
- fps = GetFPS();
- refreshRate = fps;
- counter = 0;
+ position = textLength - 1;
+ length = 0;
+ }
+
+ if (length >= textLength) length = textLength;
+
+ for (int c = 0 ; c < length ; c++)
+ {
+ *(buffer + c) = *(text + position);
+ text++;
+ }
+
+ *(buffer + length) = '\0';
+
+ return buffer;
+}
+
+// Split string into multiple strings
+// NOTE: Files count is returned by parameters pointer
+// NOTE: Allocated memory should be manually freed
+char **SplitText(char *text, char delimiter, int *strCount)
+{
+ #define MAX_SUBSTRING_LENGTH 128
+
+ char **strings = NULL;
+ int len = strlen(text);
+ char *strDup = (char *)malloc(len + 1);
+ strcpy(strDup, text);
+ int counter = 1;
+
+ // Count how many substrings we have on string
+ for (int i = 0; i < len; i++) if (text[i] == delimiter) counter++;
+
+ // Memory allocation for substrings
+ strings = (char **)malloc(sizeof(char *)*counter);
+ for (int i = 0; i < counter; i++) strings[i] = (char *)malloc(sizeof(char)*MAX_SUBSTRING_LENGTH);
+
+ char *substrPtr = NULL;
+ char delimiters[1] = { delimiter }; // Only caring for one delimiter
+ substrPtr = strtok(strDup, delimiters);
+
+ for (int i = 0; (i < counter) && (substrPtr != NULL); i++)
+ {
+ strcpy(strings[i], substrPtr);
+ substrPtr = strtok(NULL, delimiters);
}
- // NOTE: We have rounding errors every frame, so it oscillates a lot
- DrawText(FormatText("%2i FPS", fps), posX, posY, 20, LIME);
+ *strCount = counter;
+ free(strDup);
+
+ return strings;
}
//----------------------------------------------------------------------------------
@@ -911,17 +951,18 @@ static Font LoadBMFont(const char *fileName)
Font font = { 0 };
font.texture.id = 0;
- char buffer[MAX_BUFFER_SIZE];
+ char buffer[MAX_BUFFER_SIZE] = { 0 };
char *searchPoint = NULL;
int fontSize = 0;
- int texWidth, texHeight;
+ int texWidth = 0;
+ int texHeight = 0;
char texFileName[129];
int charsCount = 0;
- int base; // Useless data
+ int base = 0; // Useless data
- FILE *fntFile;
+ FILE *fntFile = NULL;
fntFile = fopen(fileName, "rt");