diff options
Diffstat (limited to 'src/sbdf.h')
-rw-r--r-- | src/sbdf.h | 214 |
1 files changed, 214 insertions, 0 deletions
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 |