Commit cba8f74bc5ce7dd3c01e6514483b7e4bf361f490 Parent: c9e2c2531efcdec67afd56d9353375f8c0e0f6a5 Author: mcol <mcol@posteo.net> Date: 2020-10-27 13:20:24 +0000 Committer: mcol <mcol@posteo.net> Committed: 2020-10-27 13:20:24 +0000 Add main chunk of code This is now a semi-complete functional version of the program, but with some limitations. It seems that some BDF fonts do not work, possibly due to size.
bdf2flf.c Modified
@@ -2,29 +2,99 @@ #include <stdlib.h> #include <string.h> +#define PROGNAME "bdf2flf" -#include <unistd.h> // ? -#include <limits.h> // ? -#include <errno.h> // ? -#define PROGNAME "bdf2flf" +// These are the characters required at the start of FIGfonts. +const unsigned int REQUIRED[] = { + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 196, 214, 220, 228, 246, 252, 223 +}; + + +struct character { + unsigned int width; + unsigned int encoding; + char *bitmap; + _Bool printed; +}; + + +void die(char *msg) +{ + fprintf(stderr, msg); + exit(EXIT_FAILURE); +} + + +void put_pixel(unsigned int c, unsigned int bit, FILE *out) +{ + + if (c & bit) { + fputc('#', out); + } else { + fputc(' ', out); + } +} + + +void print_character(FILE *out, char *bitmap, unsigned int width, unsigned int height) +{ + unsigned int y; + unsigned int x; + int c; + unsigned int bit; + size_t hex_chars = (width + 7) / 8 * 2; + char *s; + s = malloc(hex_chars); + + for (y = 0; y < height; y++) { + memset(s, 0, strlen(s)); + if (y) + fprintf(out, "\n"); + for (x = 0; x < hex_chars; x++) { + strncat(s, bitmap, 1); + bitmap++; + } + + c = (int)strtol(s, NULL, 16); + bit = 0x80 * hex_chars / 2; + for (x = 0; x < width; x++) { + put_pixel(c, bit, out); + if (bit == 1) + break; + bit = bit / 2; + } + fprintf(out, "$@"); + } + + fprintf(out, "@\n"); + free(s); +} void bdf2flf(FILE * in, FILE * out) { - char linebuf[1024]; char *s; - int widest = 0; - int comments = 2; - int baseline, old_layout, direction, full_layout, codetags; + char linebuf[1024]; char font[1024]; char copyright[1024]; - int chars = 0; + int baseline, codetags, i; + int comments = 3; + int num_chars = 0; + int width = 0; int height = 0; - int fbb_width = 0; - int fbb_height = 0; - int fbb_yoffset = 0; + char bitmap[4 * 32]; + int n = 0; + struct character *chars; + const unsigned int *j; + // Some of the bdf-reading logic is derived from bdf2c (c) Lutz Sammer. + // extract bdf headers for (;;) { if (!fgets(linebuf, sizeof(linebuf), in)) { // EOF break; @@ -33,46 +103,105 @@ break; } if (!strcasecmp(s, "FONTBOUNDINGBOX")) { - fbb_width = atoi(strtok(NULL, " \t\n\r")); - fbb_height = atoi(strtok(NULL, " \t\n\r")); + width = atoi(strtok(NULL, " \t\n\r")); + height = atoi(strtok(NULL, " \t\n\r")); strtok(NULL, " \t\n\r"); - fbb_yoffset = atoi(strtok(NULL, " \t\n\r")); + baseline = height + atoi(strtok(NULL, " \t\n\r")); } else if (!strcasecmp(s, "FONT")) { strcpy(font, strtok(NULL, "\n")); } else if (!strcasecmp(s, "COPYRIGHT")) { strcpy(copyright, strtok(NULL, "\n")); - comments = 3; + comments = 4; } else if (!strcasecmp(s, "CHARS")) { - chars = atoi(strtok(NULL, " \t\n\r")); + num_chars = atoi(strtok(NULL, " \t\n\r")); break; } } - // exit if data could not be read completely - if (chars <= 0 || fbb_width <= 0 || fbb_height <= 0 || height <= 0) { - fprintf(stderr, "Could not extract BDF data. Is the input a BDF file?\n"); - exit(EXIT_FAILURE); + if (num_chars <= 0 || width <= 0 || height <= 0) + die("Could not extract BDF data. Is the input a BDF file?\n"); + + if (width > 32 || height > 32) + die("bdf fonts this large are not supported, sorry.\n"); + + chars = malloc(num_chars * sizeof(struct character)); + if (!chars) + die("Could not allocate memory.\n"); + + // extract individual char data + for (;;) { if (!fgets(linebuf, sizeof(linebuf), in)) + break; + if (!(s = strtok(linebuf, " \t\n\r"))) + continue; + if (!strcasecmp(s, "ENCODING")) { + chars[n].encoding = atoi(strtok(NULL, " \t\n\r")); + } else if (!strcasecmp(s, "BBX")) { + chars[n].width = atoi(strtok(NULL, " \t\n\r")); + } else if (!strcasecmp(s, "BITMAP")) { + if (n == num_chars) + die("bdf font has incorrect CHARS value.\n"); + i = 0; + chars[n].printed = 0; + chars[n].bitmap = malloc(1); + chars[n].bitmap[0] = '\0'; + for (;;) { + fgets(linebuf, sizeof(linebuf), in); + s = strtok(linebuf, "\n\r"); + if (!strcasecmp(s, "ENDCHAR")) { + break; + } + strncat(chars[n].bitmap, s, 4); + i++; + } + n++; + } } - // output header - fprintf(out, "flf2a$ %i %i %i %i %i %i %i %i\n", height, baseline, widest+2, - old_layout, comments, direction, full_layout, codetags); + // output flf header + codetags = 0; + fprintf(out, "flf2a$ %i %i %i -1 %i 0 16384 %i\n", height, baseline, width+2, + comments, codetags); fprintf(out, "FIGlet font derived from %s\n", font); - if (comments > 2) + if (comments > 3) fprintf(out, "which has copyright: %s\n", copyright); - fprintf(out, "Converted to flf with bdf2flf (c) Matt Colligan.\n"); + fprintf(out, "Converted to flf with bdf2flf (c) 2020 Matt Colligan.\n\n"); + // print required characters first + n = 0; + j = &REQUIRED[0]; + for (;;) { + if (chars[n].encoding == *j) { + strncpy(bitmap, chars[n].bitmap, ((width + 7) / 8) * height * 2); + print_character(out, bitmap, chars[n].width, height); + chars[n].printed = 1; + if (*j == 223) + break; + j++; + } + n++; + if (n == num_chars) + n = 0; + } + + // print additional characters second + for (n = 0; n < num_chars; n++) { + if (!chars[n].printed) { + strncpy(bitmap, chars[n].bitmap, ((width + 7) / 8) * height * 2); + print_character(out, bitmap, chars[n].width, height); + } + free(chars[n].bitmap); + } } int main(int argc, char *argv[]) { if (argc > 1) { - printf(PROGNAME "< input.bdf > output.flf\nbdf data is read from stdin" - "and figlet font data is output to stdout.\n"); + printf(PROGNAME " < input.bdf > output.flf\nbdf data is read from stdin" + " and figlet font data is output to stdout.\n"); exit(EXIT_SUCCESS); }