Merge branch 'raysan5:master' into master

This commit is contained in:
oblerion 2024-02-03 20:10:41 +01:00 committed by GitHub
commit ec996ad536
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 347 additions and 35 deletions

View File

@ -9,7 +9,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | https://github.com/raysan5/raylib |
| raylib-beef | **5.0** | [Beef](https://www.beeflang.org/) | MIT | https://github.com/Starpelly/raylib-beef |
| raylib-boo | 3.7 | [Boo](http://boo-language.github.io/)| MIT | https://github.com/Rabios/raylib-boo |
| Raylib-cs | 4.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | https://github.com/ChrisDill/Raylib-cs |
| Raylib-cs | 5.0 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | https://github.com/ChrisDill/Raylib-cs |
| Raylib-CsLo | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | https://github.com/NotNotTech/Raylib-CsLo |
| cl-raylib | 4.0 | [Common Lisp](https://common-lisp.net/) | MIT | https://github.com/longlene/cl-raylib |
| claylib/wrap | 4.5 | [Common Lisp](https://common-lisp.net/) | Zlib | https://github.com/defun-games/claylib |

View File

@ -181,6 +181,7 @@
// Selected desired font fileformats to be supported for loading
#define SUPPORT_FILEFORMAT_FNT 1
#define SUPPORT_FILEFORMAT_TTF 1
#define SUPPORT_FILEFORMAT_BDF 1
// Support text management functions
// If not defined, still some functions are supported: TextLength(), TextFormat()

View File

@ -1081,8 +1081,9 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
int waveDataSize = wave.frameCount*wave.channels*wave.sampleSize/8;
// NOTE: Text data buffer size is estimated considering wave data size in bytes
// and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(waveDataSize*6 + 2000, sizeof(char));
// and requiring 12 char bytes for every byte; the actual size varies, but
// the longest possible char being appended is "%.4ff,\n ", which is 12 bytes.
char *txtData = (char *)RL_CALLOC(waveDataSize*12 + 2000, sizeof(char));
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "\n//////////////////////////////////////////////////////////////////////////////////\n");

View File

@ -12,6 +12,7 @@
*
* #define SUPPORT_FILEFORMAT_FNT
* #define SUPPORT_FILEFORMAT_TTF
* #define SUPPORT_FILEFORMAT_BDF
* Selected desired fileformats to be supported for loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
@ -70,14 +71,27 @@
#include <stdarg.h> // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
#if defined(SUPPORT_FILEFORMAT_TTF)
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define STB_RECT_PACK_IMPLEMENTATION
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
#include "external/stb_rect_pack.h" // Required for: ttf/bdf font rectangles packaging
#include <math.h> // Required for: ttf/bdf font rectangles packaging
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic pop
#endif
#endif
#if defined(SUPPORT_FILEFORMAT_TTF)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION
@ -127,6 +141,9 @@ static Font defaultFont = { 0 };
#if defined(SUPPORT_FILEFORMAT_FNT)
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
#endif
#if defined(SUPPORT_FILEFORMAT_BDF)
static GlyphInfo *LoadBDFFontData(const unsigned char *fileData, int dataSize, int *codepoints, int codepointCount, int* outFontSize);
#endif
static int textLineSpacing = 15; // Text vertical line spacing in pixels
#if defined(SUPPORT_DEFAULT_FONT)
@ -334,6 +351,10 @@ Font LoadFont(const char *fileName)
#if defined(SUPPORT_FILEFORMAT_FNT)
if (IsFileExtension(fileName, ".fnt")) font = LoadBMFont(fileName);
else
#endif
#if defined(SUPPORT_FILEFORMAT_BDF)
if (IsFileExtension(fileName, ".bdf")) font = LoadFontEx(fileName, FONT_TTF_DEFAULT_SIZE, NULL, FONT_TTF_DEFAULT_NUMCHARS);
else
#endif
{
Image image = LoadImage(fileName);
@ -355,7 +376,7 @@ Font LoadFont(const char *fileName)
return font;
}
// Load Font from TTF font file with generation parameters
// Load Font from TTF or BDF font file with generation parameters
// NOTE: You can pass an array with desired characters, those characters should be available in the font
// if array is NULL, default char set is selected 32..126
Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount)
@ -511,35 +532,49 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
char fileExtLower[16] = { 0 };
strcpy(fileExtLower, TextToLower(fileType));
font.baseSize = fontSize;
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
font.glyphPadding = 0;
#if defined(SUPPORT_FILEFORMAT_TTF)
if (TextIsEqual(fileExtLower, ".ttf") ||
TextIsEqual(fileExtLower, ".otf"))
{
font.baseSize = fontSize;
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
font.glyphPadding = 0;
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
if (font.glyphs != NULL)
{
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
font.texture = LoadTextureFromImage(atlas);
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.glyphCount; i++)
{
UnloadImage(font.glyphs[i].image);
font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
}
UnloadImage(atlas);
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
}
else font = GetFontDefault();
}
else
#endif
#if defined(SUPPORT_FILEFORMAT_BDF)
if (TextIsEqual(fileExtLower, ".bdf"))
{
font.glyphs = LoadBDFFontData(fileData, dataSize, codepoints, font.glyphCount, &font.baseSize);
}
else
#endif
{
font.glyphs = NULL;
}
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
if (font.glyphs != NULL)
{
font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
font.texture = LoadTextureFromImage(atlas);
// Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.glyphCount; i++)
{
UnloadImage(font.glyphs[i].image);
font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
}
UnloadImage(atlas);
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
}
else font = GetFontDefault();
#else
font = GetFontDefault();
#endif
@ -699,7 +734,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// Generate image font atlas using chars info
// NOTE: Packing method: 0-Default, 1-Skyline
#if defined(SUPPORT_FILEFORMAT_TTF)
#if defined(SUPPORT_FILEFORMAT_TTF) || defined(SUPPORT_FILEFORMAT_BDF)
Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod)
{
Image atlas = { 0 };
@ -1257,7 +1292,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
float textWidth = 0.0f;
float tempTextWidth = 0.0f; // Used to count longer text line width
float textHeight = (float)font.baseSize;
float textHeight = fontSize;
float scaleFactor = fontSize/(float)font.baseSize;
int letter = 0; // Current character
@ -1294,7 +1329,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing);
textSize.y = textHeight*scaleFactor;
textSize.y = textHeight;
return textSize;
}
@ -2036,18 +2071,21 @@ int GetCodepointPrevious(const char *text, int *codepointSize)
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
#if defined(SUPPORT_FILEFORMAT_FNT)
#if defined(SUPPORT_FILEFORMAT_FNT) || defined(SUPPORT_FILEFORMAT_BDF)
// Read a line from memory
// REQUIRES: memcpy()
// NOTE: Returns the number of bytes read
static int GetLine(const char *origin, char *buffer, int maxLength)
{
int count = 0;
for (; count < maxLength; count++) if (origin[count] == '\n') break;
for (; count < maxLength - 1; count++) if (origin[count] == '\n') break;
memcpy(buffer, origin, count);
buffer[count] = '\0';
return count;
}
#endif
#if defined(SUPPORT_FILEFORMAT_FNT)
// Load a BMFont file (AngelCode font file)
// REQUIRES: strstr(), sscanf(), strrchr(), memcpy()
static Font LoadBMFont(const char *fileName)
@ -2213,4 +2251,276 @@ static Font LoadBMFont(const char *fileName)
#endif
#if defined(SUPPORT_FILEFORMAT_BDF)
// Convert hexadecimal to decimal (single digit)
static char HexToInt(char hex) {
if (hex >= '0' && hex <= '9')
{
return hex - '0';
}
else if (hex >= 'a' && hex <= 'f')
{
return hex - 'a' + 10;
}
else if (hex >= 'A' && hex <= 'F')
{
return hex - 'A' + 10;
}
else
{
return 0;
}
}
// Load font data for further use
// NOTE: Requires BDF font memory data
static GlyphInfo *LoadBDFFontData(const unsigned char *fileData, int dataSize, int *codepoints, int codepointCount, int* outFontSize)
{
#define MAX_BUFFER_SIZE 256
char buffer[MAX_BUFFER_SIZE] = { 0 };
GlyphInfo *glyphs = NULL;
bool genFontChars = false;
int totalReadBytes = 0; // Data bytes read (total)
int readBytes = 0; // Data bytes read (line)
int readVars = 0; // Variables filled by sscanf()
const char *fileText = (const char*)fileData;
const char *fileTextPtr = fileText;
bool fontMalformed = false; // Is the font malformed
bool fontStarted = false; // Has font started (STARTFONT)
int fontBBw = 0; // Font base character bounding box width
int fontBBh = 0; // Font base character bounding box height
int fontBBxoff0 = 0; // Font base character bounding box X0 offset
int fontBByoff0 = 0; // Font base character bounding box Y0 offset
int fontAscent = 0; // Font ascent
bool charStarted = false; // Has character started (STARTCHAR)
bool charBitmapStarted = false; // Has bitmap data started (BITMAP)
int charBitmapNextRow = 0; // Y position for the next row of bitmap data
int charEncoding = -1; // The unicode value of the character (-1 if not set)
int charBBw = 0; // Character bounding box width
int charBBh = 0; // Character bounding box height
int charBBxoff0 = 0; // Character bounding box X0 offset
int charBByoff0 = 0; // Character bounding box Y0 offset
int charDWidthX = 0; // Character advance X
int charDWidthY = 0; // Character advance Y (unused)
GlyphInfo *charGlyphInfo = NULL; // Pointer to output glyph info (NULL if not set)
if (fileData == NULL) return glyphs;
// In case no chars count provided, default to 95
codepointCount = (codepointCount > 0)? codepointCount : 95;
// Fill fontChars in case not provided externally
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
if (codepoints == NULL)
{
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
genFontChars = true;
}
glyphs = (GlyphInfo *)RL_CALLOC(codepointCount, sizeof(GlyphInfo));
while (totalReadBytes <= dataSize)
{
readBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
totalReadBytes += (readBytes + 1);
fileTextPtr += (readBytes + 1);
// COMMENT
if (strstr(buffer, "COMMENT") != NULL) continue; // Ignore line
if (charStarted)
{
// ENDCHAR
if (strstr(buffer, "ENDCHAR") != NULL)
{
charStarted = false;
continue;
}
if (charBitmapStarted)
{
if (charGlyphInfo != NULL) {
int pixelY = charBitmapNextRow++;
if (pixelY >= charGlyphInfo->image.height)
{
break;
}
for (int x = 0; x < readBytes; x++)
{
char byte = HexToInt(buffer[x]);
for (int bitX = 0; bitX < 4; bitX++)
{
int pixelX = ((x * 4) + bitX);
if (pixelX >= charGlyphInfo->image.width)
{
break;
}
if ((byte & (8 >> bitX)) > 0)
{
((unsigned char*)charGlyphInfo->image.data)[(pixelY * charGlyphInfo->image.width) + pixelX] = 255;
}
}
}
}
continue;
}
// ENCODING
if (strstr(buffer, "ENCODING") != NULL)
{
readVars = sscanf(buffer, "ENCODING %i", &charEncoding);
continue;
}
// BBX
if (strstr(buffer, "BBX") != NULL)
{
readVars = sscanf(buffer, "BBX %i %i %i %i", &charBBw, &charBBh, &charBBxoff0, &charBByoff0);
continue;
}
// DWIDTH
if (strstr(buffer, "DWIDTH") != NULL)
{
readVars = sscanf(buffer, "DWIDTH %i %i", &charDWidthX, &charDWidthY);
continue;
}
// BITMAP
if (strstr(buffer, "BITMAP") != NULL)
{
// Search for glyph index in codepoints
charGlyphInfo = NULL;
for (int codepointIndex = 0; codepointIndex < codepointCount; codepointIndex++)
{
if (codepoints[codepointIndex] == charEncoding)
{
charGlyphInfo = &glyphs[codepointIndex];
break;
}
}
// Init glyph info
if (charGlyphInfo != NULL)
{
charGlyphInfo->value = charEncoding;
charGlyphInfo->offsetX = charBBxoff0 + fontBByoff0;
charGlyphInfo->offsetY = fontBBh - (charBBh + charBByoff0 + fontBByoff0 + fontAscent);
charGlyphInfo->advanceX = charDWidthX;
charGlyphInfo->image.data = RL_CALLOC(charBBw * charBBh, 1);
charGlyphInfo->image.width = charBBw;
charGlyphInfo->image.height = charBBh;
charGlyphInfo->image.mipmaps = 1;
charGlyphInfo->image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
}
charBitmapStarted = true;
charBitmapNextRow = 0;
continue;
}
}
else if (fontStarted)
{
// ENDFONT
if (strstr(buffer, "ENDFONT") != NULL)
{
fontStarted = false;
break;
}
// SIZE
if (strstr(buffer, "SIZE") != NULL)
{
if (outFontSize != NULL)
{
readVars = sscanf(buffer, "SIZE %i", outFontSize);
}
continue;
}
// PIXEL_SIZE
if (strstr(buffer, "PIXEL_SIZE") != NULL)
{
if (outFontSize != NULL)
{
readVars = sscanf(buffer, "PIXEL_SIZE %i", outFontSize);
}
continue;
}
// FONTBOUNDINGBOX
if (strstr(buffer, "FONTBOUNDINGBOX") != NULL)
{
readVars = sscanf(buffer, "FONTBOUNDINGBOX %i %i %i %i", &fontBBw, &fontBBh, &fontBBxoff0, &fontBByoff0);
continue;
}
// FONT_ASCENT
if (strstr(buffer, "FONT_ASCENT") != NULL)
{
readVars = sscanf(buffer, "FONT_ASCENT %i", &fontAscent);
continue;
}
// STARTCHAR
if (strstr(buffer, "STARTCHAR") != NULL)
{
charStarted = true;
charEncoding = -1;
charGlyphInfo = NULL;
charBBw = 0;
charBBh = 0;
charBBxoff0 = 0;
charBByoff0 = 0;
charDWidthX = 0;
charDWidthY = 0;
charGlyphInfo = NULL;
charBitmapStarted = false;
charBitmapNextRow = 0;
continue;
}
}
else
{
// STARTFONT
if (strstr(buffer, "STARTFONT") != NULL)
{
if (fontStarted)
{
fontMalformed = true;
break;
}
else
{
fontStarted = true;
continue;
}
}
}
}
if (genFontChars) RL_FREE(codepoints);
if (fontMalformed)
{
RL_FREE(glyphs);
glyphs = NULL;
}
return glyphs;
}
#endif
#endif // SUPPORT_MODULE_RTEXT