123 lines
3.9 KiB
C
123 lines
3.9 KiB
C
|
#include "textbox.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
|
||
|
|
||
|
TextBox *textBoxNew(const char *text, float x, float y, float textSize,
|
||
|
SDL_Color color, SDL_Texture *background, TTF_Font *font,
|
||
|
const Window *window) {
|
||
|
TextBox *box = malloc(sizeof(TextBox));
|
||
|
if (!box) {
|
||
|
ERROR("error: out of memory\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
box->text = strdup(text);
|
||
|
if (!box->text) {
|
||
|
ERROR("error: out of memory\n");
|
||
|
free(box);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
box->x = x;
|
||
|
box->y = y;
|
||
|
box->textColor = color;
|
||
|
box->background = background;
|
||
|
box->font = font;
|
||
|
box->textSize = textSize;
|
||
|
textBoxUpdate(box, window);
|
||
|
return box;
|
||
|
}
|
||
|
|
||
|
void textBoxDelete(TextBox *textBox) {
|
||
|
free(textBox->text);
|
||
|
size_t i;
|
||
|
for (i = 0; i < textBox->lineCount; ++i) {
|
||
|
SDL_DestroyTexture(textBox->renderedText[i]);
|
||
|
}
|
||
|
free(textBox->renderedText);
|
||
|
free(textBox);
|
||
|
}
|
||
|
|
||
|
static void getLineSizes(TextBox *textBox, int ww, int wh, int *widths,
|
||
|
int *width, int *height) {
|
||
|
int yInc = textBox->textSize * wh;
|
||
|
*width = 0;
|
||
|
size_t i;
|
||
|
for (i = 0; i < textBox->lineCount; ++i) {
|
||
|
int tw, th;
|
||
|
SDL_QueryTexture(textBox->renderedText[i], NULL, NULL, &tw, &th);
|
||
|
int lw = ((float)tw / (float)th) * (float)yInc;
|
||
|
widths[i] = lw;
|
||
|
if (lw > *width) {
|
||
|
*width = lw;
|
||
|
}
|
||
|
}
|
||
|
*width += ww * TEXT_BOX_PADDING;
|
||
|
*height = yInc * textBox->lineCount;
|
||
|
}
|
||
|
|
||
|
void textBoxDraw(TextBox *textBox, const Window *window) {
|
||
|
int ww, wh;
|
||
|
SDL_GetWindowSize(window->obj, &ww, &wh);
|
||
|
int widths[textBox->lineCount];
|
||
|
int bw, bh;
|
||
|
getLineSizes(textBox, ww, wh, widths, &bw, &bh);
|
||
|
SDL_Rect backArea = {textBox->x * ww, textBox->y * wh, bw, bh};
|
||
|
if (textBox->background != NULL) {
|
||
|
SDL_RenderCopy(window->render, textBox->background, NULL, &backArea);
|
||
|
}
|
||
|
int yInc = textBox->textSize * wh;
|
||
|
size_t i;
|
||
|
for (i = 0; i < textBox->lineCount; ++i) {
|
||
|
int th;
|
||
|
SDL_QueryTexture(textBox->renderedText[i], NULL, NULL, NULL, &th);
|
||
|
SDL_Rect area = {backArea.x * (1.0f + TEXT_BOX_PADDING),
|
||
|
(backArea.y * (1.0f + TEXT_BOX_PADDING)) + (yInc * i),
|
||
|
widths[i] * (1.0f - (2 * TEXT_BOX_PADDING)),
|
||
|
yInc * (1.0f - (2 * TEXT_BOX_PADDING))};
|
||
|
SDL_RenderCopy(window->render, textBox->renderedText[i], NULL, &area);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static SDL_Texture *renderLine(const char *text, const TextBox *textBox,
|
||
|
const Window *window) {
|
||
|
SDL_Surface *surface =
|
||
|
TTF_RenderText_Blended(textBox->font, text, textBox->textColor);
|
||
|
if (!surface) {
|
||
|
ERROR("error: sdl2: ttf: %s\n", TTF_GetError());
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
SDL_Texture *texture =
|
||
|
SDL_CreateTextureFromSurface(window->render, surface);
|
||
|
SDL_FreeSurface(surface);
|
||
|
if (!texture) {
|
||
|
ERROR("error: sdl2: %s\n", SDL_GetError());
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
return texture;
|
||
|
}
|
||
|
|
||
|
void textBoxUpdate(TextBox *textBox, const Window *window) {
|
||
|
textBox->renderedText = malloc(1);
|
||
|
if (!textBox->renderedText) {
|
||
|
ERROR("error: out of memory\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
char *savePtr;
|
||
|
char *line = strtok_r(textBox->text, "\n", &savePtr);
|
||
|
for (textBox->lineCount = 0; line != NULL; ++textBox->lineCount) {
|
||
|
textBox->renderedText =
|
||
|
realloc(textBox->renderedText,
|
||
|
sizeof(SDL_Texture *) * (textBox->lineCount + 1));
|
||
|
if (!textBox->renderedText) {
|
||
|
ERROR("error: out of memory\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
textBox->renderedText[textBox->lineCount] =
|
||
|
renderLine(line, textBox, window);
|
||
|
line = strtok_r(NULL, "\n", &savePtr);
|
||
|
}
|
||
|
}
|