aboutsummaryrefslogtreecommitdiff
path: root/src/sbdf.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbdf.h')
-rw-r--r--src/sbdf.h214
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