diff options
| author | Murray Campbell <[email protected]> | 2018-10-24 14:33:53 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2018-10-24 14:33:53 -0500 |
| commit | 03fb5499a0f2c4b45ed1b2655a6e1e77221ed46a (patch) | |
| tree | 346e60c85c667b4e7650b7d3cd1c7ee3c8a54be5 /src/text.c | |
| parent | 9c6a98aa61b0a43c0d85347b3da26f90dd5c42fc (diff) | |
| parent | 72431c6c36a166b00e52527962ab4d978ab0111d (diff) | |
| download | raylib-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.c | 325 |
1 files changed, 183 insertions, 142 deletions
@@ -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"); |
