summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2021-08-05 20:23:50 (EDT)
committer P. J. McDermott <pj@pehjota.net>2021-08-05 23:28:12 (EDT)
commita42ea8a19ab40a02c0c46b2d60ced87c5da1f7eb (patch)
treef43aadd4c8b064b4692a3e412a9ece3f925a41e6
parent9da87b6829205774ab08d46253ae5ca39723ef5e (diff)
downloadmazefight-a42ea8a19ab40a02c0c46b2d60ced87c5da1f7eb.zip
mazefight-a42ea8a19ab40a02c0c46b2d60ced87c5da1f7eb.tar.gz
mazefight-a42ea8a19ab40a02c0c46b2d60ced87c5da1f7eb.tar.bz2
tk: Add text widget (without event handling)
-rw-r--r--configure.ac2
-rw-r--r--src/splash.c42
-rw-r--r--src/tk.h4
-rw-r--r--src/tk/local.mk1
-rw-r--r--src/tk/text.c204
5 files changed, 236 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac
index 5ef2231..02b53ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,7 @@ AC_CHECK_FUNCS(
if ${funcs_missing}; then
AC_MSG_ERROR([required functions are missing])
fi
-for func in round sqrt; do
+for func in ceil log10 round sqrt; do
AC_SEARCH_LIBS([${func}], [m], [], [
AC_MSG_ERROR([required functions are missing])
])
diff --git a/src/splash.c b/src/splash.c
index 07036b8..b36ec33 100644
--- a/src/splash.c
+++ b/src/splash.c
@@ -20,6 +20,7 @@
#include <SDL.h>
#include <SDL_ttf.h>
#include <stdlib.h>
+#include <math.h>
#include <time.h>
#include "defs.h"
#include "dirs.h"
@@ -83,23 +84,15 @@ _mf_splash_play(void *user_data)
}
static struct mftk_widget *
-_mf_splash_form(SDL_Renderer *renderer, const char *font_path,
+_mf_splash_form(SDL_Renderer *renderer, TTF_Font *text_font,
SDL_Color *text_color)
{
- TTF_Font *text_font = NULL;
SDL_Color butn_color;
SDL_Color chkb_color;
SDL_Color chkm_color;
+ double rand_max_len;
struct mftk_widget *grid;
- text_font = TTF_OpenFont(font_path, MF_SPLASH_TEXT_FONT_S);
- if (text_font == NULL) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
- "Couldn't open font: %s",
- TTF_GetError());
- return NULL;
- }
-
butn_color.r = MF_COLOR_BUTN_R, butn_color.g = MF_COLOR_BUTN_G;
butn_color.b = MF_COLOR_BUTN_B, butn_color.a = MF_COLOR_BUTN_A;
chkb_color.r = MF_COLOR_CHKB_R, chkb_color.g = MF_COLOR_CHKB_G;
@@ -107,7 +100,15 @@ _mf_splash_form(SDL_Renderer *renderer, const char *font_path,
chkm_color.r = MF_COLOR_CHKM_R, chkm_color.g = MF_COLOR_CHKM_G;
chkm_color.b = MF_COLOR_CHKM_B, chkm_color.a = MF_COLOR_CHKM_A;
- grid = mftk_grid_new(4, 2, MF_SPLASH_ROW_M, MF_SPLASH_COL_M,
+ /* Assigned to a variable to satisfy -Wbad-function-cast */
+ rand_max_len = ceil(log10(RAND_MAX));
+
+ grid = mftk_grid_new(5, 2, MF_SPLASH_ROW_M, MF_SPLASH_COL_M,
+ mftk_label_new(text_font, "Seed", text_color, renderer),
+ MFTK_GRID_HALIGN_R|MFTK_GRID_VALIGN_T,
+ mftk_text_new('0', '9', rand_max_len, "0", text_font,
+ text_color),
+ MFTK_GRID_HALIGN_L|MFTK_GRID_VALIGN_T,
mftk_label_new(text_font, "Size", text_color, renderer),
MFTK_GRID_HALIGN_R|MFTK_GRID_VALIGN_T,
mftk_radio_new(MF_SPLASH_CHK_BTN_W, MF_SPLASH_CHK_BTN_P,
@@ -145,9 +146,6 @@ _mf_splash_form(SDL_Renderer *renderer, const char *font_path,
MFTK_GRID_HALIGN_L|MFTK_GRID_VALIGN_T
);
- TTF_CloseFont(text_font);
- text_font = NULL;
-
return grid;
}
@@ -156,6 +154,7 @@ mf_splash(SDL_Renderer *renderer)
{
char *font_path = NULL;
TTF_Font *title_font = NULL;
+ TTF_Font *text_font = NULL;
SDL_Color form_color;
SDL_Color text_color;
struct mftk_widget *box;
@@ -171,6 +170,13 @@ mf_splash(SDL_Renderer *renderer)
TTF_GetError());
goto err;
}
+ text_font = TTF_OpenFont(font_path, MF_SPLASH_TEXT_FONT_S);
+ if (text_font == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't open font: %s",
+ TTF_GetError());
+ goto err;
+ }
form_color.r = MF_COLOR_FORM_R, form_color.g = MF_COLOR_FORM_G;
form_color.b = MF_COLOR_FORM_B, form_color.a = MF_COLOR_FORM_A;
@@ -182,12 +188,11 @@ mf_splash(SDL_Renderer *renderer)
mftk_label_new(title_font, "Maze Fight",
&text_color, renderer),
MFTK_GRID_HALIGN_C|MFTK_GRID_VALIGN_T,
- _mf_splash_form(renderer, font_path,
+ _mf_splash_form(renderer, text_font,
&text_color),
MFTK_GRID_HALIGN_C|MFTK_GRID_VALIGN_T
)
);
- /* TODO: Widgets */
mftk_widget_layout(box);
TTF_CloseFont(title_font);
@@ -229,6 +234,8 @@ mf_splash(SDL_Renderer *renderer)
quit:
mftk_widget_destroy(&box);
+ TTF_CloseFont(text_font);
+ text_font = NULL;
mf_maze_destroy(&maze);
return 0;
@@ -240,6 +247,9 @@ mf_splash(SDL_Renderer *renderer)
if (title_font != NULL) {
TTF_CloseFont(title_font);
}
+ if (text_font != NULL) {
+ TTF_CloseFont(text_font);
+ }
mftk_widget_destroy(&box);
mf_maze_destroy(&maze);
return -1;
diff --git a/src/tk.h b/src/tk.h
index 3e22de0..5346d87 100644
--- a/src/tk.h
+++ b/src/tk.h
@@ -81,6 +81,10 @@ mftk_radio_new(int butn_width, int butn_padding, SDL_Color *butn_color,
SDL_Renderer *renderer, int state, int options, ...);
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 *
mftk_blank_new(void);
#endif /* MFTK_H_ */
diff --git a/src/tk/local.mk b/src/tk/local.mk
index d1d4efe..7522cc6 100644
--- a/src/tk/local.mk
+++ b/src/tk/local.mk
@@ -6,5 +6,6 @@ mazefight_SOURCES += \
%reldir%/grid.c \
%reldir%/label.c \
%reldir%/radio.c \
+ %reldir%/text.c \
%reldir%/widget.c \
%reldir%/widget.h
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;
+}