From 306691b02acce8711ad82c8efc736164e1fe7cd2 Mon Sep 17 00:00:00 2001 From: Krow Savcik Date: Tue, 13 Feb 2024 18:31:38 +0200 Subject: feature: simple text rendering ability --- src/cdraw.c | 16 ++++- src/cdraw.h | 1 + src/sbdf.h | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/sbdf.h (limited to 'src') diff --git a/src/cdraw.c b/src/cdraw.c index ecec5de..6088df9 100644 --- a/src/cdraw.c +++ b/src/cdraw.c @@ -1,12 +1,18 @@ #include +#include +#include +#include #include #include +#define SBDF_IMPLEMENTATION +#define SBDF_USESDL +#include "sbdf.h" #include "cdraw.h" #include "types.h" +#include "debug.h" #include "action.h" #include "canvas.h" -#include "debug.h" #include "palette.h" #include "ui.h" @@ -21,6 +27,7 @@ typedef struct { SDL_Window *win; void *ren; +void *font; void *def_palette; struct Canvas* cur_canvas; @@ -50,12 +57,15 @@ main_quit() SDL_DestroyWindow(win); IMG_Quit(); SDL_Quit(); + SBDF_FontDestroy(font); + font = NULL; return 1; } uint main_window_init(const char *s) { + /* TODO: defer*/ int ss; if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL_Init failed: %s\n", SDL_GetError()); @@ -88,6 +98,10 @@ main_window_init(const char *s) if (def_palette == NULL) return 1; + font = SBDF_FontLoad(def_font); + if (font == NULL) + return 1; + ui_create(def_theme_path); if (s == NULL) cur_canvas = canvas_init(64, 64, ren); diff --git a/src/cdraw.h b/src/cdraw.h index 633eea7..e3bc4fd 100644 --- a/src/cdraw.h +++ b/src/cdraw.h @@ -8,6 +8,7 @@ typedef union { extern SDL_Window *win; extern void *ren; +extern void *font; extern void *def_palette; extern const char *def_palette_path; extern const char *cmd_file_picker; diff --git a/src/sbdf.h b/src/sbdf.h new file mode 100644 index 0000000..ba6d413 --- /dev/null +++ b/src/sbdf.h @@ -0,0 +1,214 @@ +/* + BDF simple reader and printer (ASCII Support only) + include stdio.h stddef.h stdlib.h string.h + Should define SBDF_IMPLEMENTATION in only one .c file +*/ + +typedef struct SBDF_Font SBDF_Font; + +SBDF_Font* SBDF_FontLoad(const char *); +void SBDF_FontDestroy(SBDF_Font *); +#ifdef SBDF_USESDL +void SBDF_SDLPrint(const SDL_Renderer *, const SBDF_Font *, const char *, int, int); +#endif + +#ifdef SBDF_IMPLEMENTATION +struct SBDF_Glyph { + int dx, dy; + int bx, by, bw, bh; + size_t s; +}; + +struct SBDF_Font { + struct SBDF_Glyph g[256]; + unsigned char *data; +}; + +struct SBDF_Font* +SBDF_FontInit(size_t sz) { + struct SBDF_Font *res; + int i; + res = malloc(sizeof(*res)); + if (res == NULL) return NULL; + + res->data = malloc(sz); + if (res->data == NULL) { + free(res); + return NULL; + } + for (i = 0; i < 256; i++) + res->g[i].s = -1; + return res; +} + +void +SBDF_FontDestroy(struct SBDF_Font *f) { + if (f == NULL) return; + free(f->data); + free(f); +} + +#define SBDF_NULL 0x00000 +#define SBDF_PROPS 0x00010 +#define SBDF_CHARS 0x00100 +#define SBDF_GLYPH 0x01100 + +struct SBDF_Font* +SBDF_FontLoad(const char *path) { + FILE *f; + int cnt, rd, tp; + struct SBDF_Glyph g; + size_t sz; + char line[2049]; + char word[2049]; + char *v; + unsigned char val; + int state; + struct SBDF_Font *res; + res = NULL; + f = fopen(path, "r"); + if (f == NULL) goto SBDF_FontLoad_defer; + + state = SBDF_NULL; + rd = cnt = sz = 0; + while (fgets(line, 2049, f)) { + if ((state&SBDF_CHARS) == 0) { + sscanf(line, "%s", word); + if (state == SBDF_PROPS) { + if (strcmp(word, "ENDPROPERTIES") == 0) + state = SBDF_NULL; + } else { + if (strcmp(word, "STARTPROPERTIES") == 0) + state = SBDF_PROPS; + else if (strcmp(word, "CHARS") == 0) + state = SBDF_CHARS; + } + continue; + } else { + sscanf(line, "%s", word); + if (cnt) { + --cnt; + continue; + } + if (strcmp(word, "ENCODING") == 0) { + sscanf(line, "%*s %d", &tp); + rd = (tp > -1 && tp < 256); + continue; + } + if (strcmp(word, "DWIDTH") == 0) { + sscanf(line, "%*s %d %d", &g.dx, &g.dy); + continue; + } + if (strcmp(word, "BBX") == 0) { + sscanf(line, "%*s %d %d %d %d", &g.bw, &g.bh, &g.bx, &g.by); + if (rd) { + sz += (g.bw+7) / 8 * g.bh; + } + continue; + } + if (strcmp(word, "BITMAP") == 0) { + cnt = g.bh; + continue; + } + } + } + + fclose(f); + res = SBDF_FontInit(sz); + if (res == NULL) goto SBDF_FontLoad_defer; + f = fopen(path, "r"); + if (f == NULL) goto SBDF_FontLoad_defer; + + state = SBDF_NULL; + rd = cnt = sz = 0; + while (fgets(line, 2049, f)) { + if ((state&SBDF_CHARS) == 0) { + sscanf(line, "%s", word); + if (state == SBDF_PROPS) { + if (strcmp(word, "ENDPROPERTIES") == 0) + state = SBDF_NULL; + } else { + if (strcmp(word, "STARTPROPERTIES") == 0) + state = SBDF_PROPS; + else if (strcmp(word, "CHARS") == 0) + state = SBDF_CHARS; + } + continue; + } else { + sscanf(line, "%s", word); + if (cnt) { + --cnt; + if (rd) { + v = word; + while (v[0] != '\0') { + if (v[0] <= '9') + val = (unsigned char)16*(v[0] - '0'); + else + val = (unsigned char)16*(v[0] - 'A' + 10); + if (v[1] <= '9') + val += (unsigned char)(v[1] - '0'); + else + val += (unsigned char)(v[1] - 'A' + 10); + res->data[sz] = val; + sz++; + v += 2; + } + } + continue; + } + if (strcmp(word, "ENCODING") == 0) { + sscanf(line, "%*s %d", &tp); + rd = (tp > -1 && tp < 256); + continue; + } + if (strcmp(word, "DWIDTH") == 0) { + sscanf(line, "%*s %d %d", &g.dx, &g.dy); + continue; + } + if (strcmp(word, "BBX") == 0) { + sscanf(line, "%*s %d %d %d %d", &g.bw, &g.bh, &g.bx, &g.by); + continue; + } + if (strcmp(word, "BITMAP") == 0) { + cnt = g.bh; + if (rd) { + g.s = sz; + res->g[tp] = g; + } + continue; + } + } + } + return res; +SBDF_FontLoad_defer: + if (f != NULL) + fclose(f); + SBDF_FontDestroy(res); + return NULL; +} + +#ifdef SBDF_USESDL +void +SBDF_SDLPrint(const SDL_Renderer *r, const struct SBDF_Font *f, const char *text, int x, int y) { + char *u; + unsigned char *v; + int i, j; + u = text; + while (*u != '\0') { + v = &f->data[f->g[*u].s]; + x += f->g[*u].bx; + y += f->g[*u].by; + for (i = 0; i < f->g[*u].bh; i++) { + for (j = 0; j < f->g[*u].bw; j++) { + if (v[j/8]>>(7-(j%8))&1) + SDL_RenderDrawPoint(r, x+j, y+i); + } + v += (j + 7) / 8; + } + x += f->g[*u].dx - f->g[*u].bx; + y += f->g[*u].dy - f->g[*u].by; + u++; + } +} +#endif +#endif -- cgit v1.2.3