13 Commits

Author SHA1 Message Date
Ray
1fa3c15942 Revert "add const qualifier to the first arg of TextJoin (#5166)"
This reverts commit 4e8d08523f.
2025-09-02 19:00:22 +02:00
4e8d08523f add const qualifier to the first arg of TextJoin (#5166)
* add const qualifier to the first arg of TextJoin

* Update raylib_api.* by CI

* Update raylib.h

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ray <raysan5@gmail.com>
2025-09-02 18:58:39 +02:00
Ray
cb6a64843c Remove raylib logs 2025-09-02 18:52:10 +02:00
Ray
4fa8e23efc Update rexm.c 2025-09-02 18:52:00 +02:00
Ray
1dfff2252d rexm update 2025-09-02 18:44:27 +02:00
Ray
cf61a8b888 REXM: Update examples report 2025-09-02 18:38:20 +02:00
Ray
bcd46fb36b Update rexm.c 2025-09-02 18:38:04 +02:00
Ray
9fab2c8a13 REVIEWED: example: text_unicode_ranges 2025-09-02 18:34:58 +02:00
Ray
0fd5a1a3f5 REDESIGNED: example: text_unicode_ranges 2025-09-02 17:47:25 +02:00
Ray
d5ea6a87d9 Merge branch 'master' of https://github.com/raysan5/raylib 2025-09-02 17:47:13 +02:00
17d9927a4f Update raylib_api.* by CI 2025-09-02 15:46:09 +00:00
Ray
b16d14f5ed Update text_font_sdf.c 2025-09-02 17:45:52 +02:00
Ray
29ce5d8aa9 WARNING: BREAKING: LoadFontData() redesigned, added parameter
This redesign is a big improvement on font loading time and memory requirements. It only loads glyphs available on font from requested codepoints and only processes those glyphs for packaging. When processing +10K codepoints (CJK), the loading time improves considerably.
2025-09-02 17:45:39 +02:00
15 changed files with 270 additions and 212 deletions

View File

@ -504,10 +504,10 @@ CORE = \
core/core_2d_camera_platformer \
core/core_2d_camera_split_screen \
core/core_3d_camera_first_person \
core/core_3d_camera_fps \
core/core_3d_camera_free \
core/core_3d_camera_mode \
core/core_3d_camera_split_screen \
core/core_3d_camera_fps \
core/core_3d_picking \
core/core_automation_events \
core/core_basic_screen_manager \

View File

@ -504,10 +504,10 @@ CORE = \
core/core_2d_camera_platformer \
core/core_2d_camera_split_screen \
core/core_3d_camera_first_person \
core/core_3d_camera_fps \
core/core_3d_camera_free \
core/core_3d_camera_mode \
core/core_3d_camera_split_screen \
core/core_3d_camera_fps \
core/core_3d_picking \
core/core_automation_events \
core/core_basic_screen_manager \
@ -695,6 +695,9 @@ core/core_2d_camera_split_screen: core/core_2d_camera_split_screen.c
core/core_3d_camera_first_person: core/core_3d_camera_first_person.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_camera_fps: core/core_3d_camera_fps.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_camera_free: core/core_3d_camera_free.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -704,9 +707,6 @@ core/core_3d_camera_mode: core/core_3d_camera_mode.c
core/core_3d_camera_split_screen: core/core_3d_camera_split_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_camera_fps: core/core_3d_camera_fps.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_3d_picking: core/core_3d_picking.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)

View File

@ -100,6 +100,7 @@ text;text_input_box;⭐️⭐️☆☆;1.7;3.5;"Ramon Santamaria";@raysan5
text;text_writing_anim;⭐️⭐️☆☆;1.4;1.4;"Ramon Santamaria";@raysan5
text;text_rectangle_bounds;⭐️⭐️⭐️⭐️;2.5;4.0;"Vlad Adrian";@demizdor
text;text_unicode;⭐️⭐️⭐️⭐️;2.5;4.0;"Vlad Adrian";@demizdor
text;text_unicode_ranges;⭐️⭐️⭐️⭐️;5.5;5.6;"Vlad Adrian";@demizdor
text;text_draw_3d;⭐️⭐️⭐️⭐️;3.5;4.0;"Vlad Adrian";@demizdor
text;text_codepoints_loading;⭐️⭐️⭐️☆;4.2;4.2;"Ramon Santamaria";@raysan5
models;models_animation;⭐️⭐️☆☆;2.5;3.5;"Culacant";@culacant
@ -168,4 +169,3 @@ others;easings_testbed;⭐️⭐️⭐️☆;2.5;3.0;"Juan Miguel López";@flash
others;raylib_opengl_interop;⭐️⭐️⭐️⭐️;3.8;4.0;"Stephan Soller";@arkanis
others;embedded_files_loading;⭐️⭐️☆☆;3.0;3.5;"Kristian Holmgren";@defutura
others;raymath_vector_angle;⭐️⭐️☆☆;1.0;4.6;"Ramon Santamaria";@raysan5
text;text_unicode_ranges;⭐⭐⭐⭐️;2.5;4.0;"Vlad Adrian";@demizdor

View File

@ -50,7 +50,7 @@ int main(void)
// Loading font data from memory data
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array)
fontDefault.glyphs = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT);
fontDefault.glyphs = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT, &fontDefault.glyphCount);
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default)
Image atlas = GenImageFontAtlas(fontDefault.glyphs, &fontDefault.recs, 95, 16, 4, 0);
fontDefault.texture = LoadTextureFromImage(atlas);
@ -61,7 +61,8 @@ int main(void)
fontSDF.baseSize = 16;
fontSDF.glyphCount = 95;
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95)
fontSDF.glyphs = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF);
fontSDF.glyphs = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF, &
fontSDF.glyphCount);
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm)
atlas = GenImageFontAtlas(fontSDF.glyphs, &fontSDF.recs, 95, 16, 0, 1);
fontSDF.texture = LoadTextureFromImage(atlas);

View File

@ -11,7 +11,7 @@
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2019-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
* Copyright (c) 2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
@ -19,20 +19,11 @@
#include <stdlib.h>
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct {
int *data;
int count;
int capacity;
} CodepointsArray;
//--------------------------------------------------------------------------------------
// Module Functions Declaration
//--------------------------------------------------------------------------------------
static void AddCodepointRange(CodepointsArray* array, int start, int stop);
//static Font LoadUnicodeFont(const char* fileName, int fontSize);
// Add codepoint range to existing font
static void AddCodepointRange(Font *font, const char *fontPath, int start, int stop);
//------------------------------------------------------------------------------------
// Program main entry point
@ -46,9 +37,12 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode ranges");
// Load font with Unicode support
Font fontUni = LoadUnicodeFont("resources/NotoSansTC-Regular.ttf", 32);
SetTextureFilter(fontUni.texture, TEXTURE_FILTER_BILINEAR);
// Load font with default Unicode range: Basic ASCII [32-127]
Font font = LoadFont("resources/NotoSansTC-Regular.ttf");
SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);
int unicodeRange = 0; // Track the ranges of codepoints added to font
int prevUnicodeRange = 0; // Previous Unicode range to avoid reloading every frame
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -58,7 +52,77 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
//...
if (unicodeRange != prevUnicodeRange)
{
UnloadFont(font);
// Load font with default Unicode range: Basic ASCII [32-127]
font = LoadFont("resources/NotoSansTC-Regular.ttf");
// Add required ranges to loaded font
switch (unicodeRange)
{
/*
case 5:
{
// Unicode range: Devanari, Arabic, Hebrew
// WARNING: Glyphs not available on provided font!
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x900, 0x97f); // Devanagari
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x600, 0x6ff); // Arabic
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x5d0, 0x5ea); // Hebrew
}
*/
case 4:
{
// Unicode range: CJK (Japanese and Chinese)
// WARNING: Loading thousands of codepoints requires lot of time!
// A better strategy is prefilter the required codepoints for the text
// in the game and just load the required ones
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x4e00, 0x9fff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x3400, 0x4dbf);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x3000, 0x303f);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x3040, 0x309f);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x30A0, 0x30ff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x31f0, 0x31ff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0xff00, 0xffef);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0xac00, 0xd7af);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x1100, 0x11ff);
}
case 3:
{
// Unicode range: Cyrillic
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x400, 0x4ff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x500, 0x52f);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x2de0, 0x2Dff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0xa640, 0xA69f);
}
case 2:
{
// Unicode range: Greek
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x370, 0x3ff);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x1f00, 0x1fff);
}
case 1:
{
// Unicode range: European Languages
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0xc0, 0x17f);
AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x180, 0x24f);
//AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x1e00, 0x1eff);
//AddCodepointRange(&font, "resources/NotoSansTC-Regular.ttf", 0x2c60, 0x2c7f);
}
default: break;
}
prevUnicodeRange = unicodeRange;
SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); // Set font atlas scale filter
}
if (IsKeyPressed(KEY_ZERO)) unicodeRange = 0;
else if (IsKeyPressed(KEY_ONE)) unicodeRange = 1;
else if (IsKeyPressed(KEY_TWO)) unicodeRange = 2;
else if (IsKeyPressed(KEY_THREE)) unicodeRange = 3;
else if (IsKeyPressed(KEY_FOUR)) unicodeRange = 4;
//else if (IsKeyPressed(KEY_FIVE)) unicodeRange = 5;
//----------------------------------------------------------------------------------
// Draw
@ -66,22 +130,36 @@ int main(void)
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("ADD CODEPOINTS: [1][2][3][4]", 20, 20, 20, MAROON);
// Render test strings in different languages
DrawTextEx(fontUni, "English: Hello World!", (Vector2){ 50, 50 }, 32, 1, DARKGRAY); // English
DrawTextEx(fontUni, "Español: Hola mundo!", (Vector2){ 50, 100 }, 32, 1, DARKGRAY); // Spanish
DrawTextEx(fontUni, "Ελληνικά: Γειά σου κόσμε!", (Vector2){ 50, 150 }, 32, 1, DARKGRAY); // Greek
DrawTextEx(fontUni, "Русский: Привет мир!", (Vector2){ 50, 200 }, 32, 0, DARKGRAY); // Russian
DrawTextEx(fontUni, "中文: 你好世界!", (Vector2){ 50, 250 }, 32, 1, DARKGRAY); // Chinese
DrawTextEx(fontUni, "日本語: こんにちは世界!", (Vector2){ 50, 300 }, 32, 1, DARKGRAY); // Japanese
DrawTextEx(fontUni, "देवनागरी: होला मुंडो!", (Vector2){ 50, 350 }, 32, 1, DARKGRAY); // Devanagari
DrawTextEx(font, "> English: Hello World!", (Vector2){ 50, 70 }, 32, 1, DARKGRAY); // English
DrawTextEx(font, "> Español: Hola mundo!", (Vector2){ 50, 120 }, 32, 1, DARKGRAY); // Spanish
DrawTextEx(font, "> Ελληνικά: Γειά σου κόσμε!", (Vector2){ 50, 170 }, 32, 1, DARKGRAY); // Greek
DrawTextEx(font, "> Русский: Привет мир!", (Vector2){ 50, 220 }, 32, 0, DARKGRAY); // Russian
DrawTextEx(font, "> 中文: 你好世界!", (Vector2){ 50, 270 }, 32, 1, DARKGRAY); // Chinese
DrawTextEx(font, "> 日本語: こんにちは世界!", (Vector2){ 50, 320 }, 32, 1, DARKGRAY); // Japanese
//DrawTextEx(font, "देवनागरी: होला मुंडो!", (Vector2){ 50, 350 }, 32, 1, DARKGRAY); // Devanagari (glyphs not available in font)
DrawRectangle(400, 16, 380, 400, BLACK);
DrawTexturePro(fontUni.texture, (Rectangle){ 0, 0, fontUni.texture.width, fontUni.texture.height },
(Rectangle){ 400, 16, 380, 400 }, (Vector2){ 0, 0 }, 0.0f, WHITE);
// Draw font texture scaled to screen
float atlasScale = 380.0f/font.texture.width;
DrawRectangle(400, 16, font.texture.width*atlasScale, font.texture.height*atlasScale, BLACK);
DrawTexturePro(font.texture, (Rectangle){ 0, 0, font.texture.width, font.texture.height },
(Rectangle){ 400, 16, font.texture.width*atlasScale, font.texture.height*atlasScale }, (Vector2){ 0, 0 }, 0.0f, WHITE);
DrawRectangleLines(400, 16, 380, 380, RED);
DrawText(TextFormat("ATLAS SIZE: %ix%i px (x%02.1f)", font.texture.width, font.texture.height, atlasScale), 20, 380, 20, BLUE);
// Display font attribution
DrawText("Font: Noto Sans TC. License: SIL Open Font License 1.1", screenWidth - 300, screenHeight - 20, 10, GRAY);
if (prevUnicodeRange != unicodeRange)
{
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(WHITE, 0.8f));
DrawRectangle(0, 125, screenWidth, 200, GRAY);
DrawText("LOADING CODEPOINTS...", 150, 210, 40, BLACK);
}
EndDrawing();
//----------------------------------------------------------------------------------
@ -89,7 +167,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(fontUni); // Unload font resource
UnloadFont(font); // Unload font resource
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
@ -100,87 +178,26 @@ int main(void)
//--------------------------------------------------------------------------------------
// Module Functions Definition
//--------------------------------------------------------------------------------------
static void AddRange(CodepointsArray* array, int start, int stop)
// Add codepoint range to existing font
static void AddCodepointRange(Font *font, const char *fontPath, int start, int stop)
{
int rangeSize = stop - start + 1;
int currentRangeSize = font->glyphCount;
if ((array->count + rangeSize) > array->capacity)
{
array->capacity = array->count + rangeSize + 1024;
array->data = (int *)MemRealloc(array->data, array->capacity*sizeof(int));
if (!array->data)
{
TraceLog(LOG_ERROR, "FONTUTIL: Memory allocation failed");
exit(1);
}
}
// TODO: Load glyphs from provided vector font (if available),
// add them to existing font, regenerating font image and texture
for (int i = start; i <= stop; i++) array->data[array->count++] = i;
int updatedCodepointCount = currentRangeSize + rangeSize;
int *updatedCodepoints = (int *)RL_CALLOC(updatedCodepointCount, sizeof(int));
// Get current codepoint list
for (int i = 0; i < currentRangeSize; i++) updatedCodepoints[i] = font->glyphs[i].value;
// Add new codepoints to list (provided range)
for (int i = currentRangeSize; i < updatedCodepointCount; i++)
updatedCodepoints[i] = start + (i - currentRangeSize);
UnloadFont(*font);
*font = LoadFontEx(fontPath, 32, updatedCodepoints, updatedCodepointCount);
}
Font LoadUnicodeFont(const char *fileName, int fontSize)
{
CodepointsArray cp = { 0 };
cp.capacity = 2048;
cp.data = (int *)MemAlloc(cp.capacity*sizeof(int));
if (!cp.data)
{
TraceLog(LOG_ERROR, "FONTUTIL: Initial allocation failed");
return GetFontDefault();
}
// Unicode range: Basic ASCII
AddRange(&cp, 32, 126);
// Unicode range: European Languages
AddRange(&cp, 0xC0, 0x17F);
AddRange(&cp, 0x180, 0x24F);
AddRange(&cp, 0x1E00, 0x1EFF);
AddRange(&cp, 0x2C60, 0x2C7F);
// Unicode range: Greek
AddRange(&cp, 0x370, 0x3FF);
AddRange(&cp, 0x1F00, 0x1FFF);
// Unicode range: Cyrillic
AddRange(&cp, 0x400, 0x4FF);
AddRange(&cp, 0x500, 0x52F);
AddRange(&cp, 0x2DE0, 0x2DFF);
AddRange(&cp, 0xA640, 0xA69F);
// Unicode range: CJK
AddRange(&cp, 0x4E00, 0x9FFF);
AddRange(&cp, 0x3400, 0x4DBF);
AddRange(&cp, 0x3000, 0x303F);
AddRange(&cp, 0x3040, 0x309F);
AddRange(&cp, 0x30A0, 0x30FF);
AddRange(&cp, 0x31F0, 0x31FF);
AddRange(&cp, 0xFF00, 0xFFEF);
AddRange(&cp, 0xAC00, 0xD7AF);
AddRange(&cp, 0x1100, 0x11FF);
// Unicode range: Other
// WARNING: Not available on provided font
AddRange(&cp, 0x900, 0x97F); // Devanagari
AddRange(&cp, 0x600, 0x6FF); // Arabic
AddRange(&cp, 0x5D0, 0x5EA); // Hebrew
Font font = {0};
if (FileExists(fileName))
{
font = LoadFontEx(fileName, fontSize, cp.data, cp.count);
}
if (font.texture.id == 0)
{
font = GetFontDefault();
TraceLog(LOG_WARNING, "FONTUTIL: Using default font");
}
MemFree(cp.data);
return font;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -1466,11 +1466,11 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)

View File

@ -171,7 +171,7 @@ extern void LoadFontDefault(void)
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
defaultFont.glyphCount = 224; // Number of chars included in our default font
defaultFont.glyphCount = 224; // Number of glyphs included in our default font
defaultFont.glyphPadding = 0; // Characters padding
// Default font is directly defined here (data generated from a sprite font image)
@ -365,7 +365,7 @@ Font LoadFont(const char *fileName)
#define FONT_TTF_DEFAULT_FIRST_CHAR 32 // TTF font generation default first char for image sprite font (32-Space)
#endif
#ifndef FONT_TTF_DEFAULT_CHARS_PADDING
#define FONT_TTF_DEFAULT_CHARS_PADDING 4 // TTF font generation default chars padding
#define FONT_TTF_DEFAULT_CHARS_PADDING 4 // TTF font generation default glyphs padding
#endif
Font font = { 0 };
@ -404,7 +404,7 @@ Font LoadFont(const char *fileName)
// 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)
Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount)
{
Font font = { 0 };
@ -440,8 +440,8 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
int x = 0;
int y = 0;
// We allocate a temporal arrays for chars data measures,
// once we get the actual number of chars, we copy data to a sized arrays
// We allocate a temporal arrays for glyphs data measures,
// once we get the actual number of glyphs, we copy data to a sized arrays
int tempCharValues[MAX_GLYPHS_FROM_IMAGE] = { 0 };
Rectangle tempCharRecs[MAX_GLYPHS_FROM_IMAGE] = { 0 };
@ -520,7 +520,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
font.glyphCount = index;
font.glyphPadding = 0;
// We got tempCharValues and tempCharsRecs populated with chars data
// We got tempCharValues and tempCharsRecs populated with glyphs data
// Now we move temp data to sized charValues and charRecs arrays
font.glyphs = (GlyphInfo *)RL_MALLOC(font.glyphCount*sizeof(GlyphInfo));
font.recs = (Rectangle *)RL_MALLOC(font.glyphCount*sizeof(Rectangle));
@ -549,7 +549,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount)
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount)
{
Font font = { 0 };
@ -557,21 +557,21 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
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.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, (codepointCount > 0)? codepointCount : 95, FONT_DEFAULT, &font.glyphCount);
}
else
#endif
#if defined(SUPPORT_FILEFORMAT_BDF)
if (TextIsEqual(fileExtLower, ".bdf"))
{
font.glyphs = LoadFontDataBDF(fileData, dataSize, codepoints, font.glyphCount, &font.baseSize);
font.glyphs = LoadFontDataBDF(fileData, dataSize, codepoints, (codepointCount > 0)? codepointCount : 95, &font.baseSize);
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
}
else
#endif
@ -620,7 +620,7 @@ bool IsFontValid(Font font)
// Load font data for further use
// NOTE: Requires TTF font memory data and can generate SDF data
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type)
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount)
{
// NOTE: Using some SDF generation default values,
// trades off precision with ability to handle *smaller* sizes
@ -637,7 +637,8 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
#define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold
#endif
GlyphInfo *chars = NULL;
GlyphInfo *glyphs = NULL;
int glyphCounter = 0;
#if defined(SUPPORT_FILEFORMAT_TTF)
// Load font data (including pixel data) from TTF memory file
@ -646,6 +647,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
{
bool genFontChars = false;
stbtt_fontinfo fontInfo = { 0 };
int *requiredCodepoints = (int *)codepoints;
if (stbtt_InitFont(&fontInfo, (unsigned char *)fileData, 0)) // Initialize font for data reading
{
@ -662,21 +664,29 @@ 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)
if (requiredCodepoints == NULL)
{
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
requiredCodepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) requiredCodepoints[i] = i + 32;
genFontChars = true;
}
chars = (GlyphInfo *)RL_CALLOC(codepointCount, sizeof(GlyphInfo));
// Check available glyphs on provided font before loading them
for (int i = 0, index; i < codepointCount; i++)
{
index = stbtt_FindGlyphIndex(&fontInfo, requiredCodepoints[i]);
if (index > 0) glyphCounter++;
}
// NOTE: Using simple packaging, one char after another
// WARNING: Allocating space for maximum number of codepoints
glyphs = (GlyphInfo *)RL_CALLOC(glyphCounter, sizeof(GlyphInfo));
glyphCounter = 0; // Reset to reuse
int k = 0;
for (int i = 0; i < codepointCount; i++)
{
int chw = 0, chh = 0; // Character width and height (on generation)
int ch = codepoints[i]; // Character value to get info for
chars[i].value = ch;
int cpWidth = 0, cpHeight = 0; // Codepoint width and height (on generation)
int cp = requiredCodepoints[i]; // Codepoint value to get info for
// Render a unicode codepoint to a bitmap
// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
@ -685,76 +695,96 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// 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);
int index = stbtt_FindGlyphIndex(&fontInfo, cp);
if (index > 0)
{
// NOTE: Only storing glyphs for codepoints found in the font
glyphs[k].value = cp;
switch (type)
{
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;
case FONT_BITMAP: glyphs[k].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, cp, &cpWidth, &cpHeight, &glyphs[k].offsetX, &glyphs[k].offsetY); break;
case FONT_SDF:
{
if (cp != 32)
{
glyphs[k].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, cp,
FONT_SDF_CHAR_PADDING, FONT_SDF_ON_EDGE_VALUE, FONT_SDF_PIXEL_DIST_SCALE,
&cpWidth, &cpHeight, &glyphs[k].offsetX, &glyphs[k].offsetY);
}
} break;
//case FONT_MSDF:
default: break;
}
if (chars[i].image.data != NULL) // Glyph data has been found in the font
if (glyphs[k].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);
stbtt_GetCodepointHMetrics(&fontInfo, cp, &glyphs[k].advanceX, NULL);
glyphs[k].advanceX = (int)((float)glyphs[k].advanceX*scaleFactor);
if (chh > fontSize) TRACELOG(LOG_WARNING, "FONT: Character [0x%08x] size is bigger than expected font size", ch);
if (cpHeight > fontSize) TRACELOG(LOG_WARNING, "FONT: [0x%04x] Glyph height is bigger than requested font size: %i > %i", cp, cpHeight, (int)fontSize);
// 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;
// Load glyph image
glyphs[k].image.width = cpWidth;
glyphs[k].image.height = cpHeight;
glyphs[k].image.mipmaps = 1;
glyphs[k].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
chars[i].offsetY += (int)((float)ascent*scaleFactor);
glyphs[k].offsetY += (int)((float)ascent*scaleFactor);
}
//else TRACELOG(LOG_WARNING, "FONT: Glyph [0x%08x] has no image data available", cp); // Only reported for 0x20 and 0x3000
// NOTE: We create an empty image for space character,
// it could be further required for atlas packing
if (ch == 32)
// We create an empty image for Space character (0x20), useful for sprite font generation
// NOTE: Another space to consider: 0x3000 (CJK - Ideographic Space)
if ((cp == 0x20) || (cp == 0x3000))
{
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
chars[i].advanceX = (int)((float)chars[i].advanceX*scaleFactor);
stbtt_GetCodepointHMetrics(&fontInfo, cp, &glyphs[k].advanceX, NULL);
glyphs[k].advanceX = (int)((float)glyphs[k].advanceX*scaleFactor);
Image imSpace = {
.data = RL_CALLOC(chars[i].advanceX*fontSize, 2),
.width = chars[i].advanceX,
.data = RL_CALLOC(glyphs[k].advanceX*fontSize, 2),
.width = glyphs[k].advanceX,
.height = fontSize,
.mipmaps = 1,
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE
};
chars[i].image = imSpace;
glyphs[k].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++)
for (int p = 0; p < cpWidth*cpHeight; 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;
if (((unsigned char *)glyphs[k].image.data)[p] < FONT_BITMAP_ALPHA_THRESHOLD)
((unsigned char *)glyphs[k].image.data)[p] = 0;
else ((unsigned char *)glyphs[k].image.data)[p] = 255;
}
}
k++;
glyphCounter++;
}
else
{
// TODO: Use some fallback glyph for codepoints not found in the font
// WARNING: Glyph not found on font, optionally use a fallback glyph
}
}
if (glyphCounter < codepointCount) TRACELOG(LOG_WARNING, "FONT: Requested codepoints glyphs found: [%i/%i]", k, codepointCount);
}
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
if (genFontChars) RL_FREE(codepoints);
if (genFontChars) RL_FREE(requiredCodepoints);
}
#endif
return chars;
*glyphCount = glyphCounter;
return glyphs;
}
// Generate image font atlas using chars info
@ -1239,7 +1269,7 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
(font.recs[index].height + 2.0f*font.glyphPadding)*scaleFactor };
// Character source rectangle from font texture atlas
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
// NOTE: We consider glyphs padding when drawing, it could be required for outline/glow shader effects
Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
@ -1292,7 +1322,7 @@ int MeasureText(const char *text, int fontSize)
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0)
{
int defaultFontSize = 10; // Default Font chars height in pixel
int defaultFontSize = 10; // Default Font glyphs height in pixel
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
int spacing = fontSize/defaultFontSize;
@ -2394,7 +2424,7 @@ static unsigned char HexToInt(char hex)
// 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)
static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, const int *codepoints, int codepointCount, int *outFontSize)
{
#define MAX_BUFFER_SIZE 256
@ -2428,7 +2458,9 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
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)
GlyphInfo *glyphs = NULL; // Pointer to output glyph info (NULL if not set)
int *requiredCodepoints = codepoints;
if (fileData == NULL) return glyphs;
@ -2437,10 +2469,10 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
// Fill fontChars in case not provided externally
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
if (codepoints == NULL)
if (requiredCodepoints == NULL)
{
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
requiredCodepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) requiredCodepoints[i] = i + 32;
genFontChars = true;
}
@ -2466,11 +2498,11 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
if (charBitmapStarted)
{
if (charGlyphInfo != NULL)
if (glyphs != NULL)
{
int pixelY = charBitmapNextRow++;
if (pixelY >= charGlyphInfo->image.height) break;
if (pixelY >= glyphs->image.height) break;
for (int x = 0; x < readBytes; x++)
{
@ -2480,9 +2512,9 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
{
int pixelX = ((x*4) + bitX);
if (pixelX >= charGlyphInfo->image.width) break;
if (pixelX >= glyphs->image.width) break;
if ((byte & (8 >> bitX)) > 0) ((unsigned char *)charGlyphInfo->image.data)[(pixelY*charGlyphInfo->image.width) + pixelX] = 255;
if ((byte & (8 >> bitX)) > 0) ((unsigned char *)glyphs->image.data)[(pixelY*glyphs->image.width) + pixelX] = 255;
}
}
}
@ -2514,30 +2546,30 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
if (strstr(buffer, "BITMAP") != NULL)
{
// Search for glyph index in codepoints
charGlyphInfo = NULL;
glyphs = NULL;
for (int codepointIndex = 0; codepointIndex < codepointCount; codepointIndex++)
{
if (codepoints[codepointIndex] == charEncoding)
{
charGlyphInfo = &glyphs[codepointIndex];
glyphs = &glyphs[codepointIndex];
break;
}
}
// Init glyph info
if (charGlyphInfo != NULL)
if (glyphs != NULL)
{
charGlyphInfo->value = charEncoding;
charGlyphInfo->offsetX = charBBxoff0 + fontBByoff0;
charGlyphInfo->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
charGlyphInfo->advanceX = charDWidthX;
glyphs->value = charEncoding;
glyphs->offsetX = charBBxoff0 + fontBByoff0;
glyphs->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
glyphs->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;
glyphs->image.data = RL_CALLOC(charBBw*charBBh, 1);
glyphs->image.width = charBBw;
glyphs->image.height = charBBh;
glyphs->image.mipmaps = 1;
glyphs->image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
}
charBitmapStarted = true;
@ -2588,14 +2620,14 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i
{
charStarted = true;
charEncoding = -1;
charGlyphInfo = NULL;
glyphs = NULL;
charBBw = 0;
charBBh = 0;
charBBxoff0 = 0;
charBByoff0 = 0;
charDWidthX = 0;
charDWidthY = 0;
charGlyphInfo = NULL;
glyphs = NULL;
charBitmapStarted = false;
charBitmapNextRow = 0;
continue;

View File

@ -9041,7 +9041,7 @@
"name": "fontSize"
},
{
"type": "int *",
"type": "const int *",
"name": "codepoints"
},
{
@ -9091,7 +9091,7 @@
"name": "fontSize"
},
{
"type": "int *",
"type": "const int *",
"name": "codepoints"
},
{
@ -9129,7 +9129,7 @@
"name": "fontSize"
},
{
"type": "int *",
"type": "const int *",
"name": "codepoints"
},
{
@ -9139,6 +9139,10 @@
{
"type": "int",
"name": "type"
},
{
"type": "int *",
"name": "glyphCount"
}
]
},

View File

@ -6550,7 +6550,7 @@ return {
params = {
{type = "const char *", name = "fileName"},
{type = "int", name = "fontSize"},
{type = "int *", name = "codepoints"},
{type = "const int *", name = "codepoints"},
{type = "int", name = "codepointCount"}
}
},
@ -6573,7 +6573,7 @@ return {
{type = "const unsigned char *", name = "fileData"},
{type = "int", name = "dataSize"},
{type = "int", name = "fontSize"},
{type = "int *", name = "codepoints"},
{type = "const int *", name = "codepoints"},
{type = "int", name = "codepointCount"}
}
},
@ -6593,9 +6593,10 @@ return {
{type = "const unsigned char *", name = "fileData"},
{type = "int", name = "dataSize"},
{type = "int", name = "fontSize"},
{type = "int *", name = "codepoints"},
{type = "const int *", name = "codepoints"},
{type = "int", name = "codepointCount"},
{type = "int", name = "type"}
{type = "int", name = "type"},
{type = "int *", name = "glyphCount"}
}
},
{

View File

@ -3468,7 +3468,7 @@ Function 395: LoadFontEx() (4 input parameters)
Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
Param[1]: fileName (type: const char *)
Param[2]: fontSize (type: int)
Param[3]: codepoints (type: int *)
Param[3]: codepoints (type: const int *)
Param[4]: codepointCount (type: int)
Function 396: LoadFontFromImage() (3 input parameters)
Name: LoadFontFromImage
@ -3485,23 +3485,24 @@ Function 397: LoadFontFromMemory() (6 input parameters)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
Param[4]: fontSize (type: int)
Param[5]: codepoints (type: int *)
Param[5]: codepoints (type: const int *)
Param[6]: codepointCount (type: int)
Function 398: IsFontValid() (1 input parameters)
Name: IsFontValid
Return type: bool
Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
Param[1]: font (type: Font)
Function 399: LoadFontData() (6 input parameters)
Function 399: LoadFontData() (7 input parameters)
Name: LoadFontData
Return type: GlyphInfo *
Description: Load font data for further use
Param[1]: fileData (type: const unsigned char *)
Param[2]: dataSize (type: int)
Param[3]: fontSize (type: int)
Param[4]: codepoints (type: int *)
Param[4]: codepoints (type: const int *)
Param[5]: codepointCount (type: int)
Param[6]: type (type: int)
Param[7]: glyphCount (type: int *)
Function 400: GenImageFontAtlas() (6 input parameters)
Name: GenImageFontAtlas
Return type: Image

View File

@ -2286,7 +2286,7 @@
<Function name="LoadFontEx" retType="Font" paramCount="4" desc="Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height">
<Param type="const char *" name="fileName" desc="" />
<Param type="int" name="fontSize" desc="" />
<Param type="int *" name="codepoints" desc="" />
<Param type="const int *" name="codepoints" desc="" />
<Param type="int" name="codepointCount" desc="" />
</Function>
<Function name="LoadFontFromImage" retType="Font" paramCount="3" desc="Load font from Image (XNA style)">
@ -2299,19 +2299,20 @@
<Param type="const unsigned char *" name="fileData" desc="" />
<Param type="int" name="dataSize" desc="" />
<Param type="int" name="fontSize" desc="" />
<Param type="int *" name="codepoints" desc="" />
<Param type="const int *" name="codepoints" desc="" />
<Param type="int" name="codepointCount" desc="" />
</Function>
<Function name="IsFontValid" retType="bool" paramCount="1" desc="Check if a font is valid (font data loaded, WARNING: GPU texture not checked)">
<Param type="Font" name="font" desc="" />
</Function>
<Function name="LoadFontData" retType="GlyphInfo *" paramCount="6" desc="Load font data for further use">
<Function name="LoadFontData" retType="GlyphInfo *" paramCount="7" desc="Load font data for further use">
<Param type="const unsigned char *" name="fileData" desc="" />
<Param type="int" name="dataSize" desc="" />
<Param type="int" name="fontSize" desc="" />
<Param type="int *" name="codepoints" desc="" />
<Param type="const int *" name="codepoints" desc="" />
<Param type="int" name="codepointCount" desc="" />
<Param type="int" name="type" desc="" />
<Param type="int *" name="glyphCount" desc="" />
</Function>
<Function name="GenImageFontAtlas" retType="Image" paramCount="6" desc="Generate image font atlas using chars info">
<Param type="const GlyphInfo *" name="glyphs" desc="" />

View File

@ -36,7 +36,7 @@ Example elements validated:
| core_3d_camera_free | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_camera_first_person | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_camera_split_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_fps_controller | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_camera_fps | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_3d_picking | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_world_screen | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -113,6 +113,7 @@ Example elements validated:
| text_writing_anim | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_rectangle_bounds | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_unicode | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_unicode_ranges | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_draw_3d | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_codepoints_loading | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_animation | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -181,4 +182,4 @@ Example elements validated:
| raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| embedded_files_loading | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| text_unicode_ranges | ✔ | ✔ | ✔ | | | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_unicode_ranges | ✔ | ✔ | ✔ | | | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |

View File

@ -26,6 +26,7 @@ Example elements validated:
| core_high_dpi | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_digital_clock | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_font_sdf | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_unicode_ranges | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_draw_3d | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| text_codepoints_loading | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_loading_m3d | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@ -37,4 +38,3 @@ Example elements validated:
| raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| embedded_files_loading | ✔ | ❌ | ❌ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| text_unicode_ranges | ✔ | ✔ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |

View File

@ -181,6 +181,8 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath);
//------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
SetTraceLogLevel(LOG_NONE);
// Path values can be configured with environment variables
exBasePath = getenv("REXM_EXAMPLES_BASE_PATH");
exWebPath = getenv("REXM_EXAMPLES_WEB_PATH");
@ -370,15 +372,13 @@ int main(int argc, char *argv[])
{
// Verify example exists in collection to be removed
char *exColInfo = LoadFileText(exCollectionFilePath);
if ((TextFindIndex(exColInfo, argv[2]) != -1) && // Example in the collection
(TextFindIndex(exName, "_") != -1)) // Valid example name
if (TextFindIndex(exColInfo, argv[2]) != -1) // Example in the collection
{
strcpy(exName, argv[2]); // Register example name for removal
strncpy(exCategory, exName, TextFindIndex(exName, "_"));
opCode = OP_BUILD;
}
else LOG("WARNING: REMOVE: Example not available in the collection\n");
else LOG("WARNING: BUILD: Example not available in the collection\n");
UnloadFileText(exColInfo);
}
}
@ -1257,9 +1257,9 @@ int main(int argc, char *argv[])
printf("////////////////////////////////////////////////////////////////////////////////////////////\n\n");
printf("USAGE:\n\n");
printf(" > rexm <command> <example_name> [<example_rename>]\n");
printf(" > rexm <command> <example_name> [<example_rename>]\n\n");
printf("\COMMANDS:\n\n");
printf("COMMANDS:\n\n");
printf(" help : Provides command-line usage information\n");
printf(" create <new_example_name> : Creates an empty example, from internal template\n");
printf(" add <example_name> : Add existing example, category extracted from name\n");