From d873314c279be1582e28f3c90416c6b225b787fb Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 29 May 2018 00:52:08 +0200 Subject: Reviewed Windows resource file name --- release/libs/win32/mingw32/libraylib.a | Bin 1100766 -> 1101816 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'release/libs/win32/mingw32/libraylib.a') diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a index 3aac1c0c..940dc353 100644 Binary files a/release/libs/win32/mingw32/libraylib.a and b/release/libs/win32/mingw32/libraylib.a differ -- cgit v1.2.3 From 9688c677de8b56a78175c87f8a18af7c6bcc9d1f Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 2 Jun 2018 18:26:57 +0200 Subject: Review window creation hints --- release/include/raylib.h | 2 +- release/libs/win32/mingw32/libraylib.a | Bin 1101816 -> 1102432 bytes src/core.c | 37 +++++++++++++++------------------ src/raylib.h | 2 +- 4 files changed, 19 insertions(+), 22 deletions(-) (limited to 'release/libs/win32/mingw32/libraylib.a') diff --git a/release/include/raylib.h b/release/include/raylib.h index dad08ba2..a3fa1311 100644 --- a/release/include/raylib.h +++ b/release/include/raylib.h @@ -92,7 +92,7 @@ #define FLAG_SHOW_LOGO 1 // Set to show raylib logo at startup #define FLAG_FULLSCREEN_MODE 2 // Set to run program in fullscreen #define FLAG_WINDOW_RESIZABLE 4 // Set to allow resizable window -#define FLAG_WINDOW_DECORATED 8 // Set to show window decoration (frame and buttons) +#define FLAG_WINDOW_UNDECORATED 8 // Set to disable window decoration (frame and buttons) #define FLAG_WINDOW_TRANSPARENT 16 // Set to allow transparent window #define FLAG_MSAA_4X_HINT 32 // Set to try enabling MSAA 4X #define FLAG_VSYNC_HINT 64 // Set to try enabling V-Sync on GPU diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a index 940dc353..45b4f336 100644 Binary files a/release/libs/win32/mingw32/libraylib.a and b/release/libs/win32/mingw32/libraylib.a differ diff --git a/src/core.c b/src/core.c index 5cd9bfd4..1f9159f9 100644 --- a/src/core.c +++ b/src/core.c @@ -1884,31 +1884,28 @@ static bool InitGraphicsDevice(int width, int height) displayHeight = screenHeight; #endif // defined(PLATFORM_WEB) - glfwDefaultWindowHints(); // Set default windows hints + glfwDefaultWindowHints(); // Set default windows hints: + //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits + //glfwWindowHint(GLFW_GREEN_BITS, 8); // Framebuffer green color component bits + //glfwWindowHint(GLFW_BLUE_BITS, 8); // Framebuffer blue color component bits + //glfwWindowHint(GLFW_ALPHA_BITS, 8); // Framebuffer alpha color component bits + //glfwWindowHint(GLFW_DEPTH_BITS, 24); // Depthbuffer bits + //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window + //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // OpenGL API to use. Alternative: GLFW_OPENGL_ES_API + //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers // Check some Window creation flags - if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window + if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable - if (configFlags & FLAG_WINDOW_DECORATED) glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window + if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GL_FALSE); // Border and buttons on Window + else glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Decorated window - if (configFlags & FLAG_WINDOW_TRANSPARENT) - { - // TODO: Enable transparent window (not ready yet on GLFW 3.2) - } + if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer + else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer - if (configFlags & FLAG_MSAA_4X_HINT) - { - glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0 - TraceLog(LOG_INFO, "Trying to enable MSAA x4"); - } + if (configFlags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0 - //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits - //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depthbuffer bits (24 by default) - //glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window - //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API - //glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers - // NOTE: When asking for an OpenGL context version, most drivers provide highest supported version // with forward compatibility to older OpenGL versions. // For example, if using OpenGL 1.1, driver can provide a 4.3 context forward compatible. @@ -1926,11 +1923,11 @@ static bool InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above! // Other values: GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE #if defined(__APPLE__) - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires fordward compatibility #else glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above! #endif - //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Request OpenGL DEBUG context } if (fullscreen) diff --git a/src/raylib.h b/src/raylib.h index dad08ba2..a3fa1311 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -92,7 +92,7 @@ #define FLAG_SHOW_LOGO 1 // Set to show raylib logo at startup #define FLAG_FULLSCREEN_MODE 2 // Set to run program in fullscreen #define FLAG_WINDOW_RESIZABLE 4 // Set to allow resizable window -#define FLAG_WINDOW_DECORATED 8 // Set to show window decoration (frame and buttons) +#define FLAG_WINDOW_UNDECORATED 8 // Set to disable window decoration (frame and buttons) #define FLAG_WINDOW_TRANSPARENT 16 // Set to allow transparent window #define FLAG_MSAA_4X_HINT 32 // Set to try enabling MSAA 4X #define FLAG_VSYNC_HINT 64 // Set to try enabling V-Sync on GPU -- cgit v1.2.3 From 31cd4a1a48f0e6b9678cbc3bb5c22a353665e1af Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 3 Jun 2018 23:58:17 +0200 Subject: Latest library release compilation --- release/libs/win32/mingw32/libraylib.a | Bin 1102432 -> 1103438 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'release/libs/win32/mingw32/libraylib.a') diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a index 45b4f336..2701869a 100644 Binary files a/release/libs/win32/mingw32/libraylib.a and b/release/libs/win32/mingw32/libraylib.a differ -- cgit v1.2.3 From 75ba5aca551d2b16fa75ba31e616b009ac5dde6a Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 20 Jun 2018 00:52:14 +0200 Subject: Improved font generation and SDF Added: data to CharInfo struct Added: LoadFontData() Added: GenImageFontAtlas() Removed: LoadFontEx() Removed: LoadTTF() [internal] Some code tweaks --- release/include/raylib.h | 27 +-- release/libs/win32/mingw32/libraylib.a | Bin 1103438 -> 1116752 bytes src/raylib.h | 27 +-- src/text.c | 356 ++++++++++++++++++++------------- src/textures.c | 4 +- 5 files changed, 243 insertions(+), 171 deletions(-) (limited to 'release/libs/win32/mingw32/libraylib.a') diff --git a/release/include/raylib.h b/release/include/raylib.h index e0cfaa6d..49434d52 100644 --- a/release/include/raylib.h +++ b/release/include/raylib.h @@ -389,6 +389,7 @@ typedef struct CharInfo { int offsetX; // Character offset X when drawing int offsetY; // Character offset Y when drawing int advanceX; // Character advance position X + unsigned char *data; // Character pixel data (grayscale) } CharInfo; // Font type, includes texture and charSet array data @@ -955,29 +956,29 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters - //------------------------------------------------------------------------------------ // Font Loading and Text Drawing Functions (Module: text) //------------------------------------------------------------------------------------ // Font loading/unloading functions -RLAPI Font GetDefaultFont(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 charsCount, int *fontChars); // Load Font from file with extended parameters -RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) +RLAPI Font GetDefaultFont(void); // Get the default Font +RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) +RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use +RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int packing); // Generate image font atlas using chars info +RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions -RLAPI void DrawFPS(int posX, int posY); // Shows current FPS -RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) -RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using Font and additional parameters +RLAPI void DrawFPS(int posX, int posY); // Shows current FPS +RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) +RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters // Text misc. functions -RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font -RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font -RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' -RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string -RLAPI int GetGlyphIndex(Font font, int character); // Returns index position for a unicode character on sprite font +RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font +RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font +RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' +RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string +RLAPI int GetGlyphIndex(Font font, int character); // Get index position for a unicode character on sprite font //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a index 2701869a..3425c71a 100644 Binary files a/release/libs/win32/mingw32/libraylib.a and b/release/libs/win32/mingw32/libraylib.a differ diff --git a/src/raylib.h b/src/raylib.h index e0cfaa6d..49434d52 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -389,6 +389,7 @@ typedef struct CharInfo { int offsetX; // Character offset X when drawing int offsetY; // Character offset Y when drawing int advanceX; // Character advance position X + unsigned char *data; // Character pixel data (grayscale) } CharInfo; // Font type, includes texture and charSet array data @@ -955,29 +956,29 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters - //------------------------------------------------------------------------------------ // Font Loading and Text Drawing Functions (Module: text) //------------------------------------------------------------------------------------ // Font loading/unloading functions -RLAPI Font GetDefaultFont(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 charsCount, int *fontChars); // Load Font from file with extended parameters -RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) +RLAPI Font GetDefaultFont(void); // Get the default Font +RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) +RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use +RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int packing); // Generate image font atlas using chars info +RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions -RLAPI void DrawFPS(int posX, int posY); // Shows current FPS -RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) -RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using Font and additional parameters +RLAPI void DrawFPS(int posX, int posY); // Shows current FPS +RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) +RLAPI void DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters // Text misc. functions -RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font -RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font -RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' -RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string -RLAPI int GetGlyphIndex(Font font, int character); // Returns index position for a unicode character on sprite font +RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font +RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font +RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' +RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string +RLAPI int GetGlyphIndex(Font font, int character); // Get index position for a unicode character on sprite font //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) diff --git a/src/text.c b/src/text.c index 9755ff8b..3c3ff751 100644 --- a/src/text.c +++ b/src/text.c @@ -47,16 +47,14 @@ #include "utils.h" // Required for: fopen() Android mapping #if defined(SUPPORT_FILEFORMAT_TTF) - // Following libs are used on LoadTTF() - #define STBTT_STATIC // Define stb_truetype functions static to this module + #define STB_RECT_PACK_IMPLEMENTATION + #include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging + + #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION - #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() + #include "external/stb_truetype.h" // Required for: ttf font data reading #endif -// Rectangle packing functions (not used at the moment) -//#define STB_RECT_PACK_IMPLEMENTATION -//#include "stb_rect_pack.h" - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -89,7 +87,7 @@ static Font LoadImageFont(Image image, Color key, int firstChar); // Load a Imag static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file) #endif #if defined(SUPPORT_FILEFORMAT_TTF) -static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data +//static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data #endif #if defined(SUPPORT_DEFAULT_FONT) @@ -276,68 +274,244 @@ Font LoadFont(const char *fileName) // Default hardcoded values for ttf file loading #define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space) #define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs - #define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont + #define DEFAULT_FIRST_CHAR 32 // Expected first char for image sprite font - Font spriteFont = { 0 }; + Font font = { 0 }; #if defined(SUPPORT_FILEFORMAT_TTF) - if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL); + if (IsFileExtension(fileName, ".ttf")) + { + font.baseSize = DEFAULT_TTF_FONTSIZE; + font.charsCount = DEFAULT_TTF_NUMCHARS; + font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false); + Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0); + font.texture = LoadTextureFromImage(atlas); + UnloadImage(atlas); + } else #endif #if defined(SUPPORT_FILEFORMAT_FNT) - if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName); + if (IsFileExtension(fileName, ".fnt")) font = LoadBMFont(fileName); else #endif { Image image = LoadImage(fileName); - if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR); + if (image.data != NULL) font = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR); UnloadImage(image); } - if (spriteFont.texture.id == 0) + if (font.texture.id == 0) { TraceLog(LOG_WARNING, "[%s] Font could not be loaded, using default font", fileName); - spriteFont = GetDefaultFont(); + font = GetDefaultFont(); } - else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance) + else SetTextureFilter(font.texture, FILTER_POINT); // By default we set point filter (best performance) - return spriteFont; + return font; } -// Load Font from TTF 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 charsCount, int *fontChars) +// Load font data for further use +// NOTE: Requires TTF font and can generate SDF data +CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf) { - Font spriteFont = { 0 }; - int totalChars = 95; // Default charset [32..126] - bool fontCharsLoaded = false; + // NOTE: Using some SDF generation default values, + // trades off precision with ability to handle *smaller* sizes + #define SDF_CHAR_PADDING 4 + #define SDF_ON_EDGE_VALUE 128 + #define SDF_PIXEL_DIST_SCALE 64.0f + + CharInfo *chars = (CharInfo *)malloc(charsCount*sizeof(CharInfo)); + + // Load font data (including pixel data) from TTF file + // NOTE: Loaded information should be enough to generate font image atlas, + // using any packaging method + FILE *fontFile = fopen(fileName, "rb"); // Load font file + + fseek(fontFile, 0, SEEK_END); + long size = ftell(fontFile); // Get file size + fseek(fontFile, 0, SEEK_SET); // Reset file pointer + + unsigned char *fontBuffer = (unsigned char *)malloc(size); + + fread(fontBuffer, size, 1, fontFile); + fclose(fontFile); + + // Init font for data reading + stbtt_fontinfo fontInfo; + if (!stbtt_InitFont(&fontInfo, fontBuffer, 0)) TraceLog(LOG_WARNING, "Failed to init font!"); -#if defined(SUPPORT_FILEFORMAT_TTF) - if (IsFileExtension(fileName, ".ttf")) + // Calculate font scale factor + float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, fontSize); + + // Calculate font basic metrics + // NOTE: ascent is equivalent to font baseline + int ascent, descent, lineGap; + stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap); + ascent *= scaleFactor; + descent *= scaleFactor; + + // Fill fontChars in case not provided externally + // NOTE: By default we fill charsCount consecutevely, starting at 32 (Space) + int genFontChars = false; + if (fontChars == NULL) genFontChars = true; + if (genFontChars) + { + fontChars = (int *)malloc(charsCount*sizeof(int)); + for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32; + } + + // NOTE: Using simple packaging, one char after another + for (int i = 0; i < charsCount; i++) + { + int chw = 0, chh = 0; // Character width and height (on generation) + int ch = fontChars[i]; // Character value to get info for + chars[i].value = ch; + + // Render a unicode codepoint to a bitmap + // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap + // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be + // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide + + if (!sdf) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); + else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY); + + chars[i].rec.width = (float)chw; + chars[i].rec.height = (float)chh; + chars[i].offsetY += ascent; + + // Get bounding box for character (may be offset to account for chars that dip above or below the line) + int chX1, chY1, chX2, chY2; + stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2); + + TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1); + TraceLog(LOG_DEBUG, "Character offsetY: %i", ascent + chY1); + + stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL); + chars[i].advanceX *= scaleFactor; + } + + free(fontBuffer); + if (genFontChars) free(fontChars); + + return chars; +} + +// Generate image font atlas using chars info +// NOTE: Packing method: 0-Default, 1-Skyline +Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int packing) +{ + Image atlas = { 0 }; + + int padding = 10; + + // Calculate atlas texture size based on fontSize + // NOTE: Font texture size is predicted (being as much conservative as possible) + // Predictive method consist of supposing same number of chars by line-column (sqrtf) + // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... + //float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); + //int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT + + // TODO: TEXTURE SIZE NOT GOOD ENOUGH! -> Calculate chars area -> guess texture size? + float requiredArea = 0; + for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].rec.width + 2*padding)*(chars[i].rec.height + 2*padding)); + float guessSize = sqrtf(requiredArea)*1.25f; + int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT + + atlas.width = textureSize; // Atlas bitmap width + atlas.height = textureSize; // Atlas bitmap height + atlas.data = (unsigned char *)calloc(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp) + atlas.format = UNCOMPRESSED_GRAYSCALE; + atlas.mipmaps = 1; + + if (packing == 0) // Use basic packing algorythm { - if (charsCount != 0) totalChars = charsCount; + int offsetX = padding; + int offsetY = padding; - if (fontChars == NULL) + // NOTE: Using simple packaging, one char after another + for (int i = 0; i < charsCount; i++) { - fontChars = (int *)malloc(totalChars*sizeof(int)); - for (int i = 0; i < totalChars; i++) fontChars[i] = i + 32; // Default first character: SPACE[32] - fontCharsLoaded = true; + // Copy pixel data from fc.data to atlas + for (int y = 0; y < (int)chars[i].rec.height; y++) + { + for (int x = 0; x < (int)chars[i].rec.width; x++) + { + ((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = chars[i].data[y*(int)chars[i].rec.width + x]; + } + } + + chars[i].rec.x = offsetX; + chars[i].rec.y = offsetY; + + // Move atlas position X for next character drawing + offsetX += ((int)chars[i].advanceX + 2*padding); + + if (offsetX >= (atlas.width - (int)chars[i].rec.width - padding)) + { + offsetX = padding; + offsetY += (fontSize + 2*padding); + + if (offsetY > (atlas.height - fontSize - padding)) break; + } } + } + else if (packing == 1) // Use Skyline rect packing algorythm + { + stbrp_context *context = (stbrp_context *)malloc(sizeof(*context)); + stbrp_node *nodes = (stbrp_node *)malloc(charsCount*sizeof(*nodes)); + + stbrp_init_target(context, atlas.width, atlas.height, nodes, charsCount); + stbrp_rect *rects = (stbrp_rect *)malloc(charsCount*sizeof(stbrp_rect)); - spriteFont = LoadTTF(fileName, fontSize, totalChars, fontChars); + // Fill rectangles for packaging + for (int i = 0; i < charsCount; i++) + { + rects[i].id = i; + rects[i].w = (int)chars[i].rec.width + 2*padding; + rects[i].h = (int)chars[i].rec.height + 2*padding; + } + + // Package rectangles into atlas + stbrp_pack_rects(context, rects, charsCount); - if (fontCharsLoaded) free(fontChars); + for (int i = 0; i < charsCount; i++) + { + chars[i].rec.x = rects[i].x + padding; + chars[i].rec.y = rects[i].y + padding; + + if (rects[i].was_packed) + { + // Copy pixel data from fc.data to atlas + for (int y = 0; y < (int)chars[i].rec.height; y++) + { + for (int x = 0; x < (int)chars[i].rec.width; x++) + { + ((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = chars[i].data[y*(int)chars[i].rec.width + x]; + } + } + } + else TraceLog(LOG_WARNING, "Character could not be packed: %i", i); + } + + free(nodes); + free(context); } -#endif + + // Convert image data from GRAYSCALE to GRAY_ALPHA + //ImageAlphaMask(&atlas, atlas); // WARNING: Not working in this case, requires manual operation + unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels - if (spriteFont.texture.id == 0) + for (int i = 0, k = 0; i < atlas.width*atlas.height; i++, k += 2) { - TraceLog(LOG_WARNING, "[%s] Font could not be generated, using default font", fileName); - spriteFont = GetDefaultFont(); + dataGrayAlpha[k] = 255; + dataGrayAlpha[k + 1] = ((unsigned char *)atlas.data)[i]; } - return spriteFont; + free(atlas.data); + atlas.data = dataGrayAlpha; + atlas.format = UNCOMPRESSED_GRAY_ALPHA; + + return atlas; } // Unload Font from GPU memory (VRAM) @@ -811,108 +985,4 @@ static Font LoadBMFont(const char *fileName) return font; } -#endif - -#if defined(SUPPORT_FILEFORMAT_TTF) -// Generate a sprite font from TTF file data (font size required) -// TODO: Review texture packing method and generation (use oversampling) -static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars) -{ - #define MAX_TTF_SIZE 16 // Maximum ttf file size in MB - - // NOTE: Font texture size is predicted (being as much conservative as possible) - // Predictive method consist of supposing same number of chars by line-column (sqrtf) - // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... - - // Calculate next power-of-two value - float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); - int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - - TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); - - unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024); - unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned! - stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*charsCount); - - Font font = { 0 }; - - FILE *ttfFile = fopen(fileName, "rb"); - - if (ttfFile == NULL) - { - TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName); - return font; - } - - // NOTE: We try reading up to 16 MB of elements of 1 byte - fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile); - - // Find font baseline (vertical origin of the font) - // NOTE: This value is required because y-offset depends on it! - stbtt_fontinfo fontInfo; - int ascent, baseline; - float scale; - - stbtt_InitFont(&fontInfo, ttfBuffer, 0); - scale = stbtt_ScaleForPixelHeight(&fontInfo, fontSize); - stbtt_GetFontVMetrics(&fontInfo, &ascent, 0, 0); - baseline = (int)(ascent*scale); - - if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); - - // NOTE: Using stb_truetype crappy packing method, no guarantee the font fits the image... - // TODO: Replace this function by a proper packing method and support random chars order, - // we already receive a list (fontChars) with the ordered expected characters - int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData); - - //if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); - if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font"); - - free(ttfBuffer); - - // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA - unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels - - for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2) - { - dataGrayAlpha[k] = 0xff; - dataGrayAlpha[k + 1] = dataBitmap[i]; - } - - free(dataBitmap); - - // Sprite font generation from TTF extracted data - Image image; - image.width = textureSize; - image.height = textureSize; - image.mipmaps = 1; - image.format = UNCOMPRESSED_GRAY_ALPHA; - image.data = dataGrayAlpha; - font.texture = LoadTextureFromImage(image); // Load image into texture - UnloadImage(image); // Unloads image data (dataGrayAlpha) - - - // Fill font characters info data - font.baseSize = fontSize; - font.charsCount = charsCount; - font.chars = (CharInfo *)malloc(font.charsCount*sizeof(CharInfo)); - - for (int i = 0; i < font.charsCount; i++) - { - font.chars[i].value = fontChars[i]; - - font.chars[i].rec.x = (int)charData[i].x0; - font.chars[i].rec.y = (int)charData[i].y0; - font.chars[i].rec.width = (int)charData[i].x1 - (int)charData[i].x0; - font.chars[i].rec.height = (int)charData[i].y1 - (int)charData[i].y0; - - font.chars[i].offsetX = charData[i].xoff; - font.chars[i].offsetY = baseline + charData[i].yoff; - font.chars[i].advanceX = (int)charData[i].xadvance; - } - - free(charData); - - return font; -} -#endif +#endif \ No newline at end of file diff --git a/src/textures.c b/src/textures.c index eeaf7ffd..29316a7a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -828,9 +828,9 @@ void ImageFormat(Image *image, int newFormat) } break; case UNCOMPRESSED_GRAY_ALPHA: { - image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); + image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); - for (int i = 0; i < image->width*image->height*2; i += 2, k++) + for (int i = 0; i < image->width*image->height*2; i += 2, k++) { ((unsigned char *)image->data)[i] = (unsigned char)((pixels[k].x*0.299f + (float)pixels[k].y*0.587f + (float)pixels[k].z*0.114f)*255.0f); ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].w*255.0f); -- cgit v1.2.3 From 0e135118fd0edd3ef613cb28cb573d12916dca98 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 21 Jun 2018 00:18:13 +0200 Subject: Improved GenImageFontAtlas() --- release/include/raylib.h | 2 +- release/libs/win32/mingw32/libraylib.a | Bin 1116752 -> 1116822 bytes src/raylib.h | 2 +- src/text.c | 22 +++++++--------------- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'release/libs/win32/mingw32/libraylib.a') diff --git a/release/include/raylib.h b/release/include/raylib.h index 49434d52..9a6e117f 100644 --- a/release/include/raylib.h +++ b/release/include/raylib.h @@ -965,7 +965,7 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest RLAPI Font GetDefaultFont(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use -RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int packing); // Generate image font atlas using chars info +RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod); // Generate image font atlas using chars info RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions diff --git a/release/libs/win32/mingw32/libraylib.a b/release/libs/win32/mingw32/libraylib.a index 3425c71a..0bf3c421 100644 Binary files a/release/libs/win32/mingw32/libraylib.a and b/release/libs/win32/mingw32/libraylib.a differ diff --git a/src/raylib.h b/src/raylib.h index 49434d52..9a6e117f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -965,7 +965,7 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest RLAPI Font GetDefaultFont(void); // Get the default Font RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use -RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int packing); // Generate image font atlas using chars info +RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod); // Generate image font atlas using chars info RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) // Text drawing functions diff --git a/src/text.c b/src/text.c index 3c3ff751..5e02a471 100644 --- a/src/text.c +++ b/src/text.c @@ -284,7 +284,7 @@ Font LoadFont(const char *fileName) font.baseSize = DEFAULT_TTF_FONTSIZE; font.charsCount = DEFAULT_TTF_NUMCHARS; font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false); - Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0); + Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0); font.texture = LoadTextureFromImage(atlas); UnloadImage(atlas); } @@ -398,20 +398,12 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c // Generate image font atlas using chars info // NOTE: Packing method: 0-Default, 1-Skyline -Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int packing) +Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod) { Image atlas = { 0 }; - int padding = 10; - - // Calculate atlas texture size based on fontSize - // NOTE: Font texture size is predicted (being as much conservative as possible) - // Predictive method consist of supposing same number of chars by line-column (sqrtf) - // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... - //float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); - //int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - - // TODO: TEXTURE SIZE NOT GOOD ENOUGH! -> Calculate chars area -> guess texture size? + // Calculate texture size based on required pixel area + // NOTE: Texture is forced to be squared and POT float requiredArea = 0; for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].rec.width + 2*padding)*(chars[i].rec.height + 2*padding)); float guessSize = sqrtf(requiredArea)*1.25f; @@ -423,7 +415,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int packi atlas.format = UNCOMPRESSED_GRAYSCALE; atlas.mipmaps = 1; - if (packing == 0) // Use basic packing algorythm + if (packMethod == 0) // Use basic packing algorythm { int offsetX = padding; int offsetY = padding; @@ -455,7 +447,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int packi } } } - else if (packing == 1) // Use Skyline rect packing algorythm + else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect) { stbrp_context *context = (stbrp_context *)malloc(sizeof(*context)); stbrp_node *nodes = (stbrp_node *)malloc(charsCount*sizeof(*nodes)); @@ -498,7 +490,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int packi } // Convert image data from GRAYSCALE to GRAY_ALPHA - //ImageAlphaMask(&atlas, atlas); // WARNING: Not working in this case, requires manual operation + // WARNING: ImageAlphaMask(&atlas, atlas) does not work in this case, requires manual operation unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels for (int i = 0, k = 0; i < atlas.width*atlas.height; i++, k += 2) -- cgit v1.2.3