Improving sprite fonts support...

Support grayscale (8 bit) textures for fonts
Load unordered chars data above char 126
This commit is contained in:
raysan5 2016-10-24 19:11:29 +02:00
parent 1142d4edae
commit 6d34adbd60
2 changed files with 50 additions and 18 deletions

View File

@ -355,7 +355,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float
else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR];
}
if (rec.x > 0)
if (rec.x >= 0)
{
DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor,
position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor,
@ -811,8 +811,12 @@ static SpriteFont LoadBMFont(const char *fileName)
strncat(texPath, texFileName, strlen(texFileName));
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
Image imFont = LoadImage(texPath);
font.texture = LoadTexture(texPath);
if (imFont.format == UNCOMPRESSED_GRAYSCALE) ImageAlphaMask(&imFont, imFont);
font.texture = LoadTextureFromImage(imFont);
font.size = fontSize;
font.numChars = numChars;
font.charValues = (int *)malloc(numChars*sizeof(int));
@ -820,12 +824,14 @@ static SpriteFont LoadBMFont(const char *fileName)
font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2));
font.charAdvanceX = (int *)malloc(numChars*sizeof(int));
UnloadImage(imFont);
free(texPath);
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
bool unorderedChars = false;
int firstChar = 0;
int firstChar = 32;
for (int i = 0; i < numChars; i++)
{
@ -833,8 +839,20 @@ static SpriteFont LoadBMFont(const char *fileName)
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);
if (i == 0) firstChar = charId;
else if (i != (charId - firstChar)) unorderedChars = true;
if ((i == 0) && (charId != FONT_FIRST_CHAR))
{
TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
firstChar = charId;
break;
}
else if ((i < (126 - FONT_FIRST_CHAR)) && (i != (charId - FONT_FIRST_CHAR)))
{
// NOTE: We expect the first 95 chars (32..126) to be ordered for quick drawing access,
// characters above are stored and we look for them (search algorythm) when drawing
TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
unorderedChars = true;
break;
}
// Save data properly in sprite font
font.charValues[i] = charId;
@ -845,9 +863,6 @@ static SpriteFont LoadBMFont(const char *fileName)
fclose(fntFile);
if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
// NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0))
{

View File

@ -694,28 +694,45 @@ void ImageFormat(Image *image, int newFormat)
}
// Apply alpha mask to image
// NOTE 1: Returned image is RGBA - 32bit
// NOTE 1: Returned image is GRAY_ALPHA (16bit) or RGBA (32bit)
// NOTE 2: alphaMask should be same size as image
void ImageAlphaMask(Image *image, Image alphaMask)
{
if (image->format >= COMPRESSED_DXT1_RGB)
if ((image->width != alphaMask.width) || (image->height != alphaMask.height))
{
TraceLog(WARNING, "Alpha mask must be same size as image");
}
else if (image->format >= COMPRESSED_DXT1_RGB)
{
TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats");
return;
}
else
{
// Force mask to be Grayscale
Image mask = ImageCopy(alphaMask);
ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE);
if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE);
// Convert image to RGBA
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8);
// Apply alpha mask to alpha channel
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
// In case image is only grayscale, we just add alpha channel
if (image->format == UNCOMPRESSED_GRAYSCALE)
{
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA);
// Apply alpha mask to alpha channel
for (int i = 0, k = 1; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2)
{
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
}
}
else
{
// Convert image to RGBA
if (image->format != UNCOMPRESSED_R8G8B8A8) ImageFormat(image, UNCOMPRESSED_R8G8B8A8);
// Apply alpha mask to alpha channel
for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
{
((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
}
}
UnloadImage(mask);