aboutsummaryrefslogtreecommitdiff
path: root/src/font
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2021-07-03 00:49:03 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-03-30 08:20:20 +0200
commit6b9f686913efc3725b2690033cd4f398e07076ba (patch)
treee9aa91a6b9f617d78123ebe7ad272fc42a60d306 /src/font
parentc9e6ae44a9aeb89b3f48f3443d6baa80103f7445 (diff)
downloadjancity-6b9f686913efc3725b2690033cd4f398e07076ba.tar.gz
Add project source code
Diffstat (limited to 'src/font')
-rw-r--r--src/font/CMakeLists.txt3
-rw-r--r--src/font/inc/font.h22
-rw-r--r--src/font/src/font.c110
3 files changed, 135 insertions, 0 deletions
diff --git a/src/font/CMakeLists.txt b/src/font/CMakeLists.txt
new file mode 100644
index 0000000..46336ef
--- /dev/null
+++ b/src/font/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(font "src/font.c")
+target_include_directories(font PUBLIC "inc")
+target_link_libraries(font PUBLIC container PRIVATE gfx)
diff --git a/src/font/inc/font.h b/src/font/inc/font.h
new file mode 100644
index 0000000..2d8bd2f
--- /dev/null
+++ b/src/font/inc/font.h
@@ -0,0 +1,22 @@
+#ifndef FONT_H
+#define FONT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum font
+{
+ FONT
+};
+
+int font_printf(enum font f, short x, short y, const char *fmt, ...);
+
+extern struct sprite font_sprite;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FONT_H */
diff --git a/src/font/src/font.c b/src/font/src/font.c
new file mode 100644
index 0000000..a6a28d3
--- /dev/null
+++ b/src/font/src/font.c
@@ -0,0 +1,110 @@
+#include <font.h>
+#include <gfx.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+struct sprite font_sprite;
+
+static int renderstr(const enum font f, const short x, short y, const char *str)
+{
+ static const struct cfg
+ {
+ const struct sprite *s;
+ short fw, fh, fs;
+ } cfgs[] =
+ {
+ [FONT] =
+ {
+ .s = &font_sprite,
+ .fw = 12,
+ .fh = 14,
+ .fs = 8
+ }
+ };
+
+ const struct cfg *const cfg = &cfgs[f];
+ char c;
+ short rx = x;
+
+ while ((c = *str++))
+ {
+ if (c == ' ')
+ {
+ rx += cfg->fs;
+ continue;
+ }
+ else if (c == '\n' || c == '\r')
+ {
+ rx = x;
+ y += cfg->fh;
+ continue;
+ }
+
+ struct sprite *const s = sprite_get();
+
+ if (!s || sprite_clone(cfg->s, s))
+ return -1;
+
+ s->w = cfg->fw;
+ s->h = cfg->fh;
+
+ /* Substract non-printable characters (NUL to SP). */
+ const char ch = c - '!';
+ const short u = (cfg->fw * ch) % cfg->s->w;
+ const short v = cfg->fh * ((cfg->fw * ch) / cfg->s->w);
+
+ s->u += u;
+ s->v += v;
+ s->x = rx;
+ s->y = y;
+ sprite_sort(s);
+ rx += cfg->fs;
+ }
+
+ return 0;
+}
+
+int font_printf(const enum font f, const short x, const short y,
+ const char *const fmt, ...)
+{
+ va_list ap, aq, at;
+
+ va_start(ap, fmt);
+ va_copy(aq, ap);
+ va_copy(at, ap);
+
+ /* Short string optimization. */
+ char defstr[64];
+ int sz = vsnprintf(defstr, sizeof defstr, fmt, ap);
+
+ if (sz < 0)
+ goto end;
+ else if (sz >= sizeof defstr)
+ {
+ va_list at;
+
+ sz = vsnprintf(NULL, 0, fmt, ap);
+
+ if (sz < 0)
+ goto end;
+
+ /* VLAs are generally frowned upon, but using the heap
+ * might not be a good idea for a video game like this. */
+ char str[sz + 1];
+
+ sz = vsnprintf(str, sizeof str, fmt, ap);
+ va_end(at);
+
+ if (sz < 0)
+ goto end;
+ }
+
+ if (renderstr(f, x, y, defstr))
+ return -1;
+
+end:
+ va_end(at);
+ va_end(aq);
+ va_end(ap);
+ return sz;
+}