Add and optimize text rendering functions
New functions operate on two char*'s in the event strings are not null terminated * MeasureTextViewEx * MeasureTextView * DrawTextViewEx * DrawTextViewPro Rewrote some conditional operations as math in DrawTexturePro to try to get compiler to generate branchless code even in debug mode.
This commit is contained in:
parent
796d96408b
commit
da9c3b379e
|
|
@ -1362,16 +1362,22 @@ RLAPI void UnloadFont(Font font);
|
||||||
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
|
||||||
|
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
|
RLAPI void DrawTextViewEx(Font font, const char* text, const char* textEnd, Vector2 position, float fontSize, float spacing, Color tint);
|
||||||
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
||||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
|
RLAPI void DrawTextViewPro(Font font, const char* text, const char* textEnd, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint);
|
||||||
|
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
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 Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
|
RLAPI int MeasureTextView(const char* text, const char* textEnd, int fontSize); // Measure string width for default font
|
||||||
|
RLAPI Vector2 MeasureTextViewEx(Font font, const char* text, const char* textEnd, float fontSize, float spacing); // Measure string size for Font
|
||||||
|
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
|
||||||
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
|
|
||||||
78
src/rtext.c
78
src/rtext.c
|
|
@ -1015,8 +1015,7 @@ void DrawFPS(int posX, int posY)
|
||||||
Color color = LIME; // Good FPS
|
Color color = LIME; // Good FPS
|
||||||
int fps = GetFPS();
|
int fps = GetFPS();
|
||||||
|
|
||||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
color = (fps >= 30) ? color : (fps >= 15) ? ORANGE : RED;
|
||||||
else if (fps < 15) color = RED; // Low FPS
|
|
||||||
|
|
||||||
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
|
||||||
}
|
}
|
||||||
|
|
@ -1039,20 +1038,18 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text using Font
|
void DrawTextViewEx(Font font, const char* text, const char* textEnd, Vector2 position, float fontSize, float spacing, Color tint)
|
||||||
// NOTE: chars spacing is NOT proportional to fontSize
|
|
||||||
void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
|
|
||||||
{
|
{
|
||||||
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
||||||
|
|
||||||
int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
|
int bytes = textEnd - text; // Total size in bytes of the text, scanned by codepoints in loop
|
||||||
|
|
||||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
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 < size;)
|
for (int i = 0; i < bytes;)
|
||||||
{
|
{
|
||||||
// Get next codepoint from byte string and glyph index in font
|
// Get next codepoint from byte string and glyph index in font
|
||||||
int codepointByteCount = 0;
|
int codepointByteCount = 0;
|
||||||
|
|
@ -1067,24 +1064,46 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 line-height
|
// NOTE: Fixed line spacing of 1.5 line-height
|
||||||
// TODO: Support custom line spacing defined by user
|
// TODO: Support custom line spacing defined by user
|
||||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
textOffsetY += (int)((font.baseSize + font.baseSize / 2.0f) * scaleFactor);
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||||
{
|
{
|
||||||
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
DrawTextCodepoint(font, codepoint, (Vector2) { position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width * scaleFactor + spacing);
|
||||||
else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
|
else textOffsetX += ((float)font.glyphs[index].advanceX * scaleFactor + spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw text using Font and pro parameters (rotation)
|
||||||
|
void DrawTextViewPro(Font font, const char* text, const char* textEnd, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint)
|
||||||
|
{
|
||||||
|
rlPushMatrix();
|
||||||
|
|
||||||
|
rlTranslatef(position.x, position.y, 0.0f);
|
||||||
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
||||||
|
rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||||
|
|
||||||
|
DrawTextViewEx(font, text, textEnd, (Vector2) { 0.0f, 0.0f }, fontSize, spacing, tint);
|
||||||
|
|
||||||
|
rlPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
|
||||||
|
DrawTextViewEx(font, text, text + size, position, fontSize, spacing, tint);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw text using Font and pro parameters (rotation)
|
// Draw text using Font and pro parameters (rotation)
|
||||||
void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint)
|
void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
|
|
@ -1173,14 +1192,32 @@ int MeasureText(const char *text, int fontSize)
|
||||||
return (int)textSize.x;
|
return (int)textSize.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Measure string width for default font
|
||||||
|
int MeasureTextView(const char* text, const char* textEnd, int fontSize) {
|
||||||
|
Vector2 textSize = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
// Check if default font has been loaded
|
||||||
|
if (GetFontDefault().texture.id != 0)
|
||||||
|
{
|
||||||
|
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||||
|
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||||
|
int spacing = fontSize / defaultFontSize;
|
||||||
|
|
||||||
|
textSize = MeasureTextViewEx(GetFontDefault(), text, textEnd, (float)fontSize, (float)spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)textSize.x;
|
||||||
|
}
|
||||||
|
|
||||||
// Measure string size for Font
|
// Measure string size for Font
|
||||||
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
Vector2 MeasureTextViewEx(Font font, const char* text, const char* textEnd, float fontSize, float spacing)
|
||||||
{
|
{
|
||||||
Vector2 textSize = { 0 };
|
Vector2 textSize = { 0 };
|
||||||
|
|
||||||
if ((font.texture.id == 0) || (text == NULL)) return textSize;
|
if ((font.texture.id == 0) || (text == NULL)) return textSize;
|
||||||
|
|
||||||
int size = TextLength(text); // Get size in bytes of text
|
//int size = TextLength(text);
|
||||||
|
int size = textEnd - text; // Get size in bytes of text
|
||||||
int tempByteCounter = 0; // Used to count longer text line num chars
|
int tempByteCounter = 0; // Used to count longer text line num chars
|
||||||
int byteCounter = 0;
|
int byteCounter = 0;
|
||||||
|
|
||||||
|
|
@ -1188,7 +1225,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
float tempTextWidth = 0.0f; // Used to count longer text line width
|
float tempTextWidth = 0.0f; // Used to count longer text line width
|
||||||
|
|
||||||
float textHeight = (float)font.baseSize;
|
float textHeight = (float)font.baseSize;
|
||||||
float scaleFactor = fontSize/(float)font.baseSize;
|
float scaleFactor = fontSize / (float)font.baseSize;
|
||||||
|
|
||||||
int letter = 0; // Current character
|
int letter = 0; // Current character
|
||||||
int index = 0; // Index position in sprite font
|
int index = 0; // Index position in sprite font
|
||||||
|
|
@ -1216,7 +1253,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
byteCounter = 0;
|
byteCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
textHeight += ((float)font.baseSize * 1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
||||||
|
|
@ -1224,11 +1261,16 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
|
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
|
||||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
textSize.x = tempTextWidth * scaleFactor + (float)((tempByteCounter - 1) * spacing); // Adds chars spacing to measure
|
||||||
textSize.y = textHeight*scaleFactor;
|
textSize.y = textHeight * scaleFactor;
|
||||||
|
|
||||||
return textSize;
|
return textSize;
|
||||||
}
|
}
|
||||||
|
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
|
||||||
|
{
|
||||||
|
int size = TextLength(text); // Get size in bytes of text
|
||||||
|
return MeasureTextViewEx(font, text, text + size, fontSize, spacing);
|
||||||
|
}
|
||||||
|
|
||||||
// Get index position for a unicode character on font
|
// Get index position for a unicode character on font
|
||||||
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
|
|
|
||||||
|
|
@ -3546,10 +3546,10 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
|
||||||
float width = (float)texture.width;
|
float width = (float)texture.width;
|
||||||
float height = (float)texture.height;
|
float height = (float)texture.height;
|
||||||
|
|
||||||
bool flipX = false;
|
bool flipX = source.width < 0;
|
||||||
|
|
||||||
if (source.width < 0) { flipX = true; source.width *= -1; }
|
source.width = flipX ? source.width * -1 : source.width;
|
||||||
if (source.height < 0) source.y -= source.height;
|
source.y -= (source.height < 0) ? source.height : 0.0f;
|
||||||
|
|
||||||
Vector2 topLeft = { 0 };
|
Vector2 topLeft = { 0 };
|
||||||
Vector2 topRight = { 0 };
|
Vector2 topRight = { 0 };
|
||||||
|
|
@ -3594,24 +3594,29 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
|
||||||
|
|
||||||
|
float right_edge_x = (source.x + source.width) / width;
|
||||||
|
float left_edge_x = source.x / width;
|
||||||
|
float bottom_edge_y = (source.y + source.height) / height;
|
||||||
|
float top_edge_y = source.y / height;
|
||||||
|
|
||||||
|
// Should communicate the non-branchy version of this expression to the compiler
|
||||||
|
float l_edge = (flipX * right_edge_x) + (!flipX * left_edge_x);//flipX ? right_edge_x : left_edge_x;
|
||||||
|
float r_edge = (flipX * left_edge_x) + (!flipX * right_edge_x);//flipX ? left_edge_x : right_edge_x;
|
||||||
|
|
||||||
// Top-left corner for texture and quad
|
// Top-left corner for texture and quad
|
||||||
if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height);
|
rlTexCoord2f(l_edge, top_edge_y);
|
||||||
else rlTexCoord2f(source.x/width, source.y/height);
|
|
||||||
rlVertex2f(topLeft.x, topLeft.y);
|
rlVertex2f(topLeft.x, topLeft.y);
|
||||||
|
|
||||||
// Bottom-left corner for texture and quad
|
// Bottom-left corner for texture and quad
|
||||||
if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
|
rlTexCoord2f(l_edge, bottom_edge_y);
|
||||||
else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
|
|
||||||
rlVertex2f(bottomLeft.x, bottomLeft.y);
|
rlVertex2f(bottomLeft.x, bottomLeft.y);
|
||||||
|
|
||||||
// Bottom-right corner for texture and quad
|
// Bottom-right corner for texture and quad
|
||||||
if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
|
rlTexCoord2f(r_edge, bottom_edge_y);
|
||||||
else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
|
|
||||||
rlVertex2f(bottomRight.x, bottomRight.y);
|
rlVertex2f(bottomRight.x, bottomRight.y);
|
||||||
|
|
||||||
// Top-right corner for texture and quad
|
// Top-right corner for texture and quad
|
||||||
if (flipX) rlTexCoord2f(source.x/width, source.y/height);
|
rlTexCoord2f(r_edge, top_edge_y);
|
||||||
else rlTexCoord2f((source.x + source.width)/width, source.y/height);
|
|
||||||
rlVertex2f(topRight.x, topRight.y);
|
rlVertex2f(topRight.x, topRight.y);
|
||||||
|
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user