/* * NAME * srctohex - convert font from src to hex format * * EXAMPLE USAGE * srctohex -w 12 -h 22 < gallant.src > gallant.hex */ #include #include #include #include #include #include #include #define PixelWidth 12 #define PixelHeight 22 #define PixelSet L'Y' #define PixelClear L' ' #define LINE_MAX_WCHAR 1024 #define FULL_BLOCK 0x2588 #define STARTCHAR 1 #define BITMAP 2 #define ENDCHAR 3 void parse_options(int aArgc, char **aArgv); void usage(int aStatus); void errx(const char *aFormat, ...); int parse_startchar(const wchar_t *aLine); void parse_bitmap(const wchar_t *aLine, int aWidth); void parse_endchar(const wchar_t *aLine); int gWidth = PixelWidth; int gHeight = PixelHeight; int gLineNr = 0; unsigned int gCodepoint = 0; int main(int aArgc, char **aArgv) { if (!setlocale(LC_CTYPE, "")) { fprintf(stderr, "Can't set the locale. Check LANG, LC_CTYPE, LC_ALL.\n"); exit(EXIT_FAILURE); } int expect = STARTCHAR; int bitmaps = 0; int glyphs = 0; int width = 1; parse_options(aArgc, aArgv); printf("# Width: %d\n# Height: %d\n", gWidth, gHeight); wchar_t wbuf[LINE_MAX_WCHAR]; while (fgetws(wbuf, LINE_MAX_WCHAR, stdin)) { ++gLineNr; switch (expect) { case STARTCHAR: width = parse_startchar(wbuf); expect = BITMAP; break; case BITMAP: parse_bitmap(wbuf, width); ++bitmaps; if (bitmaps == gHeight) { putchar('\n'); expect = ENDCHAR; } break; case ENDCHAR: parse_endchar(wbuf); expect = STARTCHAR; bitmaps = 0; ++glyphs; break; default: break; } } if (expect != STARTCHAR) errx("line %d, glyph U+%04x: incomplete glyph due to early end-of-file\n", gLineNr, gCodepoint); fprintf(stderr, "found %d glyphs\n", glyphs); return EXIT_SUCCESS; } // Parse a STARTCHAR directive. // int parse_startchar(const wchar_t *aLine) { if (swscanf(aLine, L"STARTCHAR U+%x", &gCodepoint) == 1) { printf("%04x:", gCodepoint); return wcwidth(gCodepoint); } errx("line %d: expected 'STARTCHAR U+xxxx', got %ls", gLineNr, aLine); return 0; } // Parse a |BITMAP| directive. // void parse_bitmap(const wchar_t *aLine, int aWidth) { const wchar_t *delim1 = wcschr(aLine, L'|'); if (delim1 == NULL) errx("line %d: initial delimiter '|' not found in %ls; not enough pixel lines?\n", gLineNr, aLine); const wchar_t *delim2 = wcschr(delim1 + 1, L'|'); if (delim2 == NULL) errx("line %d: final delimiter '|' not found in %ls", gLineNr, aLine); const int bits = (delim2 - delim1) - 1; if (aWidth == 2) { if (bits != (2 * gWidth)) errx("line %d, glyph U+%04x: expected %d pixels bewteen || delimiters for double width glyph, found %d\n", gLineNr, gCodepoint, 2 * gWidth, bits); } else { if (bits != gWidth) errx("line %d, glyph U+%04x: expected %d pixels bewteen || delimiters for normal width glyph, found %d\n", gLineNr, gCodepoint, gWidth, bits); } int hex = 0; aLine = delim1 + 1; for (int i = 0; i < bits; ++i) { const int rem = i % 4; if (aLine[i] == FULL_BLOCK) hex += (8 >> rem); else { if (aLine[i] != L' ') errx("line %d, glyph U+%04x: pixels must be SPACE or FULL BLOCK U+2588 '%lc', found '%lc'\n", gLineNr, gCodepoint, FULL_BLOCK, aLine[i]); } if (rem == 3) { putchar("0123456789abcdef"[hex]); hex = 0; } } /* Pad to octet with zero bits, if any. */ const int pad = 8 * ((bits + 7) / 8); for (int i = bits; i < pad; ++i) { if (i % 4 == 3) { putchar("0123456789abcdef"[hex]); hex = 0; } } } // Parse an ENDCHAR directive. // void parse_endchar(const wchar_t *aLine) { if (wcscmp(aLine, L"ENDCHAR\n") != 0) errx("line %d, glyph U+%04x: expected 'ENDCHAR', got %ls", gLineNr, gCodepoint, aLine); } // Parse the command line options. // void parse_options(int aArgc, char **aArgv) { int ch; while ((ch = getopt(aArgc, aArgv, "w:h:")) != -1) { switch (ch) { case 'h': if (sscanf(optarg, "%d", &gHeight) != 1) errx("can't convert '%s' to height integer\n", optarg); break; case 'w': if (sscanf(optarg, "%d", &gWidth) != 1) errx("can't convert '%s' to width integer\n", optarg); break; default: usage(EXIT_FAILURE); } } } // Output usage message and exit with status. // void usage(int aStatus) { fprintf(stderr, "usage: srctohex [options]\n"); fprintf(stderr, "Options [default]:\n"); fprintf(stderr, " -h height height in pixels [%d]\n", PixelHeight); fprintf(stderr, " -w width width in pixels [%d]\n", PixelWidth); exit(aStatus); } // Print formatted message on stderr and exit. // void errx(const char *aFormat, ...) { va_list ap; va_start(ap, aFormat); vfprintf(stderr, aFormat, ap); va_end(ap); exit(EXIT_FAILURE); } /* vim: set tabstop=4 shiftwidth=4 expandtab fileformat=unix: */