Update C sources
This commit is contained in:
parent
2a66186c7d
commit
1868520849
27 changed files with 4582 additions and 2234 deletions
662
raylib/rtext.c
662
raylib/rtext.c
|
@ -12,6 +12,7 @@
|
|||
*
|
||||
* #define SUPPORT_FILEFORMAT_FNT
|
||||
* #define SUPPORT_FILEFORMAT_TTF
|
||||
* #define SUPPORT_FILEFORMAT_BDF
|
||||
* 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
|
||||
*
|
||||
|
@ -33,7 +34,7 @@
|
|||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2024 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.
|
||||
|
@ -70,14 +71,27 @@
|
|||
#include <stdarg.h> // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
|
||||
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
|
||||
#if defined(__GNUC__) // GCC and Clang
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
||||
#include "external/stb_rect_pack.h" // Required for: ttf/bdf font rectangles packaging
|
||||
|
||||
#include <math.h> // Required for: ttf/bdf font rectangles packaging
|
||||
|
||||
#if defined(__GNUC__) // GCC and Clang
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
#if defined(__GNUC__) // GCC and Clang
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#define STBTT_STATIC
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
|
@ -105,7 +119,7 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// ...
|
||||
//...
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global variables
|
||||
|
@ -127,7 +141,10 @@ static Font defaultFont = { 0 };
|
|||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||
#endif
|
||||
static int textLineSpacing = 15; // Text vertical line spacing in pixels
|
||||
#if defined(SUPPORT_FILEFORMAT_BDF)
|
||||
static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, int *codepoints, int codepointCount, int *outFontSize);
|
||||
#endif
|
||||
static int textLineSpacing = 2; // Text vertical line spacing in pixels (between lines)
|
||||
|
||||
#if defined(SUPPORT_DEFAULT_FONT)
|
||||
extern void LoadFontDefault(void);
|
||||
|
@ -334,6 +351,10 @@ Font LoadFont(const char *fileName)
|
|||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
if (IsFileExtension(fileName, ".fnt")) font = LoadBMFont(fileName);
|
||||
else
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_BDF)
|
||||
if (IsFileExtension(fileName, ".bdf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Image image = LoadImage(fileName);
|
||||
|
@ -355,7 +376,7 @@ Font LoadFont(const char *fileName)
|
|||
return font;
|
||||
}
|
||||
|
||||
// Load Font from TTF font file with generation parameters
|
||||
// Load Font from TTF or BDF font file with generation 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
|
||||
Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount)
|
||||
|
@ -413,7 +434,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
|||
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||
}
|
||||
|
||||
if ((x == 0) || (y == 0)) return font;
|
||||
if ((x == 0) || (y == 0)) return font; // Security check
|
||||
|
||||
charSpacing = x;
|
||||
lineSpacing = y;
|
||||
|
@ -509,37 +530,51 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||
Font font = { 0 };
|
||||
|
||||
char fileExtLower[16] = { 0 };
|
||||
strcpy(fileExtLower, TextToLower(fileType));
|
||||
strncpy(fileExtLower, TextToLower(fileType), 16 - 1);
|
||||
|
||||
font.baseSize = fontSize;
|
||||
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
|
||||
font.glyphPadding = 0;
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
if (TextIsEqual(fileExtLower, ".ttf") ||
|
||||
TextIsEqual(fileExtLower, ".otf"))
|
||||
{
|
||||
font.baseSize = fontSize;
|
||||
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
|
||||
font.glyphPadding = 0;
|
||||
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
|
||||
|
||||
if (font.glyphs != NULL)
|
||||
{
|
||||
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
|
||||
|
||||
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
|
||||
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
UnloadImage(font.glyphs[i].image);
|
||||
font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
|
||||
}
|
||||
|
||||
UnloadImage(atlas);
|
||||
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
|
||||
}
|
||||
else font = GetFontDefault();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_BDF)
|
||||
if (TextIsEqual(fileExtLower, ".bdf"))
|
||||
{
|
||||
font.glyphs = LoadFontDataBDF(fileData, dataSize, codepoints, font.glyphCount, &font.baseSize);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
font.glyphs = NULL;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
|
||||
if (font.glyphs != NULL)
|
||||
{
|
||||
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
|
||||
|
||||
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
|
||||
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
UnloadImage(font.glyphs[i].image);
|
||||
font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
|
||||
}
|
||||
|
||||
UnloadImage(atlas);
|
||||
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
|
||||
}
|
||||
else font = GetFontDefault();
|
||||
#else
|
||||
font = GetFontDefault();
|
||||
#endif
|
||||
|
@ -604,7 +639,6 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||
|
||||
// Fill fontChars in case not provided externally
|
||||
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
||||
|
||||
if (codepoints == NULL)
|
||||
{
|
||||
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||
|
@ -612,7 +646,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||
genFontChars = true;
|
||||
}
|
||||
|
||||
chars = (GlyphInfo *)RL_MALLOC(codepointCount*sizeof(GlyphInfo));
|
||||
chars = (GlyphInfo *)RL_CALLOC(codepointCount, sizeof(GlyphInfo));
|
||||
|
||||
// NOTE: Using simple packaging, one char after another
|
||||
for (int i = 0; i < codepointCount; i++)
|
||||
|
@ -626,54 +660,67 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
|
||||
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
|
||||
|
||||
if (type != FONT_SDF) chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
else chars[i].image.data = NULL;
|
||||
// Check if a glyph is available in the font
|
||||
// WARNING: if (index == 0), glyph not found, it could fallback to default .notdef glyph (if defined in font)
|
||||
int index = stbtt_FindGlyphIndex(&fontInfo, ch);
|
||||
|
||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
|
||||
|
||||
// Load characters images
|
||||
chars[i].image.width = chw;
|
||||
chars[i].image.height = chh;
|
||||
chars[i].image.mipmaps = 1;
|
||||
chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
|
||||
chars[i].offsetY += (int)((float)ascent*scaleFactor);
|
||||
|
||||
// NOTE: We create an empty image for space character, it could be further required for atlas packing
|
||||
if (ch == 32)
|
||||
if (index > 0)
|
||||
{
|
||||
Image imSpace = {
|
||||
.data = RL_CALLOC(chars[i].advanceX*fontSize, 2),
|
||||
.width = chars[i].advanceX,
|
||||
.height = fontSize,
|
||||
.mipmaps = 1,
|
||||
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
|
||||
};
|
||||
|
||||
chars[i].image = imSpace;
|
||||
}
|
||||
|
||||
if (type == FONT_BITMAP)
|
||||
{
|
||||
// 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++)
|
||||
switch (type)
|
||||
{
|
||||
if (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0;
|
||||
else ((unsigned char *)chars[i].image.data)[p] = 255;
|
||||
case FONT_DEFAULT:
|
||||
case FONT_BITMAP: chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break;
|
||||
case FONT_SDF: if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (chars[i].image.data != NULL) // Glyph data has been found in the font
|
||||
{
|
||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
|
||||
|
||||
// Load characters images
|
||||
chars[i].image.width = chw;
|
||||
chars[i].image.height = chh;
|
||||
chars[i].image.mipmaps = 1;
|
||||
chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
|
||||
chars[i].offsetY += (int)((float)ascent*scaleFactor);
|
||||
}
|
||||
|
||||
// NOTE: We create an empty image for space character,
|
||||
// it could be further required for atlas packing
|
||||
if (ch == 32)
|
||||
{
|
||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
|
||||
|
||||
Image imSpace = {
|
||||
.data = RL_CALLOC(chars[i].advanceX*fontSize, 2),
|
||||
.width = chars[i].advanceX,
|
||||
.height = fontSize,
|
||||
.mipmaps = 1,
|
||||
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
|
||||
};
|
||||
|
||||
chars[i].image = imSpace;
|
||||
}
|
||||
|
||||
if (type == FONT_BITMAP)
|
||||
{
|
||||
// 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 (((unsigned char *)chars[i].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0;
|
||||
else ((unsigned char *)chars[i].image.data)[p] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get bounding box for character (maybe 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);
|
||||
|
||||
TRACELOGD("FONT: Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
|
||||
TRACELOGD("FONT: Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
|
||||
*/
|
||||
else
|
||||
{
|
||||
// TODO: Use some fallback glyph for codepoints not found in the font
|
||||
}
|
||||
}
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
|
||||
|
@ -687,7 +734,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
|
|||
|
||||
// Generate image font atlas using chars info
|
||||
// NOTE: Packing method: 0-Default, 1-Skyline
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
|
||||
Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod)
|
||||
{
|
||||
Image atlas = { 0 };
|
||||
|
@ -713,7 +760,7 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
|
|||
for (int i = 0; i < glyphCount; i++)
|
||||
{
|
||||
if (glyphs[i].image.width > maxGlyphWidth) maxGlyphWidth = glyphs[i].image.width;
|
||||
totalWidth += glyphs[i].image.width + 4*padding;
|
||||
totalWidth += glyphs[i].image.width + 2*padding;
|
||||
}
|
||||
|
||||
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
|
||||
|
@ -731,8 +778,9 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
|
|||
atlas.width = imageSize; // Atlas bitmap width
|
||||
atlas.height = imageSize; // Atlas bitmap height
|
||||
#else
|
||||
int paddedFontSize = fontSize + 2*padding;
|
||||
// No need for a so-conservative atlas generation
|
||||
float totalArea = totalWidth*fontSize*1.2f;
|
||||
float totalArea = totalWidth*paddedFontSize*1.2f;
|
||||
float imageMinSize = sqrtf(totalArea);
|
||||
int imageSize = (int)powf(2, ceilf(logf(imageMinSize)/logf(2)));
|
||||
|
||||
|
@ -775,10 +823,10 @@ Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyp
|
|||
|
||||
if (offsetY > (atlas.height - fontSize - padding))
|
||||
{
|
||||
for(int j = i + 1; j < glyphCount; j++)
|
||||
for (int j = i + 1; j < glyphCount; j++)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FONT: Failed to package character (%i)", j);
|
||||
// make sure remaining recs contain valid data
|
||||
// Make sure remaining recs contain valid data
|
||||
recs[j].x = 0;
|
||||
recs[j].y = 0;
|
||||
recs[j].width = 0;
|
||||
|
@ -923,7 +971,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
|
||||
// Get file name from path
|
||||
char fileNamePascal[256] = { 0 };
|
||||
strcpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)));
|
||||
strncpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)), 256 - 1);
|
||||
|
||||
// NOTE: Text data buffer size is estimated considering image data size in bytes
|
||||
// and requiring 6 char bytes for every byte: "0x00, "
|
||||
|
@ -937,7 +985,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2023 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2024 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// ---------------------------------------------------------------------------------- //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
|
@ -1029,7 +1077,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
#endif
|
||||
// We have two possible mechanisms to assign font.recs and font.glyphs data,
|
||||
// that data is already available as global arrays, we two options to assign that data:
|
||||
// - 1. Data copy. This option consumes more memory and Font MUST be unloaded by user, requiring additional code.
|
||||
// - 1. Data copy. This option consumes more memory and Font MUST be unloaded by user, requiring additional code
|
||||
// - 2. Data assignment. This option consumes less memory and Font MUST NOT be unloaded by user because data is on protected DATA segment
|
||||
//#define SUPPORT_FONT_DATA_COPY
|
||||
#if defined(SUPPORT_FONT_DATA_COPY)
|
||||
|
@ -1064,7 +1112,6 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
return success;
|
||||
}
|
||||
|
||||
|
||||
// Draw current FPS
|
||||
// NOTE: Uses default font
|
||||
void DrawFPS(int posX, int posY)
|
||||
|
@ -1104,7 +1151,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
|||
|
||||
int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||
float textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||
|
@ -1119,7 +1166,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
|||
if (codepoint == '\n')
|
||||
{
|
||||
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||
textOffsetY += textLineSpacing;
|
||||
textOffsetY += (fontSize + textLineSpacing);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
|
@ -1178,7 +1225,7 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
|||
// Draw multiple character (codepoints)
|
||||
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
|
||||
{
|
||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||
float textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||
|
@ -1190,7 +1237,7 @@ void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Ve
|
|||
if (codepoints[i] == '\n')
|
||||
{
|
||||
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||
textOffsetY += textLineSpacing;
|
||||
textOffsetY += (fontSize + textLineSpacing);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
|
@ -1235,7 +1282,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
{
|
||||
Vector2 textSize = { 0 };
|
||||
|
||||
if ((font.texture.id == 0) || (text == NULL)) return textSize;
|
||||
if ((font.texture.id == 0) || (text == NULL)) return textSize; // Security check
|
||||
|
||||
int size = TextLength(text); // Get size in bytes of text
|
||||
int tempByteCounter = 0; // Used to count longer text line num chars
|
||||
|
@ -1244,7 +1291,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
float textWidth = 0.0f;
|
||||
float tempTextWidth = 0.0f; // Used to count longer text line width
|
||||
|
||||
float textHeight = (float)font.baseSize;
|
||||
float textHeight = fontSize;
|
||||
float scaleFactor = fontSize/(float)font.baseSize;
|
||||
|
||||
int letter = 0; // Current character
|
||||
|
@ -1272,7 +1319,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
textWidth = 0;
|
||||
|
||||
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||
textHeight += (float)textLineSpacing;
|
||||
textHeight += (fontSize + textLineSpacing);
|
||||
}
|
||||
|
||||
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
||||
|
@ -1281,7 +1328,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing);
|
||||
textSize.y = textHeight*scaleFactor;
|
||||
textSize.y = textHeight;
|
||||
|
||||
return textSize;
|
||||
}
|
||||
|
@ -1390,7 +1437,6 @@ const char *TextFormat(const char *text, ...)
|
|||
return currentBuffer;
|
||||
}
|
||||
|
||||
|
||||
// Get integer value from text
|
||||
// NOTE: This function replaces atoi() [stdlib.h]
|
||||
int TextToInteger(const char *text)
|
||||
|
@ -1409,6 +1455,37 @@ int TextToInteger(const char *text)
|
|||
return value*sign;
|
||||
}
|
||||
|
||||
// Get float value from text
|
||||
// NOTE: This function replaces atof() [stdlib.h]
|
||||
// WARNING: Only '.' character is understood as decimal point
|
||||
float TextToFloat(const char *text)
|
||||
{
|
||||
float value = 0.0f;
|
||||
float sign = 1.0f;
|
||||
|
||||
if ((text[0] == '+') || (text[0] == '-'))
|
||||
{
|
||||
if (text[0] == '-') sign = -1.0f;
|
||||
text++;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
|
||||
|
||||
if (text[i++] != '.') value *= sign;
|
||||
else
|
||||
{
|
||||
float divisor = 10.0f;
|
||||
for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
|
||||
{
|
||||
value += ((float)(text[i] - '0'))/divisor;
|
||||
divisor = divisor*10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_TEXT_MANIPULATION)
|
||||
// Copy one string to another, returns bytes copied
|
||||
int TextCopy(char *dst, const char *src)
|
||||
|
@ -1480,7 +1557,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
// Replace text string
|
||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplace(char *text, const char *replace, const char *by)
|
||||
char *TextReplace(const char *text, const char *replace, const char *by)
|
||||
{
|
||||
// Sanity checks and initialization
|
||||
if (!text || !replace || !by) return NULL;
|
||||
|
@ -1500,7 +1577,7 @@ char *TextReplace(char *text, const char *replace, const char *by)
|
|||
byLen = TextLength(by);
|
||||
|
||||
// Count the number of replacements needed
|
||||
insertPoint = text;
|
||||
insertPoint = (char*)text;
|
||||
for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen;
|
||||
|
||||
// Allocate returning string and point temp to it
|
||||
|
@ -1620,7 +1697,8 @@ const char **TextSplit(const char *text, char delimiter, int *count)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Append text at specific position and move cursor!
|
||||
// Append text at specific position and move cursor
|
||||
// WARNING: It's up to the user to make sure appended text does not overflow the buffer!
|
||||
// REQUIRES: strcpy()
|
||||
void TextAppend(char *text, const char *append, int *position)
|
||||
{
|
||||
|
@ -1951,21 +2029,21 @@ int GetCodepointNext(const char *text, int *codepointSize)
|
|||
if (0xf0 == (0xf8 & ptr[0]))
|
||||
{
|
||||
// 4 byte UTF-8 codepoint
|
||||
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
|
||||
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
|
||||
*codepointSize = 4;
|
||||
}
|
||||
else if (0xe0 == (0xf0 & ptr[0]))
|
||||
{
|
||||
// 3 byte UTF-8 codepoint */
|
||||
if(((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
|
||||
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
|
||||
*codepointSize = 3;
|
||||
}
|
||||
else if (0xc0 == (0xe0 & ptr[0]))
|
||||
{
|
||||
// 2 byte UTF-8 codepoint
|
||||
if((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
|
||||
if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
|
||||
*codepointSize = 2;
|
||||
}
|
||||
|
@ -2001,23 +2079,27 @@ int GetCodepointPrevious(const char *text, int *codepointSize)
|
|||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT) || defined(SUPPORT_FILEFORMAT_BDF)
|
||||
// Read a line from memory
|
||||
// REQUIRES: memcpy()
|
||||
// NOTE: Returns the number of bytes read
|
||||
static int GetLine(const char *origin, char *buffer, int maxLength)
|
||||
{
|
||||
int count = 0;
|
||||
for (; count < maxLength; count++) if (origin[count] == '\n') break;
|
||||
for (; count < maxLength - 1; count++) if (origin[count] == '\n') break;
|
||||
memcpy(buffer, origin, count);
|
||||
buffer[count] = '\0';
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
// Load a BMFont file (AngelCode font file)
|
||||
// REQUIRES: strstr(), sscanf(), strrchr(), memcpy()
|
||||
static Font LoadBMFont(const char *fileName)
|
||||
{
|
||||
#define MAX_BUFFER_SIZE 256
|
||||
#define MAX_BUFFER_SIZE 256
|
||||
#define MAX_FONT_IMAGE_PAGES 8
|
||||
|
||||
Font font = { 0 };
|
||||
|
||||
|
@ -2029,7 +2111,8 @@ static Font LoadBMFont(const char *fileName)
|
|||
|
||||
int imWidth = 0;
|
||||
int imHeight = 0;
|
||||
char imFileName[129] = { 0 };
|
||||
int pageCount = 1;
|
||||
char imFileName[MAX_FONT_IMAGE_PAGES][129] = { 0 };
|
||||
|
||||
int base = 0; // Useless data
|
||||
int readBytes = 0; // Data bytes read
|
||||
|
@ -2048,17 +2131,26 @@ static Font LoadBMFont(const char *fileName)
|
|||
// Read line data
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
searchPoint = strstr(buffer, "lineHeight");
|
||||
readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &imWidth, &imHeight);
|
||||
readVars = sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i pages=%i", &fontSize, &base, &imWidth, &imHeight, &pageCount);
|
||||
fileTextPtr += (readBytes + 1);
|
||||
|
||||
|
||||
if (readVars < 4) { UnloadFileText(fileText); return font; } // Some data not available, file malformed
|
||||
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
searchPoint = strstr(buffer, "file");
|
||||
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName);
|
||||
fileTextPtr += (readBytes + 1);
|
||||
if (pageCount > MAX_FONT_IMAGE_PAGES)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FONT: [%s] Font defines more pages than supported: %i/%i", fileName, pageCount, MAX_FONT_IMAGE_PAGES);
|
||||
pageCount = MAX_FONT_IMAGE_PAGES;
|
||||
}
|
||||
|
||||
if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
|
||||
for (int i = 0; i < pageCount; i++)
|
||||
{
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
searchPoint = strstr(buffer, "file");
|
||||
readVars = sscanf(searchPoint, "file=\"%128[^\"]\"", imFileName[i]);
|
||||
fileTextPtr += (readBytes + 1);
|
||||
|
||||
if (readVars < 1) { UnloadFileText(fileText); return font; } // No fileName read
|
||||
}
|
||||
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
searchPoint = strstr(buffer, "count");
|
||||
|
@ -2067,50 +2159,56 @@ static Font LoadBMFont(const char *fileName)
|
|||
|
||||
if (readVars < 1) { UnloadFileText(fileText); return font; } // No glyphCount read
|
||||
|
||||
// Compose correct path using route of .fnt file (fileName) and imFileName
|
||||
char *imPath = NULL;
|
||||
char *lastSlash = NULL;
|
||||
// Load all required images for further compose
|
||||
Image *imFonts = (Image *)RL_CALLOC(pageCount, sizeof(Image)); // Font atlases, multiple images
|
||||
|
||||
lastSlash = strrchr(fileName, '/');
|
||||
if (lastSlash == NULL) lastSlash = strrchr(fileName, '\\');
|
||||
|
||||
if (lastSlash != NULL)
|
||||
for (int i = 0; i < pageCount; i++)
|
||||
{
|
||||
// NOTE: We need some extra space to avoid memory corruption on next allocations!
|
||||
imPath = (char *)RL_CALLOC(TextLength(fileName) - TextLength(lastSlash) + TextLength(imFileName) + 4, 1);
|
||||
memcpy(imPath, fileName, TextLength(fileName) - TextLength(lastSlash) + 1);
|
||||
memcpy(imPath + TextLength(fileName) - TextLength(lastSlash) + 1, imFileName, TextLength(imFileName));
|
||||
}
|
||||
else imPath = imFileName;
|
||||
imFonts[i] = LoadImage(TextFormat("%s/%s", GetDirectoryPath(fileName), imFileName[i]));
|
||||
|
||||
TRACELOGD(" > Image loading path: %s", imPath);
|
||||
|
||||
Image imFont = LoadImage(imPath);
|
||||
|
||||
if (imFont.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
|
||||
{
|
||||
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
|
||||
Image imFontAlpha = {
|
||||
.data = RL_CALLOC(imFont.width*imFont.height, 2),
|
||||
.width = imFont.width,
|
||||
.height = imFont.height,
|
||||
.mipmaps = 1,
|
||||
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
|
||||
};
|
||||
|
||||
for (int p = 0, i = 0; p < (imFont.width*imFont.height*2); p += 2, i++)
|
||||
if (imFonts[i].format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
|
||||
{
|
||||
((unsigned char *)(imFontAlpha.data))[p] = 0xff;
|
||||
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFont.data)[i];
|
||||
}
|
||||
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
|
||||
Image imFontAlpha = {
|
||||
.data = RL_CALLOC(imFonts[i].width*imFonts[i].height, 2),
|
||||
.width = imFonts[i].width,
|
||||
.height = imFonts[i].height,
|
||||
.mipmaps = 1,
|
||||
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA
|
||||
};
|
||||
|
||||
UnloadImage(imFont);
|
||||
imFont = imFontAlpha;
|
||||
for (int p = 0, pi = 0; p < (imFonts[i].width*imFonts[i].height*2); p += 2, pi++)
|
||||
{
|
||||
((unsigned char *)(imFontAlpha.data))[p] = 0xff;
|
||||
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFonts[i].data)[pi];
|
||||
}
|
||||
|
||||
UnloadImage(imFonts[i]);
|
||||
imFonts[i] = imFontAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
font.texture = LoadTextureFromImage(imFont);
|
||||
Image fullFont = imFonts[0];
|
||||
for (int i = 1; i < pageCount; i++) UnloadImage(imFonts[i]);
|
||||
|
||||
if (lastSlash != NULL) RL_FREE(imPath);
|
||||
// If multiple atlas, then merge atlas
|
||||
// NOTE: WARNING: This process could be really slow!
|
||||
if (pageCount > 1)
|
||||
{
|
||||
// Resize font atlas to draw additional images
|
||||
ImageResizeCanvas(&fullFont, imWidth, imHeight*pageCount, 0, 0, BLACK);
|
||||
|
||||
for (int i = 1; i < pageCount; i++)
|
||||
{
|
||||
Rectangle srcRec = { 0.0f, 0.0f, (float)imWidth, (float)imHeight };
|
||||
Rectangle destRec = { 0.0f, (float)imHeight*(float)i, (float)imWidth, (float)imHeight };
|
||||
ImageDraw(&fullFont, imFonts[i], srcRec, destRec, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
RL_FREE(imFonts);
|
||||
|
||||
font.texture = LoadTextureFromImage(fullFont);
|
||||
|
||||
// Fill font characters info data
|
||||
font.baseSize = fontSize;
|
||||
|
@ -2119,19 +2217,19 @@ static Font LoadBMFont(const char *fileName)
|
|||
font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
|
||||
font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
|
||||
|
||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX, pageID;
|
||||
|
||||
for (int i = 0; i < glyphCount; i++)
|
||||
{
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
readVars = 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);
|
||||
readVars = sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i page=%i",
|
||||
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX, &pageID);
|
||||
fileTextPtr += (readBytes + 1);
|
||||
|
||||
if (readVars == 8) // Make sure all char data has been properly read
|
||||
|
||||
if (readVars == 9) // Make sure all char data has been properly read
|
||||
{
|
||||
// Get character rectangle in the font atlas texture
|
||||
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
|
||||
font.recs[i] = (Rectangle){ (float)charX, (float)charY + (float)imHeight*pageID, (float)charWidth, (float)charHeight };
|
||||
|
||||
// Save data properly in sprite font
|
||||
font.glyphs[i].value = charId;
|
||||
|
@ -2139,13 +2237,13 @@ static Font LoadBMFont(const char *fileName)
|
|||
font.glyphs[i].offsetY = charOffsetY;
|
||||
font.glyphs[i].advanceX = charAdvanceX;
|
||||
|
||||
// Fill character image data from imFont data
|
||||
font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
|
||||
// Fill character image data from full font data
|
||||
font.glyphs[i].image = ImageFromImage(fullFont, font.recs[i]);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FONT: [%s] Some characters data not correctly provided", fileName);
|
||||
}
|
||||
|
||||
UnloadImage(imFont);
|
||||
UnloadImage(fullFont);
|
||||
UnloadFileText(fileText);
|
||||
|
||||
if (font.texture.id == 0)
|
||||
|
@ -2158,6 +2256,258 @@ static Font LoadBMFont(const char *fileName)
|
|||
|
||||
return font;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_BDF)
|
||||
|
||||
// Convert hexadecimal to decimal (single digit)
|
||||
static unsigned char HexToInt(char hex)
|
||||
{
|
||||
if (hex >= '0' && hex <= '9') return hex - '0';
|
||||
else if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;
|
||||
else if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
// Load font data for further use
|
||||
// NOTE: Requires BDF font memory data
|
||||
static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, int *codepoints, int codepointCount, int *outFontSize)
|
||||
{
|
||||
#define MAX_BUFFER_SIZE 256
|
||||
|
||||
char buffer[MAX_BUFFER_SIZE] = { 0 };
|
||||
|
||||
GlyphInfo *glyphs = NULL;
|
||||
bool genFontChars = false;
|
||||
|
||||
int totalReadBytes = 0; // Data bytes read (total)
|
||||
int readBytes = 0; // Data bytes read (line)
|
||||
int readVars = 0; // Variables filled by sscanf()
|
||||
|
||||
const char *fileText = (const char*)fileData;
|
||||
const char *fileTextPtr = fileText;
|
||||
|
||||
bool fontMalformed = false; // Is the font malformed
|
||||
bool fontStarted = false; // Has font started (STARTFONT)
|
||||
int fontBBw = 0; // Font base character bounding box width
|
||||
int fontBBh = 0; // Font base character bounding box height
|
||||
int fontBBxoff0 = 0; // Font base character bounding box X0 offset
|
||||
int fontBByoff0 = 0; // Font base character bounding box Y0 offset
|
||||
int fontAscent = 0; // Font ascent
|
||||
|
||||
bool charStarted = false; // Has character started (STARTCHAR)
|
||||
bool charBitmapStarted = false; // Has bitmap data started (BITMAP)
|
||||
int charBitmapNextRow = 0; // Y position for the next row of bitmap data
|
||||
int charEncoding = -1; // The unicode value of the character (-1 if not set)
|
||||
int charBBw = 0; // Character bounding box width
|
||||
int charBBh = 0; // Character bounding box height
|
||||
int charBBxoff0 = 0; // Character bounding box X0 offset
|
||||
int charBByoff0 = 0; // Character bounding box Y0 offset
|
||||
int charDWidthX = 0; // Character advance X
|
||||
int charDWidthY = 0; // Character advance Y (unused)
|
||||
GlyphInfo *charGlyphInfo = NULL; // Pointer to output glyph info (NULL if not set)
|
||||
|
||||
if (fileData == NULL) return glyphs;
|
||||
|
||||
// In case no chars count provided, default to 95
|
||||
codepointCount = (codepointCount > 0)? codepointCount : 95;
|
||||
|
||||
// Fill fontChars in case not provided externally
|
||||
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
|
||||
if (codepoints == NULL)
|
||||
{
|
||||
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
|
||||
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
|
||||
genFontChars = true;
|
||||
}
|
||||
|
||||
glyphs = (GlyphInfo *)RL_CALLOC(codepointCount, sizeof(GlyphInfo));
|
||||
|
||||
while (totalReadBytes <= dataSize)
|
||||
{
|
||||
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
|
||||
totalReadBytes += (readBytes + 1);
|
||||
fileTextPtr += (readBytes + 1);
|
||||
|
||||
// Line: COMMENT
|
||||
if (strstr(buffer, "COMMENT") != NULL) continue; // Ignore line
|
||||
|
||||
if (charStarted)
|
||||
{
|
||||
// Line: ENDCHAR
|
||||
if (strstr(buffer, "ENDCHAR") != NULL)
|
||||
{
|
||||
charStarted = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (charBitmapStarted)
|
||||
{
|
||||
if (charGlyphInfo != NULL)
|
||||
{
|
||||
int pixelY = charBitmapNextRow++;
|
||||
|
||||
if (pixelY >= charGlyphInfo->image.height) break;
|
||||
|
||||
for (int x = 0; x < readBytes; x++)
|
||||
{
|
||||
unsigned char byte = HexToInt(buffer[x]);
|
||||
|
||||
for (int bitX = 0; bitX < 4; bitX++)
|
||||
{
|
||||
int pixelX = ((x*4) + bitX);
|
||||
|
||||
if (pixelX >= charGlyphInfo->image.width) break;
|
||||
|
||||
if ((byte & (8 >> bitX)) > 0) ((unsigned char *)charGlyphInfo->image.data)[(pixelY*charGlyphInfo->image.width) + pixelX] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Line: ENCODING
|
||||
if (strstr(buffer, "ENCODING") != NULL)
|
||||
{
|
||||
readVars = sscanf(buffer, "ENCODING %i", &charEncoding);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Line: BBX
|
||||
if (strstr(buffer, "BBX") != NULL)
|
||||
{
|
||||
readVars = sscanf(buffer, "BBX %i %i %i %i", &charBBw, &charBBh, &charBBxoff0, &charBByoff0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Line: DWIDTH
|
||||
if (strstr(buffer, "DWIDTH") != NULL)
|
||||
{
|
||||
readVars = sscanf(buffer, "DWIDTH %i %i", &charDWidthX, &charDWidthY);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Line: BITMAP
|
||||
if (strstr(buffer, "BITMAP") != NULL)
|
||||
{
|
||||
// Search for glyph index in codepoints
|
||||
charGlyphInfo = NULL;
|
||||
|
||||
for (int codepointIndex = 0; codepointIndex < codepointCount; codepointIndex++)
|
||||
{
|
||||
if (codepoints[codepointIndex] == charEncoding)
|
||||
{
|
||||
charGlyphInfo = &glyphs[codepointIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Init glyph info
|
||||
if (charGlyphInfo != NULL)
|
||||
{
|
||||
charGlyphInfo->value = charEncoding;
|
||||
charGlyphInfo->offsetX = charBBxoff0 + fontBByoff0;
|
||||
charGlyphInfo->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
|
||||
charGlyphInfo->advanceX = charDWidthX;
|
||||
|
||||
charGlyphInfo->image.data = RL_CALLOC(charBBw*charBBh, 1);
|
||||
charGlyphInfo->image.width = charBBw;
|
||||
charGlyphInfo->image.height = charBBh;
|
||||
charGlyphInfo->image.mipmaps = 1;
|
||||
charGlyphInfo->image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
}
|
||||
|
||||
charBitmapStarted = true;
|
||||
charBitmapNextRow = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (fontStarted)
|
||||
{
|
||||
// Line: ENDFONT
|
||||
if (strstr(buffer, "ENDFONT") != NULL)
|
||||
{
|
||||
fontStarted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Line: SIZE
|
||||
if (strstr(buffer, "SIZE") != NULL)
|
||||
{
|
||||
if (outFontSize != NULL) readVars = sscanf(buffer, "SIZE %i", outFontSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
// PIXEL_SIZE
|
||||
if (strstr(buffer, "PIXEL_SIZE") != NULL)
|
||||
{
|
||||
if (outFontSize != NULL) readVars = sscanf(buffer, "PIXEL_SIZE %i", outFontSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
// FONTBOUNDINGBOX
|
||||
if (strstr(buffer, "FONTBOUNDINGBOX") != NULL)
|
||||
{
|
||||
readVars = sscanf(buffer, "FONTBOUNDINGBOX %i %i %i %i", &fontBBw, &fontBBh, &fontBBxoff0, &fontBByoff0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// FONT_ASCENT
|
||||
if (strstr(buffer, "FONT_ASCENT") != NULL)
|
||||
{
|
||||
readVars = sscanf(buffer, "FONT_ASCENT %i", &fontAscent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// STARTCHAR
|
||||
if (strstr(buffer, "STARTCHAR") != NULL)
|
||||
{
|
||||
charStarted = true;
|
||||
charEncoding = -1;
|
||||
charGlyphInfo = NULL;
|
||||
charBBw = 0;
|
||||
charBBh = 0;
|
||||
charBBxoff0 = 0;
|
||||
charBByoff0 = 0;
|
||||
charDWidthX = 0;
|
||||
charDWidthY = 0;
|
||||
charGlyphInfo = NULL;
|
||||
charBitmapStarted = false;
|
||||
charBitmapNextRow = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// STARTFONT
|
||||
if (strstr(buffer, "STARTFONT") != NULL)
|
||||
{
|
||||
if (fontStarted)
|
||||
{
|
||||
fontMalformed = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fontStarted = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (genFontChars) RL_FREE(codepoints);
|
||||
|
||||
if (fontMalformed)
|
||||
{
|
||||
RL_FREE(glyphs);
|
||||
glyphs = NULL;
|
||||
}
|
||||
|
||||
return glyphs;
|
||||
}
|
||||
#endif // SUPPORT_FILEFORMAT_BDF
|
||||
|
||||
#endif // SUPPORT_MODULE_RTEXT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue