Browse Source

ADDED: DrawTextRec() and example

pull/708/head
raysan5 6 years ago
parent
commit
0619571149
4 changed files with 247 additions and 1 deletions
  1. +120
    -0
      examples/text/text_draw_inside_rectangle.c
  2. BIN
      examples/text/text_draw_inside_rectangle.png
  3. +2
    -1
      src/raylib.h
  4. +125
    -0
      src/text.c

+ 120
- 0
examples/text/text_draw_inside_rectangle.c View File

@ -0,0 +1,120 @@
/*******************************************************************************************
*
* raylib [text] example - Draw text inside a rectangle
*
* This example has been created using raylib 2.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2018 Vlad Adrian (@demizdor)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle");
char text[] = "Text cannot escape\tthis container\t...word wrap also works when active so here's\
a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\
tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget.";
bool resizing = false;
bool wordWrap = true;
Rectangle container = { 25, 25, screenWidth - 50, screenHeight - 250};
Rectangle resizer = { container.x + container.width - 17, container.y + container.height - 17, 14, 14 };
// Minimum width and heigh for the container rectangle
const int minWidth = 60;
const int minHeight = 60;
const int maxWidth = screenWidth - 50;
const int maxHeight = screenHeight - 160;
Vector2 lastMouse = { 0, 0 }; // Stores last mouse coordinates
Color borderColor = MAROON; // Container border color
Font font = GetFontDefault(); // Get default system font
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE)) wordWrap = !wordWrap;
Vector2 mouse = GetMousePosition();
// Check if the mouse is inside the container and toggle border color
if (CheckCollisionPointRec(mouse, container)) borderColor = Fade(MAROON, 0.4f);
else if (!resizing) borderColor = MAROON;
// Container resizing logic
if (resizing)
{
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) resizing = false;
int width = container.width + (mouse.x - lastMouse.x);
container.width = (width > minWidth)? ((width < maxWidth)? width : maxWidth) : minWidth;
int height = container.height + (mouse.y - lastMouse.y);
container.height = (height > minHeight)? ((height < maxHeight)? height : maxHeight) : minHeight;
}
else
{
// Check if we're resizing
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, resizer)) resizing = true;
}
// Move resizer rectangle properly
resizer.x = container.x + container.width - 17;
resizer.y = container.y + container.height - 17;
lastMouse = mouse; // Update mouse
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangleLinesEx(container, 3, borderColor); // Draw container border
// Draw text in container (add some padding)
DrawTextRec(font, text,
(Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 },
20.0f, 2.0f, wordWrap, GRAY);
DrawRectangleRec(resizer, borderColor); // Draw the resize box
// Draw info
DrawText("Word Wrap: ", 313, screenHeight-115, 20, BLACK);
if (wordWrap) DrawText("ON", 447, screenHeight - 115, 20, RED);
else DrawText("OFF", 447, screenHeight - 115, 20, BLACK);
DrawText("Press [SPACE] to toggle word wrap", 218, screenHeight - 91, 20, GRAY);
DrawRectangle(0, screenHeight - 54, screenWidth, 54, GRAY);
DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, RAYWHITE);
DrawRectangleRec((Rectangle){ 382, screenHeight - 34, 12, 12 }, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

BIN
examples/text/text_draw_inside_rectangle.png View File

Before After
Width: 800  |  Height: 450  |  Size: 17 KiB

+ 2
- 1
src/raylib.h View File

@ -1110,7 +1110,8 @@ RLAPI void UnloadFont(Font font);
// Text drawing functions
RLAPI void DrawFPS(int posX, int posY); // Shows 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 DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
RLAPI void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits
// Text misc. functions
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font

+ 125
- 0
src/text.c View File

@ -779,6 +779,131 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
}
}
// Draw text using font inside rectangle limits
void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
{
int length = strlen(text);
int textOffsetX = 0; // Offset between characters
int textOffsetY = 0; // Required for line break!
float scaleFactor = 0.0f;
unsigned char letter = 0; // Current character
int index = 0; // Index position in sprite font
scaleFactor = fontSize/font.baseSize;
enum { MEASURE_WORD = 0, DRAW_WORD = 1 };
int state = wordWrap ? MEASURE_WORD : DRAW_WORD;
int lastTextOffsetX = 0;
int wordStart = 0;
bool firstWord = true;
for (int i = 0; i < length; i++)
{
int glyphWidth = 0;
letter = (unsigned char)text[i];
if (letter != '\n')
{
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
{
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
letter = (unsigned char)text[i + 1];
index = GetGlyphIndex(font, (int)letter);
i++;
}
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
{
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
letter = (unsigned char)text[i + 1];
index = GetGlyphIndex(font, (int)letter + 64);
i++;
}
else index = GetGlyphIndex(font, (unsigned char)text[i]);
glyphWidth = (font.chars[index].advanceX == 0)?
(int)(font.chars[index].rec.width*scaleFactor + spacing):
(int)(font.chars[index].advanceX*scaleFactor + spacing);
}
// NOTE: When word wrap is active first we measure a `word`(measure until a ' ','\n','\t' is found)
// then set all the variables back to what they were before the measurement, change the state to
// draw that word then change the state again and repeat until the end of the string...when the word
// doesn't fit inside the rect we simple increase `textOffsetY` to draw it on the next line
if (state == MEASURE_WORD)
{
// Measuring state
if ((letter == ' ') || (letter == '\n') || (letter == '\t') || ((i + 1) == length))
{
int t = textOffsetX + glyphWidth;
if (textOffsetX+1>=rec.width)
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
lastTextOffsetX = t - lastTextOffsetX;
textOffsetX = 0;
}
else
{
textOffsetX = lastTextOffsetX;
lastTextOffsetX = t;
}
glyphWidth = 0;
state = !state; // Change state
t = i;
i = firstWord?-1:wordStart;
wordStart = t;
}
}
else
{
// Drawing state
int t = textOffsetX + glyphWidth;
if (letter == '\n')
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
lastTextOffsetX = t - lastTextOffsetX;
if (lastTextOffsetX < 0) lastTextOffsetX = 0;
textOffsetX = 0;
}
else if ((letter != ' ') && (letter != '\t'))
{
if ((t + 1) >= rec.width)
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
textOffsetX = 0;
}
if ((textOffsetY + (int)((font.baseSize + font.baseSize/2)*scaleFactor)) > rec.height) break;
DrawTexturePro(font.texture, font.chars[index].rec,
(Rectangle){ rec.x + textOffsetX + font.chars[index].offsetX*scaleFactor,
rec.y + textOffsetY + font.chars[index].offsetY*scaleFactor,
font.chars[index].rec.width*scaleFactor,
font.chars[index].rec.height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
}
if (wordWrap)
{
if ((letter == ' ') || (letter == '\n') || (letter == '\t'))
{
// After drawing a word change the state
firstWord = false;
i = wordStart;
textOffsetX = lastTextOffsetX;
glyphWidth = 0;
state = !state;
}
}
}
textOffsetX += glyphWidth;
}
}
// Measure string width for default font
int MeasureText(const char *text, int fontSize)
{

Loading…
Cancel
Save