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
|
||||
|
||||
// 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 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 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 DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||
|
||||
// Text font info functions
|
||||
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 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 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
|
||||
|
|
|
|||
78
src/rtext.c
78
src/rtext.c
|
|
@ -1015,8 +1015,7 @@ void DrawFPS(int posX, int posY)
|
|||
Color color = LIME; // Good FPS
|
||||
int fps = GetFPS();
|
||||
|
||||
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
|
||||
else if (fps < 15) color = RED; // Low FPS
|
||||
color = (fps >= 30) ? color : (fps >= 15) ? ORANGE : RED;
|
||||
|
||||
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
|
||||
// NOTE: chars spacing is NOT proportional to fontSize
|
||||
void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
|
||||
void DrawTextViewEx(Font font, const char* text, const char* textEnd, Vector2 position, float fontSize, float spacing, Color tint)
|
||||
{
|
||||
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')
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
else textOffsetX += ((float)font.glyphs[index].advanceX*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);
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
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 };
|
||||
|
||||
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 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 textHeight = (float)font.baseSize;
|
||||
float scaleFactor = fontSize/(float)font.baseSize;
|
||||
float scaleFactor = fontSize / (float)font.baseSize;
|
||||
|
||||
int letter = 0; // Current character
|
||||
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;
|
||||
byteCounter = 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;
|
||||
|
|
@ -1224,11 +1261,16 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
|||
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
||||
textSize.y = textHeight*scaleFactor;
|
||||
textSize.x = tempTextWidth * scaleFactor + (float)((tempByteCounter - 1) * spacing); // Adds chars spacing to measure
|
||||
textSize.y = textHeight * scaleFactor;
|
||||
|
||||
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
|
||||
// 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 height = (float)texture.height;
|
||||
|
||||
bool flipX = false;
|
||||
bool flipX = source.width < 0;
|
||||
|
||||
if (source.width < 0) { flipX = true; source.width *= -1; }
|
||||
if (source.height < 0) source.y -= source.height;
|
||||
source.width = flipX ? source.width * -1 : source.width;
|
||||
source.y -= (source.height < 0) ? source.height : 0.0f;
|
||||
|
||||
Vector2 topLeft = { 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);
|
||||
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
|
||||
if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height);
|
||||
else rlTexCoord2f(source.x/width, source.y/height);
|
||||
rlTexCoord2f(l_edge, top_edge_y);
|
||||
rlVertex2f(topLeft.x, topLeft.y);
|
||||
|
||||
// Bottom-left corner for texture and quad
|
||||
if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
|
||||
else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
|
||||
rlTexCoord2f(l_edge, bottom_edge_y);
|
||||
rlVertex2f(bottomLeft.x, bottomLeft.y);
|
||||
|
||||
// Bottom-right corner for texture and quad
|
||||
if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
|
||||
else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
|
||||
rlTexCoord2f(r_edge, bottom_edge_y);
|
||||
rlVertex2f(bottomRight.x, bottomRight.y);
|
||||
|
||||
// Top-right corner for texture and quad
|
||||
if (flipX) rlTexCoord2f(source.x/width, source.y/height);
|
||||
else rlTexCoord2f((source.x + source.width)/width, source.y/height);
|
||||
rlTexCoord2f(r_edge, top_edge_y);
|
||||
rlVertex2f(topRight.x, topRight.y);
|
||||
|
||||
rlEnd();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user