ADDED: ExportFontAsCode()
This commit is contained in:
parent
62858e11f7
commit
2116a98745
@ -1325,7 +1325,9 @@ RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileDat
|
||||
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
|
||||
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
|
||||
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
|
||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||
|
||||
|
||||
// Text drawing functions
|
||||
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
||||
|
155
src/rtext.c
155
src/rtext.c
@ -821,6 +821,161 @@ void UnloadFont(Font font)
|
||||
}
|
||||
}
|
||||
|
||||
// Export font as code file, returns true on success
|
||||
bool ExportFontAsCode(Font font, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
#endif
|
||||
|
||||
#define MAX_FONT_DATA_SIZE 1024*1024 // 1 MB
|
||||
|
||||
// Get file name from path
|
||||
char fileNamePascal[256] = { 0 };
|
||||
strcpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)));
|
||||
|
||||
// NOTE: Text data buffer size is estimated considering image data size in bytes
|
||||
// and requiring 6 char bytes for every byte: "0x00, "
|
||||
char *txtData = (char *)RL_CALLOC(MAX_FONT_DATA_SIZE, sizeof(char));
|
||||
|
||||
int byteCount = 0;
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// FontAsCode exporter v1.0 - Font data exported as an array of bytes //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
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-2022 Ramon Santamaria (@raysan5) //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// ---------------------------------------------------------------------------------- //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// TODO: Fill the information and license of the exported font here: //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font name: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font creator: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// Font LICENSE: .... //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// //\n");
|
||||
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
|
||||
|
||||
// Support font export and initialization
|
||||
// NOTE: This mechanism is highly coupled to raylib
|
||||
Image image = LoadImageFromTexture(font.texture);
|
||||
if (image.format != PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) TRACELOG(LOG_WARNING, "Font export as code: Font image format is not GRAY+ALPHA!");
|
||||
int imageDataSize = GetPixelDataSize(image.width, image.height, image.format);
|
||||
|
||||
// Image data is usually GRAYSCALE + ALPHA and can be reduced to GRAYSCALE
|
||||
//ImageFormat(&image, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE);
|
||||
|
||||
#define SUPPORT_COMPRESSED_FONT_ATLAS
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
// WARNING: Data is compressed using raylib CompressData() DEFLATE,
|
||||
// it requires to be decompressed with raylib DecompressData(), that requires
|
||||
// compiling raylib with SUPPORT_COMPRESSION_API config flag enabled
|
||||
|
||||
// Compress font image data
|
||||
int compDataSize = 0;
|
||||
unsigned char *compData = CompressData(image.data, imageDataSize, &compDataSize);
|
||||
|
||||
// Save font image data (compressed)
|
||||
byteCount += sprintf(txtData + byteCount, "#define COMPRESSED_DATA_SIZE_FONT_%s %i\n\n", TextToUpper(fileNamePascal), compDataSize);
|
||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data compressed (DEFLATE)\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: Original pixel data simplified to GRAYSCALE\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
|
||||
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
|
||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
|
||||
MemFree(compData);
|
||||
#else
|
||||
// Save font image data (uncompressed)
|
||||
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: 2 bytes per pixel, GRAY + ALPHA channels\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static unsigned char fontImageData_%s[%i] = { ", fileNamePascal, imageDataSize);
|
||||
for (int i = 0; i < imageDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), ((unsigned char *)imFont.data)[i]);
|
||||
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", ((unsigned char *)imFont.data)[imageDataSize - 1]);
|
||||
#endif
|
||||
|
||||
// Save font recs data
|
||||
byteCount += sprintf(txtData + byteCount, "// Font characters rectangles data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static const Rectangle fontRecs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
byteCount += sprintf(txtData + byteCount, " { %1.0f, %1.0f, %1.0f , %1.0f },\n", font.recs[i].x, font.recs[i].y, font.recs[i].width, font.recs[i].height);
|
||||
}
|
||||
byteCount += sprintf(txtData + byteCount, "};\n\n");
|
||||
|
||||
// Save font glyphs data
|
||||
// NOTE: Glyphs image data not saved (grayscale pixels),
|
||||
// it could be generated from image and recs
|
||||
byteCount += sprintf(txtData + byteCount, "// Font glyphs info data\n");
|
||||
byteCount += sprintf(txtData + byteCount, "// NOTE: No glyphs.image data provided\n");
|
||||
byteCount += sprintf(txtData + byteCount, "static const GlyphInfo fontGlyphs_%s[%i] = {\n", fileNamePascal, font.glyphCount);
|
||||
for (int i = 0; i < font.glyphCount; i++)
|
||||
{
|
||||
byteCount += sprintf(txtData + byteCount, " { %i, %i, %i, %i, { 0 }},\n", font.glyphs[i].value, font.glyphs[i].offsetX, font.glyphs[i].offsetY, font.glyphs[i].advanceX);
|
||||
}
|
||||
byteCount += sprintf(txtData + byteCount, "};\n\n");
|
||||
|
||||
// Custom font loading function
|
||||
byteCount += sprintf(txtData + byteCount, "// Font loading function: %s\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, "static Font LoadFont_%s(void)\n{\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " Font font = { 0 };\n\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.baseSize = %i;\n", font.baseSize);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphCount = %i;\n", font.glyphCount);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphPadding = %i;\n\n", FONT_TTF_DEFAULT_CHARS_PADDING);
|
||||
byteCount += sprintf(txtData + byteCount, " // Custom font loading\n");
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function\n");
|
||||
byteCount += sprintf(txtData + byteCount, " int fontDataSize_%s = 0;\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " unsigned char *data = DecompressData(fontData_%s, COMPRESSED_DATA_SIZE_FONT_%s, &fontDataSize_%s);\n", fileNamePascal, TextToUpper(fileNamePascal), fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " Image imFont = { data, %i, %i, 1, %i };\n\n", image.width, image.height, image.format);
|
||||
#else
|
||||
byteCount += sprintf(txtData + byteCount, " Image imFont = { fontImageData_%s, %i, %i, 1, %i };\n\n", styleName, image.width, image.height, image.format);
|
||||
#endif
|
||||
byteCount += sprintf(txtData + byteCount, " // Load texture from image\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.texture = LoadTextureFromImage(imFont);\n");
|
||||
#if defined(SUPPORT_COMPRESSED_FONT_ATLAS)
|
||||
byteCount += sprintf(txtData + byteCount, " UnloadImage(imFont); // Uncompressed data can be unloaded from memory\n\n");
|
||||
#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.
|
||||
// - 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)
|
||||
byteCount += sprintf(txtData + byteCount, " // Copy glyph recs data from global fontRecs\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Required to avoid issues if trying to free font\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.recs = (Rectangle *)malloc(font.glyphCount*sizeof(Rectangle));\n");
|
||||
byteCount += sprintf(txtData + byteCount, " memcpy(font.recs, fontRecs_%s, font.glyphCount*sizeof(Rectangle));\n\n", fileNamePascal);
|
||||
|
||||
byteCount += sprintf(txtData + byteCount, " // Copy font glyph info data from global fontChars\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // NOTE: Required to avoid issues if trying to free font\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphs = (GlyphInfo *)malloc(font.glyphCount*sizeof(GlyphInfo));\n");
|
||||
byteCount += sprintf(txtData + byteCount, " memcpy(font.glyphs, fontGlyphs_%s, font.glyphCount*sizeof(GlyphInfo));\n\n", fileNamePascal);
|
||||
#else
|
||||
byteCount += sprintf(txtData + byteCount, " // Assign glyph recs and info data directly\n");
|
||||
byteCount += sprintf(txtData + byteCount, " // WARNING: This font data must not be unloaded\n");
|
||||
byteCount += sprintf(txtData + byteCount, " font.recs = fontRecs_%s;\n", fileNamePascal);
|
||||
byteCount += sprintf(txtData + byteCount, " font.glyphs = fontGlyphs_%s;\n\n", fileNamePascal);
|
||||
#endif
|
||||
byteCount += sprintf(txtData + byteCount, " return font;\n");
|
||||
byteCount += sprintf(txtData + byteCount, "}\n\0");
|
||||
|
||||
UnloadImage(image);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
// Draw current FPS
|
||||
// NOTE: Uses default font
|
||||
void DrawFPS(int posX, int posY)
|
||||
|
Loading…
x
Reference in New Issue
Block a user