diff --git a/src/raylib.h b/src/raylib.h index 4cd9e4349..9afac7c53 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -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 diff --git a/src/rtext.c b/src/rtext.c index 9eec0059f..3da3832e3 100644 --- a/src/rtext.c +++ b/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 '?' diff --git a/src/rtextures.c b/src/rtextures.c index b5f9998a9..6538ddf15 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -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();