#include "textbox.h" #include #include #include #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); } }