summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/raylib.h15
-rw-r--r--src/shapes.c2
-rw-r--r--src/text.c357
-rw-r--r--src/textures.c88
4 files changed, 258 insertions, 204 deletions
diff --git a/src/raylib.h b/src/raylib.h
index f9f5882a..fc66e149 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -263,18 +263,18 @@ typedef struct NPatchInfo {
// Font character info
typedef struct CharInfo {
int value; // Character value (Unicode)
- Rectangle rec; // Character rectangle in sprite font
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)
+ Image image; // Character image data
} CharInfo;
// Font type, includes texture and charSet array data
typedef struct Font {
- Texture2D texture; // Font texture
int baseSize; // Base size (default chars height)
int charsCount; // Number of characters
+ Texture2D texture; // Characters texture atlas
+ Rectangle *recs; // Characters rectangles in texture
CharInfo *chars; // Characters info data
} Font;
@@ -1100,6 +1100,7 @@ RLAPI void UpdateTexture(Texture2D texture, const void *pixels);
// Image manipulation functions
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
+RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
@@ -1115,7 +1116,7 @@ RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);
RLAPI Color *ImageExtractPalette(Image image, int maxPaletteSize, int *extractCount); // Extract color palette from image to maximum size (memory should be freed)
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font)
-RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image
+RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
RLAPI void ImageDrawRectangle(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image
RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color); // Draw text (default font) within an image (destination)
@@ -1165,7 +1166,7 @@ RLAPI Font LoadFont(const char *fileName);
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
-RLAPI Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
+RLAPI Image GenImageFontAtlas(const CharInfo *chars, Rectangle **recs, int charsCount, int fontSize, 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
@@ -1180,8 +1181,8 @@ RLAPI void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontS
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 int GetGlyphIndex(Font font, int character); // Get index position for a unicode character on font
-RLAPI int GetNextCodepoint(const char *text, int *count); // Returns next codepoint in a UTF8 encoded string
- // NOTE: 0x3f(`?`) is returned on failure, `count` will hold the total number of bytes processed
+RLAPI int GetNextCodepoint(const char *text, int *bytesProcessed); // Returns next codepoint in a UTF8 encoded string
+ // NOTE: 0x3f('?') is returned on failure
// Text strings management functions
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
diff --git a/src/shapes.c b/src/shapes.c
index 190bd4e1..d1956b26 100644
--- a/src/shapes.c
+++ b/src/shapes.c
@@ -1522,7 +1522,7 @@ static Texture2D GetShapesTexture(void)
{
#if defined(SUPPORT_FONT_TEXTURE)
texShapes = GetFontDefault().texture; // Use font texture white character
- Rectangle rec = GetFontDefault().chars[95].rec;
+ Rectangle rec = GetFontDefault().recs[95];
// NOTE: We setup a 1px padding on char rectangle to avoid texture bleeding on MSAA filtering
recTexShapes = (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 };
#else
diff --git a/src/text.c b/src/text.c
index eb956d1b..1c775c8d 100644
--- a/src/text.c
+++ b/src/text.c
@@ -193,13 +193,12 @@ extern void LoadFontDefault(void)
if (counter > 512) counter = 0; // Security check...
}
- Image image = LoadImageEx(imagePixels, imWidth, imHeight);
- ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
+ Image imFont = LoadImageEx(imagePixels, imWidth, imHeight);
+ ImageFormat(&imFont, UNCOMPRESSED_GRAY_ALPHA);
RL_FREE(imagePixels);
- defaultFont.texture = LoadTextureFromImage(image);
- UnloadImage(image);
+ defaultFont.texture = LoadTextureFromImage(imFont);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, charsCount
//------------------------------------------------------------------------------
@@ -207,6 +206,7 @@ extern void LoadFontDefault(void)
// Allocate space for our characters info data
// NOTE: This memory should be freed at end! --> CloseWindow()
defaultFont.chars = (CharInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(CharInfo));
+ defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle));
int currentLine = 0;
int currentPosX = charsDivisor;
@@ -216,12 +216,12 @@ extern void LoadFontDefault(void)
{
defaultFont.chars[i].value = 32 + i; // First char is 32
- defaultFont.chars[i].rec.x = (float)currentPosX;
- defaultFont.chars[i].rec.y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
- defaultFont.chars[i].rec.width = (float)charsWidth[i];
- defaultFont.chars[i].rec.height = (float)charsHeight;
+ defaultFont.recs[i].x = (float)currentPosX;
+ defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
+ defaultFont.recs[i].width = (float)charsWidth[i];
+ defaultFont.recs[i].height = (float)charsHeight;
- testPosX += (int)(defaultFont.chars[i].rec.width + (float)charsDivisor);
+ testPosX += (int)(defaultFont.recs[i].width + (float)charsDivisor);
if (testPosX >= defaultFont.texture.width)
{
@@ -229,8 +229,8 @@ extern void LoadFontDefault(void)
currentPosX = 2*charsDivisor + charsWidth[i];
testPosX = currentPosX;
- defaultFont.chars[i].rec.x = (float)charsDivisor;
- defaultFont.chars[i].rec.y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
+ defaultFont.recs[i].x = (float)charsDivisor;
+ defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
}
else currentPosX = testPosX;
@@ -238,9 +238,14 @@ extern void LoadFontDefault(void)
defaultFont.chars[i].offsetX = 0;
defaultFont.chars[i].offsetY = 0;
defaultFont.chars[i].advanceX = 0;
+
+ // Fill character image data from fontClear data
+ defaultFont.chars[i].image = ImageFromImage(imFont, defaultFont.recs[i]);
}
- defaultFont.baseSize = (int)defaultFont.chars[0].rec.height;
+ UnloadImage(imFont);
+
+ defaultFont.baseSize = (int)defaultFont.recs[0].height;
TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
}
@@ -248,8 +253,10 @@ extern void LoadFontDefault(void)
// Unload raylib default font
extern void UnloadFontDefault(void)
{
+ for (int i = 0; i < defaultFont.charsCount; i++) UnloadImage(defaultFont.chars[i].image);
UnloadTexture(defaultFont.texture);
RL_FREE(defaultFont.chars);
+ RL_FREE(defaultFont.recs);
}
#endif // SUPPORT_DEFAULT_FONT
@@ -312,12 +319,21 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
#if defined(SUPPORT_FILEFORMAT_TTF)
if (font.chars != NULL)
{
- Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
+ Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, 2, 0);
font.texture = LoadTextureFromImage(atlas);
+
+ // Update chars[i].image to use alpha, required to be used on ImageDrawText()
+ for (int i = 0; i < font.charsCount; i++)
+ {
+ UnloadImage(font.chars[i].image);
+ font.chars[i].image = ImageFromImage(atlas, font.recs[i]);
+ }
+
UnloadImage(atlas);
}
else font = GetFontDefault();
#else
+ UnloadFont(font);
font = GetFontDefault();
#endif
@@ -415,25 +431,30 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
spriteFont.charsCount = index;
- UnloadImage(fontClear); // Unload processed image once converted to texture
-
// We got tempCharValues and tempCharsRecs populated with chars data
// Now we move temp data to sized charValues and charRecs arrays
spriteFont.chars = (CharInfo *)RL_MALLOC(spriteFont.charsCount*sizeof(CharInfo));
+ spriteFont.recs = (Rectangle *)RL_MALLOC(spriteFont.charsCount*sizeof(Rectangle));
for (int i = 0; i < spriteFont.charsCount; i++)
{
spriteFont.chars[i].value = tempCharValues[i];
- spriteFont.chars[i].rec = tempCharRecs[i];
+
+ // Get character rectangle in the font atlas texture
+ spriteFont.recs[i] = tempCharRecs[i];
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
spriteFont.chars[i].offsetX = 0;
spriteFont.chars[i].offsetY = 0;
spriteFont.chars[i].advanceX = 0;
- spriteFont.chars[i].data = NULL;
+
+ // Fill character image data from fontClear data
+ spriteFont.chars[i].image = ImageFromImage(fontClear, tempCharRecs[i]);
}
- spriteFont.baseSize = (int)spriteFont.chars[0].rec.height;
+ UnloadImage(fontClear); // Unload processed image once converted to texture
+
+ spriteFont.baseSize = (int)spriteFont.recs[0].height;
TraceLog(LOG_INFO, "Image file loaded correctly as Font");
@@ -510,9 +531,9 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
- if (type != FONT_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);
- else chars[i].data = NULL;
+ if (type != FONT_SDF) chars[i].image.data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+ else if (ch != 32) chars[i].image.data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
+ else chars[i].image.data = NULL;
if (type == FONT_BITMAP)
{
@@ -520,13 +541,17 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
// NOTE: For optimum results, bitmap font should be generated at base pixel size
for (int p = 0; p < chw*chh; p++)
{
- if (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
- else chars[i].data[p] = 255;
+ if (((unsigned char *)chars[i].image.data)[p] < BITMAP_ALPHA_THRESHOLD) ((unsigned char *)chars[i].image.data)[p] = 0;
+ else ((unsigned char *)chars[i].image.data)[p] = 255;
}
}
- chars[i].rec.width = (float)chw;
- chars[i].rec.height = (float)chh;
+ // Load characters images
+ chars[i].image.width = chw;
+ chars[i].image.height = chh;
+ chars[i].image.mipmaps = 1;
+ chars[i].image.format = UNCOMPRESSED_GRAYSCALE;
+
chars[i].offsetY += (int)((float)ascent*scaleFactor);
// Get bounding box for character (may be offset to account for chars that dip above or below the line)
@@ -554,19 +579,24 @@ 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
#if defined(SUPPORT_FILEFORMAT_TTF)
-Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod)
+Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod)
{
Image atlas = { 0 };
+ *charRecs = NULL;
+
// In case no chars count provided we suppose default of 95
- charsCount = (charsCount > 0)? charsCount : 95;
+ charsCount = (charsCount > 0) ? charsCount : 95;
+
+ // NOTE: Rectangles memory is loaded here!
+ Rectangle *recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
// Calculate image size based on required pixel area
// NOTE 1: Image is forced to be squared and POT... very conservative!
// 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 < charsCount; i++) requiredArea += ((chars[i].rec.width + 2*padding)*(chars[i].rec.height + 2*padding));
+ for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
float guessSize = sqrtf(requiredArea)*1.25f;
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
@@ -588,21 +618,24 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
for (int i = 0; i < charsCount; i++)
{
// Copy pixel data from fc.data to atlas
- for (int y = 0; y < (int)chars[i].rec.height; y++)
+ for (int y = 0; y < chars[i].image.height; y++)
{
- for (int x = 0; x < (int)chars[i].rec.width; x++)
+ for (int x = 0; x < chars[i].image.width; x++)
{
- ((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = chars[i].data[y*(int)chars[i].rec.width + x];
+ ((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
}
}
- chars[i].rec.x = (float)offsetX;
- chars[i].rec.y = (float)offsetY;
+ // Fill chars rectangles in atlas info
+ recs[i].x = (float)offsetX;
+ recs[i].y = (float)offsetY;
+ recs[i].width = (float)chars[i].image.width;
+ recs[i].height = (float)chars[i].image.height;
// Move atlas position X for next character drawing
- offsetX += ((int)chars[i].rec.width + 2*padding);
+ offsetX += (chars[i].image.width + 2*padding);
- if (offsetX >= (atlas.width - (int)chars[i].rec.width - padding))
+ if (offsetX >= (atlas.width - chars[i].image.width - padding))
{
offsetX = padding;
@@ -629,8 +662,8 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
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;
+ rects[i].w = chars[i].image.width + 2*padding;
+ rects[i].h = chars[i].image.height + 2*padding;
}
// Package rectangles into atlas
@@ -638,17 +671,20 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
for (int i = 0; i < charsCount; i++)
{
- chars[i].rec.x = rects[i].x + (float)padding;
- chars[i].rec.y = rects[i].y + (float)padding;
+ // It return char rectangles in atlas
+ recs[i].x = rects[i].x + (float)padding;
+ recs[i].y = rects[i].y + (float)padding;
+ recs[i].width = (float)chars[i].image.width;
+ recs[i].height = (float)chars[i].image.height;
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 y = 0; y < chars[i].image.height; y++)
{
- for (int x = 0; x < (int)chars[i].rec.width; x++)
+ for (int x = 0; x < chars[i].image.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];
+ ((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
}
}
}
@@ -664,7 +700,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
// Convert image data from GRAYSCALE to GRAY_ALPHA
// WARNING: ImageAlphaMask(&atlas, atlas) does not work in this case, requires manual operation
- unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(imageSize*imageSize*sizeof(unsigned char)*2); // Two channels
+ unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(atlas.width*atlas.height*sizeof(unsigned char)*2); // Two channels
for (int i = 0, k = 0; i < atlas.width*atlas.height; i++, k += 2)
{
@@ -675,6 +711,8 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi
RL_FREE(atlas.data);
atlas.data = dataGrayAlpha;
atlas.format = UNCOMPRESSED_GRAY_ALPHA;
+
+ *charRecs = recs;
return atlas;
}
@@ -686,10 +724,11 @@ void UnloadFont(Font font)
// NOTE: Make sure spriteFont is not default font (fallback)
if (font.texture.id != GetFontDefault().texture.id)
{
- for (int i = 0; i < font.charsCount; i++) RL_FREE(font.chars[i].data);
+ for (int i = 0; i < font.charsCount; i++) UnloadImage(font.chars[i].image);
UnloadTexture(font.texture);
RL_FREE(font.chars);
+ RL_FREE(font.recs);
TraceLog(LOG_DEBUG, "Unloaded sprite font data");
}
@@ -717,11 +756,13 @@ void DrawFPS(int posX, int posY)
DrawText(TextFormat("%2i FPS", fps), posX, posY, 20, LIME);
}
-// Returns next codepoint in a UTF8 encoded `text` scanning until '\0' is found. When a invalid UTF8 byte is encountered we exit as soon
-// as possible and a `?`(0x3f) codepoint is returned. `count` will hold the total number of bytes processed.
-// NOTE: the standard says U+FFFD should be returned in case of errors but that character is not supported by the default font in raylib
+// Returns next codepoint in a UTF8 encoded text, scanning until '\0' is found
+// When a invalid UTF8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
+// Total number of bytes processed are returned as a parameter
+// NOTE: the standard says U+FFFD should be returned in case of errors
+// but that character is not supported by the default font in raylib
// TODO: optimize this code for speed!!
-int GetNextCodepoint(const char *text, int *count)
+int GetNextCodepoint(const char *text, int *bytesProcessed)
{
/*
UTF8 specs from https://www.ietf.org/rfc/rfc3629.txt
@@ -737,40 +778,40 @@ int GetNextCodepoint(const char *text, int *count)
// NOTE: on decode errors we return as soon as possible
- int c = 0x3f; // Codepoint (defaults to `?`)
- int o = (unsigned char)(text[0]); // The first UTF8 octet
- *count = 1;
+ int code = 0x3f; // Codepoint (defaults to '?')
+ int octet = (unsigned char)(text[0]); // The first UTF8 octet
+ *bytesProcessed = 1;
- if (o <= 0x7f)
+ if (octet <= 0x7f)
{
// Only one octet (ASCII range x00-7F)
- c = text[0];
+ code = text[0];
}
- else if ((o & 0xe0) == 0xc0)
+ else if ((octet & 0xe0) == 0xc0)
{
// Two octets
// [0]xC2-DF [1]UTF8-tail(x80-BF)
- unsigned char o1 = text[1];
+ unsigned char octet1 = text[1];
- if ((o1 == '\0') || ((o1 >> 6) != 2)) { *count = 2; return c; } // Unexpected sequence
+ if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
- if ((o >= 0xc2) && (o <= 0xdf))
+ if ((octet >= 0xc2) && (octet <= 0xdf))
{
- c = ((o & 0x1f) << 6) | (o1 & 0x3f);
- *count = 2;
+ code = ((octet & 0x1f) << 6) | (octet1 & 0x3f);
+ *bytesProcessed = 2;
}
}
- else if ((o & 0xf0) == 0xe0)
+ else if ((octet & 0xf0) == 0xe0)
{
// Three octets
- unsigned char o1 = text[1];
- unsigned char o2 = '\0';
+ unsigned char octet1 = text[1];
+ unsigned char octet2 = '\0';
- if ((o1 == '\0') || ((o1 >> 6) != 2)) { *count = 2; return c; } // Unexpected sequence
+ if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
- o2 = text[2];
+ octet2 = text[2];
- if ((o2 == '\0') || ((o2 >> 6) != 2)) { *count = 3; return c; } // Unexpected sequence
+ if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *bytesProcessed = 3; return code; } // Unexpected sequence
/*
[0]xE0 [1]xA0-BF [2]UTF8-tail(x80-BF)
@@ -779,33 +820,33 @@ int GetNextCodepoint(const char *text, int *count)
[0]xEE-EF [1]UTF8-tail [2]UTF8-tail(x80-BF)
*/
- if (((o == 0xe0) && !((o1 >= 0xa0) && (o1 <= 0xbf))) ||
- ((o == 0xed) && !((o1 >= 0x80) && (o1 <= 0x9f)))) { *count = 2; return c; }
+ if (((octet == 0xe0) && !((octet1 >= 0xa0) && (octet1 <= 0xbf))) ||
+ ((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f)))) { *bytesProcessed = 2; return code; }
- if ((o >= 0xe0) && (0 <= 0xef))
+ if ((octet >= 0xe0) && (0 <= 0xef))
{
- c = ((o & 0xf) << 12) | ((o1 & 0x3f) << 6) | (o2 & 0x3f);
- *count = 3;
+ code = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
+ *bytesProcessed = 3;
}
}
- else if ((o & 0xf8) == 0xf0)
+ else if ((octet & 0xf8) == 0xf0)
{
// Four octets
- if (o > 0xf4) return c;
+ if (octet > 0xf4) return code;
- unsigned char o1 = text[1];
- unsigned char o2 = '\0';
- unsigned char o3 = '\0';
+ unsigned char octet1 = text[1];
+ unsigned char octet2 = '\0';
+ unsigned char octet3 = '\0';
- if ((o1 == '\0') || ((o1 >> 6) != 2)) { *count = 2; return c; } // Unexpected sequence
+ if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
- o2 = text[2];
+ octet2 = text[2];
- if ((o2 == '\0') || ((o2 >> 6) != 2)) { *count = 3; return c; } // Unexpected sequence
+ if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *bytesProcessed = 3; return code; } // Unexpected sequence
- o3 = text[3];
+ octet3 = text[3];
- if ((o3 == '\0') || ((o3 >> 6) != 2)) { *count = 4; return c; } // Unexpected sequence
+ if ((octet3 == '\0') || ((octet3 >> 6) != 2)) { *bytesProcessed = 4; return code; } // Unexpected sequence
/*
[0]xF0 [1]x90-BF [2]UTF8-tail [3]UTF8-tail
@@ -813,19 +854,19 @@ int GetNextCodepoint(const char *text, int *count)
[0]xF4 [1]x80-8F [2]UTF8-tail [3]UTF8-tail
*/
- if (((o == 0xf0) && !((o1 >= 0x90) && (o1 <= 0xbf))) ||
- ((o == 0xf4) && !((o1 >= 0x80) && (o1 <= 0x8f)))) { *count = 2; return c; } // Unexpected sequence
+ if (((octet == 0xf0) && !((octet1 >= 0x90) && (octet1 <= 0xbf))) ||
+ ((octet == 0xf4) && !((octet1 >= 0x80) && (octet1 <= 0x8f)))) { *bytesProcessed = 2; return code; } // Unexpected sequence
- if (o >= 0xf0)
+ if (octet >= 0xf0)
{
- c = ((o & 0x7) << 18) | ((o1 & 0x3f) << 12) | ((o2 & 0x3f) << 6) | (o3 & 0x3f);
- *count = 4;
+ code = ((octet & 0x7) << 18) | ((octet1 & 0x3f) << 12) | ((octet2 & 0x3f) << 6) | (octet3 & 0x3f);
+ *bytesProcessed = 4;
}
}
- if (c > 0x10ffff) c = 0x3f; // Codepoints after U+10ffff are invalid
+ if (code > 0x10ffff) code = 0x3f; // Codepoints after U+10ffff are invalid
- return c;
+ return code;
}
@@ -863,13 +904,14 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
for (int i = 0; i < length; i++)
{
- int next = 1;
+ int next = 0;
letter = GetNextCodepoint(&text[i], &next);
- // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
- // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set `next = 1`
- if(letter == 0x3f) next = 1;
index = GetGlyphIndex(font, letter);
- i += next - 1;
+
+ // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
+ // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set 'next = 1'
+ if (letter == 0x3f) next = 1;
+ i += (next - 1);
if (letter == '\n')
{
@@ -881,14 +923,14 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
{
if (letter != ' ')
{
- DrawTexturePro(font.texture, font.chars[index].rec,
+ DrawTexturePro(font.texture, font.recs[index],
(Rectangle){ position.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
position.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
- font.chars[index].rec.width*scaleFactor,
- font.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
+ font.recs[index].width*scaleFactor,
+ font.recs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
}
- if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.chars[index].rec.width*scaleFactor + spacing);
+ if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
else textOffsetX += ((float)font.chars[index].advanceX*scaleFactor + spacing);
}
}
@@ -901,8 +943,7 @@ void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, flo
}
// Draw text using font inside rectangle limits with support for text selection
-void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint,
- int selectStart, int selectLength, Color selectText, Color selectBack)
+void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectText, Color selectBack)
{
int length = strlen(text);
int textOffsetX = 0; // Offset between characters
@@ -916,39 +957,38 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
enum { MEASURE_STATE = 0, DRAW_STATE = 1 };
int state = wordWrap? MEASURE_STATE : DRAW_STATE;
- int startLine = -1; // Index where to begin drawing (where a line begins)
- int endLine = -1; // Index where to stop drawing (where a line ends)
- int lastk = -1; // Holds last value of the character position
+ int startLine = -1; // Index where to begin drawing (where a line begins)
+ int endLine = -1; // Index where to stop drawing (where a line ends)
+ int lastk = -1; // Holds last value of the character position
+
for (int i = 0, k = 0; i < length; i++, k++)
{
int glyphWidth = 0;
- int next = 1;
+ int next = 0;
letter = GetNextCodepoint(&text[i], &next);
- // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
- // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set `next = 1`
- if(letter == 0x3f) next = 1;
index = GetGlyphIndex(font, letter);
+
+ // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
+ // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1
+ if (letter == 0x3f) next = 1;
i += next - 1;
if (letter != '\n')
- {
+ {
glyphWidth = (font.chars[index].advanceX == 0)?
- (int)(font.chars[index].rec.width*scaleFactor + spacing):
+ (int)(font.recs[index].width*scaleFactor + spacing):
(int)(font.chars[index].advanceX*scaleFactor + spacing);
}
- // NOTE: When wordWrap is ON we first measure how much of the text we can draw
- // before going outside of the `rec` container. We store this info inside
- // `startLine` and `endLine` then we change states, draw the text between those two
- // variables then change states again and again recursively until the end of the text
- // (or until we get outside of the container).
- // When wordWrap is OFF we don't need the measure state so we go to the drawing
- // state immediately and begin drawing on the next line before we can get outside
- // the container.
+ // NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
+ // We store this info in startLine and endLine, then we change states, draw the text between those two variables
+ // and change states again and again recursively until the end of the text (or until we get outside of the container).
+ // When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
+ // and begin drawing on the next line before we can get outside the container.
if (state == MEASURE_STATE)
{
- // TODO: there are multiple types of `spaces` in UNICODE, maybe it's a good idea to add support for more
- // see: http://jkorpela.fi/chars/spaces.html
+ // TODO: there are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
+ // See: http://jkorpela.fi/chars/spaces.html
if ((letter == ' ') || (letter == '\t') || (letter == '\n')) endLine = i;
if ((textOffsetX + glyphWidth + 1) >= rec.width)
@@ -979,7 +1019,6 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
lastk = k - 1;
k = tmp;
}
-
}
else
{
@@ -1001,7 +1040,7 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
if ((textOffsetY + (int)(font.baseSize*scaleFactor)) > rec.height) break;
- //draw selected
+ // Draw selected
bool isGlyphSelected = false;
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
{
@@ -1010,14 +1049,14 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
isGlyphSelected = true;
}
- //draw glyph
+ // Draw glyph
if ((letter != ' ') && (letter != '\t'))
{
- DrawTexturePro(font.texture, font.chars[index].rec,
+ DrawTexturePro(font.texture, font.recs[index],
(Rectangle){ rec.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
rec.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
- font.chars[index].rec.width*scaleFactor,
- font.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f,
+ font.recs[index].width*scaleFactor,
+ font.recs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f,
(!isGlyphSelected)? tint : selectText);
}
}
@@ -1076,19 +1115,19 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
{
lenCounter++;
- int next = 1;
+ int next = 0;
letter = GetNextCodepoint(&text[i], &next);
+ index = GetGlyphIndex(font, letter);
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
- // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set `next = 1`
- if(letter == 0x3f) next = 1;
+ // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1
+ if (letter == 0x3f) next = 1;
i += next - 1;
if (letter != '\n')
{
- index = GetGlyphIndex(font, letter);
if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX;
- else textWidth += (font.chars[index].rec.width + font.chars[index].offsetX);
+ else textWidth += (font.recs[index].width + font.chars[index].offsetX);
}
else
{
@@ -1103,7 +1142,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
- Vector2 vec;
+ Vector2 vec = { 0 };
vec.x = tempTextWidth*scaleFactor + (float)((tempLen - 1)*spacing); // Adds chars spacing to measure
vec.y = textHeight*scaleFactor;
@@ -1155,20 +1194,24 @@ unsigned int TextLength(const char *text)
return length;
}
-// Returns total number of characters(codepoints) in a UTF8 encoded `text` until `\0` is found.
-// NOTE: If a invalid UTF8 sequence is encountered a `?`(0x3f) codepoint is counted instead.
+// Returns total number of characters(codepoints) in a UTF8 encoded text, until '\0' is found
+// NOTE: If an invalid UTF8 sequence is encountered a '?'(0x3f) codepoint is counted instead
unsigned int TextCountCodepoints(const char *text)
{
unsigned int len = 0;
- char* ptr = (char*)&text[0];
- while(*ptr != '\0')
+ char *ptr = (char *)&text[0];
+
+ while (*ptr != '\0')
{
int next = 0;
int letter = GetNextCodepoint(ptr, &next);
- if(letter == 0x3f) ptr += 1;
+
+ if (letter == 0x3f) ptr += 1;
else ptr += next;
- ++len;
+
+ len++;
}
+
return len;
}
@@ -1286,17 +1329,28 @@ char *TextInsert(const char *text, const char *insert, int position)
// REQUIRES: strcat()
const char *TextJoin(const char **textList, int count, const char *delimiter)
{
- // TODO: Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
-
static char text[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(text, 0, MAX_TEXT_BUFFER_LENGTH);
+ int totalLength = 0;
int delimiterLen = strlen(delimiter);
for (int i = 0; i < count; i++)
{
- strcat(text, textList[i]);
- if ((delimiterLen > 0) && (i < (count - 1))) strcat(text, delimiter);
+ int textListLength = strlen(textList[i]);
+
+ // Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
+ if ((totalLength + textListLength) < MAX_TEXT_BUFFER_LENGTH)
+ {
+ strcat(text, textList[i]);
+ totalLength += textListLength;
+
+ if ((delimiterLen > 0) && (i < (count - 1)))
+ {
+ strcat(text, delimiter);
+ totalLength += delimiterLen;
+ }
+ }
}
return text;
@@ -1513,27 +1567,26 @@ static Font LoadBMFont(const char *fileName)
TraceLog(LOG_DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
Image imFont = LoadImage(texPath);
+ Image imFontAlpha = ImageCopy(imFont);
if (imFont.format == UNCOMPRESSED_GRAYSCALE)
{
- Image imCopy = ImageCopy(imFont);
-
- for (int i = 0; i < imCopy.width*imCopy.height; i++) ((unsigned char *)imCopy.data)[i] = 0xff;
+ for (int i = 0; i < imFontAlpha.width*imFontAlpha.height; i++) ((unsigned char *)imFontAlpha.data)[i] = 0xff;
- ImageAlphaMask(&imCopy, imFont);
- font.texture = LoadTextureFromImage(imCopy);
- UnloadImage(imCopy);
+ ImageAlphaMask(&imFontAlpha, imFont);
+ font.texture = LoadTextureFromImage(imFontAlpha);
}
else font.texture = LoadTextureFromImage(imFont);
-
+
UnloadImage(imFont);
- RL_FREE(texPath);
+ RL_FREE(texPath);
// Fill font characters info data
font.baseSize = fontSize;
font.charsCount = charsCount;
font.chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo));
+ font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
@@ -1542,16 +1595,22 @@ static Font LoadBMFont(const char *fileName)
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
+
+ // Get character rectangle in the font atlas texture
+ font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
// Save data properly in sprite font
font.chars[i].value = charId;
- font.chars[i].rec = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
font.chars[i].offsetX = charOffsetX;
font.chars[i].offsetY = charOffsetY;
font.chars[i].advanceX = charAdvanceX;
- font.chars[i].data = NULL;
+
+ // Fill character image data from imFont data
+ font.chars[i].image = ImageFromImage(imFontAlpha, font.recs[i]);
}
+ UnloadImage(imFontAlpha);
+
fclose(fntFile);
if (font.texture.id == 0)
diff --git a/src/textures.c b/src/textures.c
index d9ad1ad0..53e22341 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -888,6 +888,16 @@ Image ImageCopy(Image image)
return newImage;
}
+// Create an image from another image piece
+Image ImageFromImage(Image image, Rectangle rec)
+{
+ Image result = ImageCopy(image);
+
+ ImageCrop(&result, rec);
+
+ return result;
+}
+
// Convert image to POT (power-of-two)
// NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5)
void ImageToPOT(Image *image, Color fillColor)
@@ -1274,7 +1284,7 @@ TextureCubemap LoadTextureCubemap(Image image, int layoutType)
// TODO: Image formating does not work with compressed textures!
}
- for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, size*i, size, size });
+ for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, size*i, size, size }, WHITE);
cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format);
if (cubemap.id == 0) TraceLog(LOG_WARNING, "Cubemap image could not be loaded.");
@@ -1476,7 +1486,7 @@ void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, i
Rectangle srcRec = { 0.0f, 0.0f, (float)image->width, (float)image->height };
Rectangle dstRec = { (float)offsetX, (float)offsetY, srcRec.width, srcRec.height };
- ImageDraw(&imTemp, *image, srcRec, dstRec);
+ ImageDraw(&imTemp, *image, srcRec, dstRec, WHITE);
ImageFormat(&imTemp, image->format);
UnloadImage(*image);
*image = imTemp;
@@ -1507,7 +1517,7 @@ void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, i
dstRec.y = 0.0f;
}
- ImageDraw(&imTemp, *image, srcRec, dstRec);
+ ImageDraw(&imTemp, *image, srcRec, dstRec, WHITE);
ImageFormat(&imTemp, image->format);
UnloadImage(*image);
*image = imTemp;
@@ -1757,7 +1767,8 @@ Color *ImageExtractPalette(Image image, int maxPaletteSize, int *extractCount)
}
// Draw an image (source) within an image (destination)
-void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
+// NOTE: Color tint is applied to source image
+void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint)
{
// Security check to avoid program crash
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0) ||
@@ -1823,7 +1834,8 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
UnloadImage(srcCopy); // Source copy not required any more
- Vector4 fsrc, fdst, fout; // float based versions of pixel data
+ Vector4 fsrc, fdst, fout; // Normalized pixel data (ready for operation)
+ Vector4 ftint = ColorNormalize(tint); // Normalized color tint
// Blit pixels, copy source image into destination
// TODO: Maybe out-of-bounds blitting could be considered here instead of so much cropping
@@ -1835,6 +1847,9 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec)
fdst = ColorNormalize(dstPixels[j*(int)dst->width + i]);
fsrc = ColorNormalize(srcPixels[(j - (int)dstRec.y)*(int)dstRec.width + (i - (int)dstRec.x)]);
+
+ // Apply color tint to source image
+ fsrc.x *= ftint.x; fsrc.y *= ftint.y; fsrc.z *= ftint.z; fsrc.w *= ftint.w;
fout.w = fsrc.w + fdst.w*(1.0f - fsrc.w);
@@ -1885,65 +1900,44 @@ Image ImageText(const char *text, int fontSize, Color color)
Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
{
int length = strlen(text);
- int posX = 0;
+
int index; // Index position in sprite font
- unsigned char character; // Current character
+ int letter = 0; // Current character
+ int positionX = 0; // Image drawing position
+ // NOTE: Text image is generated at font base size, later scaled to desired font size
Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing);
- TraceLog(LOG_DEBUG, "Text Image size: %f, %f", imSize.x, imSize.y);
-
- // NOTE: glGetTexImage() not available in OpenGL ES
- // TODO: This is horrible, retrieving font texture from GPU!!!
- // Define ImageFont struct? or include Image spritefont in Font struct?
- Image imFont = GetTextureData(font.texture);
-
- ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Make sure image format could be properly colored!
-
- ImageColorTint(&imFont, tint); // Apply color tint to font
-
// Create image to store text
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
-
+
for (int i = 0; i < length; i++)
{
- if ((unsigned char)text[i] == '\n')
+ int next = 0;
+ letter = GetNextCodepoint(&text[i], &next);
+ index = GetGlyphIndex(font, letter);
+
+ if (letter == 0x3f) next = 1;
+ i += (next - 1);
+
+ if (letter == '\n')
{
// TODO: Support line break
}
else
{
- if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
- {
- // Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
- character = (unsigned char)text[i + 1];
- index = GetGlyphIndex(font, (int)character);
- i++;
- }
- else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
+ if (letter != ' ')
{
- // Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
- character = (unsigned char)text[i + 1];
- index = GetGlyphIndex(font, (int)character + 64);
- i++;
+ ImageDraw(&imText, font.chars[index].image, (Rectangle){ 0, 0, font.chars[index].image.width, font.chars[index].image.height },
+ (Rectangle){ (float)(positionX + font.chars[index].offsetX),(float)font.chars[index].offsetY,
+ font.chars[index].image.width, font.chars[index].image.height }, tint);
}
- else index = GetGlyphIndex(font, (unsigned char)text[i]);
- CharInfo letter = font.chars[index];
-
- if ((unsigned char)text[i] != ' ')
- {
- ImageDraw(&imText, imFont, letter.rec, (Rectangle){ (float)(posX + letter.offsetX),
- (float)letter.offsetY, (float)letter.rec.width, (float)letter.rec.height });
- }
-
- if (letter.advanceX == 0) posX += (int)(letter.rec.width + spacing);
- else posX += letter.advanceX + (int)spacing;
+ if (font.chars[index].advanceX == 0) positionX += (int)(font.recs[index].width + spacing);
+ else positionX += font.chars[index].advanceX + (int)spacing;
}
}
- UnloadImage(imFont);
-
// Scale image depending on text size
if (fontSize > imSize.y)
{
@@ -1965,7 +1959,7 @@ void ImageDrawRectangle(Image *dst, Rectangle rec, Color color)
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
Image imRec = GenImageColor((int)rec.width, (int)rec.height, color);
- ImageDraw(dst, imRec, (Rectangle){ 0, 0, rec.width, rec.height }, rec);
+ ImageDraw(dst, imRec, (Rectangle){ 0, 0, rec.width, rec.height }, rec, WHITE);
UnloadImage(imRec);
}
@@ -1993,7 +1987,7 @@ void ImageDrawTextEx(Image *dst, Vector2 position, Font font, const char *text,
Rectangle srcRec = { 0.0f, 0.0f, (float)imText.width, (float)imText.height };
Rectangle dstRec = { position.x, position.y, (float)imText.width, (float)imText.height };
- ImageDraw(dst, imText, srcRec, dstRec);
+ ImageDraw(dst, imText, srcRec, dstRec, WHITE);
UnloadImage(imText);
}