summaryrefslogtreecommitdiffstats
path: root/src/tk/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tk/text.c')
-rw-r--r--src/tk/text.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/tk/text.c b/src/tk/text.c
new file mode 100644
index 0000000..205c8e3
--- /dev/null
+++ b/src/tk/text.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2021 P. J. McDermott
+ *
+ * This file is part of Maze Fight
+ *
+ * Maze Fight is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Maze Fight is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Maze Fight. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+#include <errno.h>
+#include <string.h>
+#include "../tk.h"
+#include "../util.h"
+#include "widget.h"
+
+struct mftk_text {
+ struct mftk_widget parent;
+ char min_char;
+ char max_char;
+ size_t len;
+ size_t cur;
+ int y;
+ int w;
+ int h;
+ char *val;
+ TTF_Font *font;
+ int line_skip;
+ int ascent;
+ SDL_Color *color;
+ SDL_Texture *texture;
+};
+
+static void
+_mftk_text_layout(struct mftk_widget *w __attribute__((__unused__)))
+{
+ /* Size set in constructor */
+}
+
+static int
+_mftk_text_event(struct mftk_widget *w, SDL_Event *e,
+ int x __attribute__((__unused__)),
+ int y __attribute__((__unused__)))
+{
+ struct mftk_text *t = (struct mftk_text *) w;
+
+ /* TODO */
+ t->texture = NULL;
+ return 0;
+}
+
+static int
+_mftk_text_render_val(struct mftk_text *t, SDL_Renderer *renderer)
+{
+ SDL_Surface *surface;
+ int max_y;
+ const char *c;
+ int glyph_max_y;
+
+ surface = TTF_RenderUTF8_Blended(t->font, t->val, *t->color);
+ if (surface == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't create surface: %s",
+ TTF_GetError());
+ return -1;
+ }
+
+ t->texture = SDL_CreateTextureFromSurface(renderer, surface);
+ if (t->texture == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't create texture: %s",
+ SDL_GetError());
+ SDL_FreeSurface(surface);
+ return -1;
+ }
+
+ max_y = 0;
+ for (c = t->val; *c != '\0'; ++c) {
+ if (TTF_GlyphMetrics(t->font, *c, NULL, NULL, NULL,
+ &glyph_max_y, NULL) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't get glyph metrics: %s",
+ TTF_GetError());
+ continue;
+ }
+ if (glyph_max_y > max_y) {
+ max_y = glyph_max_y;
+ }
+ }
+ t->y = (t->line_skip - t->ascent) / 2 + (t->ascent - max_y);
+ t->w = surface->w;
+ t->h = surface->h;
+
+ SDL_FreeSurface(surface);
+
+ return 0;
+}
+
+static int
+_mftk_text_render(struct mftk_widget *w, SDL_Renderer *renderer, int x, int y)
+{
+ struct mftk_text *t = (struct mftk_text *) w;
+ SDL_Rect rect;
+ char *val;
+ int cur_x;
+
+ if (t->texture == NULL && _mftk_text_render_val(t, renderer) < 0) {
+ return -1;
+ }
+
+ rect.x = x;
+ rect.y = t->y + y;
+ rect.w = t->w;
+ rect.h = t->h;
+
+ val = mf_strdup(t->val);
+ if (val == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't render widget: %s",
+ strerror(errno));
+ return -1;
+ }
+ val[t->cur] = '\0';
+ TTF_SizeUTF8(t->font, val, &cur_x, NULL);
+
+ if (SDL_RenderCopy(renderer, t->texture, NULL, &rect) < 0 ||
+ SDL_SetRenderDrawColor(renderer,
+ t->color->r, t->color->g,
+ t->color->b, t->color->a) < 0 ||
+ SDL_RenderDrawLine(renderer,
+ x + cur_x, y + t->y, x + cur_x, y + t->h) < 0 ||
+ SDL_RenderDrawLine(renderer,
+ x, y + w->h, x + w->w, y + w->h) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't render widget: %s",
+ SDL_GetError());
+ free(val);
+ return -1;
+ }
+
+ free(val);
+ return 0;
+}
+
+static void
+_mftk_text_destroy(struct mftk_widget *w)
+{
+ struct mftk_text *t = (struct mftk_text *) w;
+
+ free(t->val);
+ SDL_DestroyTexture(t->texture);
+}
+
+struct mftk_widget *
+mftk_text_new(char min_char, char max_char, size_t len, const char *val,
+ TTF_Font *font, SDL_Color *color)
+{
+ struct mftk_widget *w;
+ struct mftk_text *t;
+ int advance;
+ char ch;
+
+ mftk_widget_init(w, t, text);
+
+ t->min_char = min_char;
+ t->max_char = max_char;
+ t->len = len;
+ t->cur = strlen(val);
+ t->val = mf_strdup(val);
+ t->font = font;
+ t->line_skip = TTF_FontLineSkip(font);
+ t->ascent = TTF_FontAscent (font);
+ t->color = color;
+ t->texture = NULL;
+
+ w->w = 0;
+ for (ch = min_char; ch <= max_char; ++ch) {
+ if (TTF_GlyphMetrics(font, ch, NULL, NULL, NULL, NULL, &advance)
+ < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't get glyph metrics: %s",
+ TTF_GetError());
+ continue;
+ }
+ advance *= len;
+ if (advance > w->w) {
+ w->w = advance;
+ }
+ }
+ w->h = t->line_skip + 1;
+
+ return w;
+}