diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2021-07-03 00:49:03 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2022-03-30 08:20:20 +0200 |
| commit | 6b9f686913efc3725b2690033cd4f398e07076ba (patch) | |
| tree | e9aa91a6b9f617d78123ebe7ad272fc42a60d306 /src/font | |
| parent | c9e6ae44a9aeb89b3f48f3443d6baa80103f7445 (diff) | |
| download | jancity-6b9f686913efc3725b2690033cd4f398e07076ba.tar.gz | |
Add project source code
Diffstat (limited to 'src/font')
| -rw-r--r-- | src/font/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/font/inc/font.h | 22 | ||||
| -rw-r--r-- | src/font/src/font.c | 110 |
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; +} |
