Update C sources

This commit is contained in:
Milan Nikolic 2021-05-25 14:35:17 +02:00
parent 9d258bad65
commit c1525b67af
No known key found for this signature in database
GPG key ID: 9229D0EAA3AA4E75
68 changed files with 34056 additions and 25957 deletions

View file

@ -27,7 +27,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2020 Ramon Santamaria (@raysan5)
* Copyright (c) 2013-2021 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.
@ -128,7 +128,8 @@ extern void LoadFontDefault(void)
// NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
defaultFont.charsCount = 224; // Number of chars included in our default font
defaultFont.charsCount = 224; // Number of chars included in our default font
defaultFont.charsPadding = 0; // Characters padding
// Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct Font without creating large global variables
@ -193,9 +194,9 @@ extern void LoadFontDefault(void)
//----------------------------------------------------------------------
Image imFont = {
.data = calloc(128*128, 2), // 2 bytes per pixel (gray + alpha)
.width = 128,
.width = 128,
.height = 128,
.format = UNCOMPRESSED_GRAY_ALPHA,
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA,
.mipmaps = 1
};
@ -302,6 +303,9 @@ Font LoadFont(const char *fileName)
#ifndef FONT_TTF_DEFAULT_FIRST_CHAR
#define FONT_TTF_DEFAULT_FIRST_CHAR 32 // TTF font generation default first char for image sprite font (32-Space)
#endif
#ifndef FONT_TTF_DEFAULT_CHARS_PADDING
#define FONT_TTF_DEFAULT_CHARS_PADDING 4 // TTF font generation default chars padding
#endif
Font font = { 0 };
@ -324,7 +328,7 @@ 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, 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)
return font;
}
@ -336,29 +340,18 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
{
Font font = { 0 };
#if defined(SUPPORT_FILEFORMAT_TTF)
font.baseSize = fontSize;
font.charsCount = (charsCount > 0)? charsCount : 95;
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
// Loading file to memory
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
if (font.chars != NULL)
if (fileData != NULL)
{
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, 2, 0);
font.texture = LoadTextureFromImage(atlas);
// Loading font from memory data
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, charsCount);
// 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);
RL_FREE(fileData);
}
else font = GetFontDefault();
#else
font = GetFontDefault();
#endif
return font;
}
@ -369,7 +362,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
#ifndef MAX_GLYPHS_FROM_IMAGE
#define MAX_GLYPHS_FROM_IMAGE 256 // Maximum number of glyphs supported on image scan
#endif
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
int charSpacing = 0;
@ -383,7 +376,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
int tempCharValues[MAX_GLYPHS_FROM_IMAGE];
Rectangle tempCharRecs[MAX_GLYPHS_FROM_IMAGE];
Color *pixels = GetImageData(image);
Color *pixels = LoadImageColors(image);
// Parse image data to get charSpacing and lineSpacing
for (y = 0; y < image.height; y++)
@ -439,7 +432,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}
// NOTE: We need to remove key color borders from image to avoid weird
// artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR
// artifacts on texture scaling when using TEXTURE_FILTER_BILINEAR or TEXTURE_FILTER_TRILINEAR
for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK;
// Create a new image with the processed color data (key color replaced by BLANK)
@ -447,7 +440,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
.data = pixels,
.width = image.width,
.height = image.height,
.format = UNCOMPRESSED_R8G8B8A8,
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
.mipmaps = 1
};
@ -456,6 +449,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
font.charsCount = index;
font.charsPadding = 0;
// We got tempCharValues and tempCharsRecs populated with chars data
// Now we move temp data to sized charValues and charRecs arrays
@ -485,9 +479,51 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
return font;
}
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount)
{
Font font = { 0 };
char fileExtLower[16] = { 0 };
strcpy(fileExtLower, TextToLower(fileType));
#if defined(SUPPORT_FILEFORMAT_TTF)
if (TextIsEqual(fileExtLower, ".ttf") ||
TextIsEqual(fileExtLower, ".otf"))
{
font.baseSize = fontSize;
font.charsCount = (charsCount > 0)? charsCount : 95;
font.charsPadding = 0;
font.chars = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
if (font.chars != NULL)
{
font.charsPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, font.charsPadding, 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
font = GetFontDefault();
#endif
return font;
}
// 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, int type)
// NOTE: Requires TTF font memory data and can generate SDF data
CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type)
{
// NOTE: Using some SDF generation default values,
// trades off precision with ability to handle *smaller* sizes
@ -507,18 +543,14 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
CharInfo *chars = NULL;
#if defined(SUPPORT_FILEFORMAT_TTF)
// Load font data (including pixel data) from TTF file
// NOTE: Loaded information should be enough to generate
// font image atlas, using any packaging method
unsigned int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
// Load font data (including pixel data) from TTF memory file
// NOTE: Loaded information should be enough to generate font image atlas, using any packaging method
if (fileData != NULL)
{
int genFontChars = false;
stbtt_fontinfo fontInfo = { 0 };
if (stbtt_InitFont(&fontInfo, fileData, 0)) // Init font for data reading
if (stbtt_InitFont(&fontInfo, (unsigned char *)fileData, 0)) // Init font for data reading
{
// Calculate font scale factor
float scaleFactor = stbtt_ScaleForPixelHeight(&fontInfo, (float)fontSize);
@ -566,7 +598,7 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
chars[i].image.width = chw;
chars[i].image.height = chh;
chars[i].image.mipmaps = 1;
chars[i].image.format = UNCOMPRESSED_GRAYSCALE;
chars[i].image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
chars[i].offsetY += (int)((float)ascent*scaleFactor);
@ -577,10 +609,10 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
.data = calloc(chars[i].advanceX*fontSize, 2),
.width = chars[i].advanceX,
.height = fontSize,
.format = UNCOMPRESSED_GRAYSCALE,
.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE,
.mipmaps = 1
};
chars[i].image = imSpace;
}
@ -607,7 +639,6 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
}
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
RL_FREE(fileData);
if (genFontChars) RL_FREE(fontChars);
}
#endif
@ -648,7 +679,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
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.format = UNCOMPRESSED_GRAYSCALE;
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
atlas.mipmaps = 1;
// DEBUG: We can see padding in the generated image setting a gray background...
@ -752,7 +783,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
RL_FREE(atlas.data);
atlas.data = dataGrayAlpha;
atlas.format = UNCOMPRESSED_GRAY_ALPHA;
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
*charRecs = recs;
@ -760,27 +791,39 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
}
#endif
// Unload font chars info data (RAM)
void UnloadFontData(CharInfo *chars, int charsCount)
{
for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image);
RL_FREE(chars);
}
// Unload Font from GPU memory (VRAM)
void UnloadFont(Font font)
{
// NOTE: Make sure font is not default font (fallback)
if (font.texture.id != GetFontDefault().texture.id)
{
for (int i = 0; i < font.charsCount; i++) UnloadImage(font.chars[i].image);
UnloadFontData(font.chars, font.charsCount);
UnloadTexture(font.texture);
RL_FREE(font.chars);
RL_FREE(font.recs);
TRACELOGD("FONT: Unloaded font data from RAM and VRAM");
}
}
// Shows current FPS on top-left corner
// Draw current FPS
// NOTE: Uses default font
void DrawFPS(int posX, int posY)
{
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, LIME);
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
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
}
// Draw text (using default font)
@ -801,30 +844,18 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
}
}
// Draw one character (codepoint)
void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float scale, Color tint)
{
// Character index position in sprite font
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
int index = GetGlyphIndex(font, codepoint);
// Character rectangle on screen
// NOTE: Quad is scaled proportionally to base character width-height
Rectangle rec = { position.x, position.y, font.recs[index].width*scale, font.recs[index].height*scale };
DrawTexturePro(font.texture, font.recs[index], rec, (Vector2){ 0, 0 }, 0.0f, tint);
}
// Draw text using Font
// NOTE: chars spacing is NOT proportional to fontSize
void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
{
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
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
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
for (int i = 0; i < length;)
{
@ -848,12 +879,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
{
if ((codepoint != ' ') && (codepoint != '\t'))
{
Rectangle rec = { position.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
position.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
font.recs[index].width*scaleFactor,
font.recs[index].height*scaleFactor };
DrawTexturePro(font.texture, font.recs[index], rec, (Vector2){ 0, 0 }, 0.0f, tint);
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
}
if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
@ -873,7 +899,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 selectTint, Color selectBackTint)
{
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
int textOffsetY = 0; // Offset between lines (on line break '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw
@ -976,14 +1002,10 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
isGlyphSelected = true;
}
// Draw current chracter glyph
// Draw current character glyph
if ((codepoint != ' ') && (codepoint != '\t'))
{
DrawTexturePro(font.texture, font.recs[index],
(Rectangle){ rec.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
rec.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
font.recs[index].width*scaleFactor, font.recs[index].height*scaleFactor },
(Vector2){ 0, 0 }, 0.0f, (!isGlyphSelected)? tint : selectTint);
DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint);
}
}
@ -1005,6 +1027,30 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
}
}
// Draw one character (codepoint)
void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint)
{
// Character index position in sprite font
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
int index = GetGlyphIndex(font, codepoint);
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
// Character destination rectangle on screen
// NOTE: We consider charsPadding on drawing
Rectangle dstRec = { position.x + font.chars[index].offsetX*scaleFactor - (float)font.charsPadding*scaleFactor,
position.y + font.chars[index].offsetY*scaleFactor - (float)font.charsPadding*scaleFactor,
(font.recs[index].width + 2.0f*font.charsPadding)*scaleFactor,
(font.recs[index].height + 2.0f*font.charsPadding)*scaleFactor };
// Character source rectangle from font texture atlas
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding,
font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding };
// Draw the character texture on the screen
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
}
// Measure string width for default font
int MeasureText(const char *text, int fontSize)
{
@ -1080,7 +1126,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
// Returns index position for a unicode character on spritefont
int GetGlyphIndex(Font font, int codepoint)
{
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
#define GLYPH_NOTFOUND_CHAR_FALLBACK 63 // Character used if requested codepoint is not found: '?'
#endif
@ -1127,7 +1173,7 @@ const char *TextFormat(const char *text, ...)
#ifndef MAX_TEXTFORMAT_BUFFERS
#define MAX_TEXTFORMAT_BUFFERS 4 // Maximum number of static buffers for text formatting
#endif
// We create an array of buffers so strings don't expire until MAX_TEXTFORMAT_BUFFERS invocations
static char buffers[MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH] = { 0 };
static int index = 0;
@ -1137,7 +1183,7 @@ const char *TextFormat(const char *text, ...)
va_list args;
va_start(args, text);
vsprintf(currentBuffer, text, args);
vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
va_end(args);
index += 1; // Move to next buffer for next function call
@ -1231,7 +1277,7 @@ char *TextReplace(char *text, const char *replace, const char *by)
{
// Sanity checks and initialization
if (!text || !replace || !by) return NULL;
char *result;
char *insertPoint; // Next insert point
@ -1327,6 +1373,7 @@ const char *TextJoin(const char **textList, int count, const char *delimiter)
}
// Split string into multiple strings
// REQUIRES: memset()
const char **TextSplit(const char *text, char delimiter, int *count)
{
// NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
@ -1388,6 +1435,7 @@ int TextFindIndex(const char *text, const char *find)
}
// Get upper case version of provided string
// REQUIRES: toupper()
const char *TextToUpper(const char *text)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
@ -1409,6 +1457,7 @@ const char *TextToUpper(const char *text)
}
// Get lower case version of provided string
// REQUIRES: tolower()
const char *TextToLower(const char *text)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
@ -1427,6 +1476,7 @@ const char *TextToLower(const char *text)
}
// Get Pascal case notation version of provided string
// REQUIRES: toupper()
const char *TextToPascal(const char *text)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
@ -1450,7 +1500,9 @@ const char *TextToPascal(const char *text)
return buffer;
}
// Encode text codepoint into utf8 text (memory must be freed!)
// Encode text codepoint into utf8 text
// REQUIRES: memcpy()
// WARNING: Allocated memory should be manually freed
char *TextToUtf8(int *codepoints, int length)
{
// We allocate enough memory fo fit all possible codepoints
@ -1513,6 +1565,7 @@ RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength)
}
// Get all codepoints in a string, codepoints count returned by parameters
// REQUIRES: memset()
int *GetCodepoints(const char *text, int *count)
{
static int codepoints[MAX_TEXT_UNICODE_CHARS] = { 0 };
@ -1560,7 +1613,7 @@ int GetCodepointsCount(const char *text)
// 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!!
// TODO: Optimize this code for speed!!
int GetNextCodepoint(const char *text, int *bytesProcessed)
{
/*
@ -1673,6 +1726,7 @@ int GetNextCodepoint(const char *text, int *bytesProcessed)
#if defined(SUPPORT_FILEFORMAT_FNT)
// Read a line from memory
// REQUIRES: memcpy()
// NOTE: Returns the number of bytes read
static int GetLine(const char *origin, char *buffer, int maxLength)
{
@ -1695,7 +1749,7 @@ static Font LoadBMFont(const char *fileName)
int fontSize = 0;
int charsCount = 0;
int imWidth = 0;
int imHeight = 0;
char imFileName[129];
@ -1707,7 +1761,7 @@ static Font LoadBMFont(const char *fileName)
if (fileText == NULL) return font;
char *fileTextPtr = fileText;
// NOTE: We skip first line, it contains no useful information
int lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
fileTextPtr += (lineBytes + 1);
@ -1756,14 +1810,14 @@ static Font LoadBMFont(const char *fileName)
Image imFont = LoadImage(imPath);
if (imFont.format == UNCOMPRESSED_GRAYSCALE)
if (imFont.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
{
// Convert image to GRAYSCALE + ALPHA, using the mask as the alpha channel
Image imFontAlpha = {
.data = calloc(imFont.width*imFont.height, 2),
.width = imFont.width,
.height = imFont.height,
.format = UNCOMPRESSED_GRAY_ALPHA,
.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA,
.mipmaps = 1
};
@ -1772,7 +1826,7 @@ static Font LoadBMFont(const char *fileName)
((unsigned char *)(imFontAlpha.data))[p] = 0xff;
((unsigned char *)(imFontAlpha.data))[p + 1] = ((unsigned char *)imFont.data)[i];
}
UnloadImage(imFont);
imFont = imFontAlpha;
}
@ -1784,6 +1838,7 @@ static Font LoadBMFont(const char *fileName)
// Fill font characters info data
font.baseSize = fontSize;
font.charsCount = charsCount;
font.charsPadding = 0;
font.chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo));
font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
@ -1810,7 +1865,7 @@ static Font LoadBMFont(const char *fileName)
}
UnloadImage(imFont);
RL_FREE(fileText);
UnloadFileText(fileText);
if (font.texture.id == 0)
{