Update C sources
This commit is contained in:
parent
dd222de786
commit
b83dec57b5
14 changed files with 2900 additions and 1289 deletions
278
raylib/rtext.c
278
raylib/rtext.c
|
@ -4,6 +4,9 @@
|
|||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_MODULE_RTEXT
|
||||
* rtext module is included in the build
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_FNT
|
||||
* #define SUPPORT_FILEFORMAT_TTF
|
||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||
|
@ -22,12 +25,12 @@
|
|||
*
|
||||
* DEPENDENCIES:
|
||||
* stb_truetype - Load TTF file and rasterize characters data
|
||||
* stb_rect_pack - Rectangles packing algorythms, required for font atlas generation
|
||||
* stb_rect_pack - Rectangles packing algorithms, required for font atlas generation
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2013-2022 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
|
@ -53,6 +56,8 @@
|
|||
#include "config.h" // Defines module configuration flags
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_MODULE_RTEXT)
|
||||
|
||||
#include "utils.h" // Required for: LoadFileText()
|
||||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro()
|
||||
|
||||
|
@ -224,7 +229,7 @@ extern void LoadFontDefault(void)
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
// Allocate space for our characters info data
|
||||
// NOTE: This memory should be freed at end! --> CloseWindow()
|
||||
// NOTE: This memory must be freed at end! --> Done by CloseWindow()
|
||||
defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
|
||||
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
|
||||
|
||||
|
@ -311,7 +316,7 @@ Font LoadFont(const char *fileName)
|
|||
Font font = { 0 };
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
if (IsFileExtension(fileName, ".ttf;.otf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
if (IsFileExtension(fileName, ".ttf") || IsFileExtension(fileName, ".otf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
else
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
|
@ -329,7 +334,11 @@ Font LoadFont(const char *fileName)
|
|||
TRACELOG(LOG_WARNING, "FONT: [%s] Failed to load font texture -> Using default font", fileName);
|
||||
font = GetFontDefault();
|
||||
}
|
||||
else SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default we set point filter (best performance)
|
||||
else
|
||||
{
|
||||
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); // By default we set point filter (best performance)
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", FONT_TTF_DEFAULT_SIZE, FONT_TTF_DEFAULT_NUMCHARS);
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -515,7 +524,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||
|
||||
UnloadImage(atlas);
|
||||
|
||||
// TRACELOG(LOG_INFO, "FONT: Font loaded successfully (%i glyphs)", font.glyphCount);
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
|
||||
}
|
||||
else font = GetFontDefault();
|
||||
}
|
||||
|
@ -677,20 +686,20 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// NOTE 2: SDF font characters already contain an internal padding,
|
||||
// so image size would result bigger than default font type
|
||||
float requiredArea = 0;
|
||||
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
|
||||
float guessSize = sqrtf(requiredArea)*1.3f;
|
||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(fontSize + 2*padding));
|
||||
float guessSize = sqrtf(requiredArea)*1.4f;
|
||||
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||
|
||||
atlas.width = imageSize; // Atlas bitmap width
|
||||
atlas.height = imageSize; // Atlas bitmap height
|
||||
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
||||
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
||||
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||
atlas.mipmaps = 1;
|
||||
|
||||
// DEBUG: We can see padding in the generated image setting a gray background...
|
||||
//for (int i = 0; i < atlas.width*atlas.height; i++) ((unsigned char *)atlas.data)[i] = 100;
|
||||
|
||||
if (packMethod == 0) // Use basic packing algorythm
|
||||
if (packMethod == 0) // Use basic packing algorithm
|
||||
{
|
||||
int offsetX = padding;
|
||||
int offsetY = padding;
|
||||
|
@ -725,11 +734,23 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// height is bigger than fontSize, it could be up to (fontSize + 8)
|
||||
offsetY += (fontSize + 2*padding);
|
||||
|
||||
if (offsetY > (atlas.height - fontSize - padding)) break;
|
||||
if (offsetY > (atlas.height - fontSize - padding))
|
||||
{
|
||||
for(int j = i + 1; j < glyphCount; j++)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FONT: Failed to package character (%i)", j);
|
||||
// make sure remaining recs contain valid data
|
||||
recs[j].x = 0;
|
||||
recs[j].y = 0;
|
||||
recs[j].width = 0;
|
||||
recs[j].height = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
|
||||
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
|
||||
{
|
||||
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
|
||||
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
|
||||
|
@ -797,9 +818,12 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
|||
// Unload font glyphs info data (RAM)
|
||||
void UnloadFontData(GlyphInfo *glyphs, int glyphCount)
|
||||
{
|
||||
for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
|
||||
if (glyphs != NULL)
|
||||
{
|
||||
for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
|
||||
|
||||
RL_FREE(glyphs);
|
||||
RL_FREE(glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
// Unload Font from GPU memory (VRAM)
|
||||
|
@ -816,15 +840,170 @@ 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.glyphPadding);
|
||||
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");
|
||||
|
||||
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)
|
||||
{
|
||||
Color color = LIME; // good fps
|
||||
Color color = LIME; // Good FPS
|
||||
int fps = GetFPS();
|
||||
|
||||
if (fps < 30 && fps >= 15) color = ORANGE; // warning FPS
|
||||
else if (fps < 15) color = RED; // bad FPS
|
||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
||||
else if (fps < 15) color = RED; // Low FPS
|
||||
|
||||
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
||||
}
|
||||
|
@ -875,7 +1054,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
|||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
|
@ -931,10 +1110,42 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
|
|||
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||
}
|
||||
|
||||
// Draw multiple character (codepoints)
|
||||
void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
|
||||
{
|
||||
int textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int index = GetGlyphIndex(font, codepoints[i]);
|
||||
|
||||
if (codepoints[i] == '\n')
|
||||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((codepoints[i] != ' ') && (codepoints[i] != '\t'))
|
||||
{
|
||||
DrawTextCodepoint(font, codepoints[i], (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
||||
}
|
||||
|
||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
||||
else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Measure string width for default font
|
||||
int MeasureText(const char *text, int fontSize)
|
||||
{
|
||||
Vector2 vec = { 0.0f, 0.0f };
|
||||
Vector2 textSize = { 0.0f, 0.0f };
|
||||
|
||||
// Check if default font has been loaded
|
||||
if (GetFontDefault().texture.id != 0)
|
||||
|
@ -943,15 +1154,19 @@ int MeasureText(const char *text, int fontSize)
|
|||
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||
int spacing = fontSize/defaultFontSize;
|
||||
|
||||
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing);
|
||||
textSize = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing);
|
||||
}
|
||||
|
||||
return (int)vec.x;
|
||||
return (int)textSize.x;
|
||||
}
|
||||
|
||||
// Measure string size for Font
|
||||
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
||||
{
|
||||
Vector2 textSize = { 0 };
|
||||
|
||||
if ((font.texture.id == 0) || (text == NULL)) return textSize;
|
||||
|
||||
int size = TextLength(text); // Get size in bytes of text
|
||||
int tempByteCounter = 0; // Used to count longer text line num chars
|
||||
int byteCounter = 0;
|
||||
|
@ -996,11 +1211,10 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
Vector2 vec = { 0 };
|
||||
vec.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||
vec.y = textHeight*scaleFactor;
|
||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||
textSize.y = textHeight*scaleFactor;
|
||||
|
||||
return vec;
|
||||
return textSize;
|
||||
}
|
||||
|
||||
// Get index position for a unicode character on font
|
||||
|
@ -1179,7 +1393,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
|
||||
// Replace text string
|
||||
// REQUIRES: strlen(), strstr(), strncpy(), strcpy()
|
||||
// WARNING: Returned buffer must be freed by the user (if return != NULL)
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplace(char *text, const char *replace, const char *by)
|
||||
{
|
||||
// Sanity checks and initialization
|
||||
|
@ -1228,7 +1442,7 @@ char *TextReplace(char *text, const char *replace, const char *by)
|
|||
}
|
||||
|
||||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory should be manually freed
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsert(const char *text, const char *insert, int position)
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
|
@ -1412,8 +1626,8 @@ const char *TextToPascal(const char *text)
|
|||
|
||||
// Encode text codepoint into UTF-8 text
|
||||
// REQUIRES: memcpy()
|
||||
// WARNING: Allocated memory should be manually freed
|
||||
char *TextCodepointsToUTF8(int *codepoints, int length)
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextCodepointsToUTF8(const int *codepoints, int length)
|
||||
{
|
||||
// We allocate enough memory fo fit all possible codepoints
|
||||
// NOTE: 5 bytes for every codepoint should be enough
|
||||
|
@ -1593,7 +1807,7 @@ int GetCodepoint(const char *text, int *bytesProcessed)
|
|||
if (((octet == 0xe0) && !((octet1 >= 0xa0) && (octet1 <= 0xbf))) ||
|
||||
((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f)))) { *bytesProcessed = 2; return code; }
|
||||
|
||||
if ((octet >= 0xe0) && (0 <= 0xef))
|
||||
if ((octet >= 0xe0) && (octet <= 0xef))
|
||||
{
|
||||
code = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
|
||||
*bytesProcessed = 3;
|
||||
|
@ -1795,3 +2009,5 @@ static Font LoadBMFont(const char *fileName)
|
|||
return font;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SUPPORT_MODULE_RTEXT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue