/* See LICENSE file for copyright and license details. */ #include "libparsepsf.h" #include #include #include #include static size_t readfile(int fd, char **datap, size_t *sizep) { size_t len = 0; ssize_t r; for (;;) { if (len == *sizep) { *datap = realloc(*datap, *sizep += 4096); if (!*datap) { perror("realloc"); exit(1); } } r = read(fd, &(*datap)[len], *sizep - len); if (r <= 0) { if (!r) break; perror("read"); exit(1); } len += (size_t)r; } return len; } static uint8_t * genreplacement(const struct libparsepsf_font *font) { size_t glyph, size, i, linesize, xoff, yoff; int invert = 0, round = 0; uint8_t *data, xbit; glyph = libparsepsf_get_glyph(font, "�", NULL, NULL); if (!glyph) { invert = 1; round = 1; glyph = libparsepsf_get_glyph(font, "?", NULL, NULL); if (!glyph) { round = 0; glyph = libparsepsf_get_glyph(font, " ", NULL, NULL); } } glyph -= (glyph ? 1 : 0); linesize = font->width / 8 + (font->width % 8 ? 1 : 0); size = linesize * font->height; data = malloc(size); if (!data) { perror("malloc"); exit(1); } memcpy(data, &font->glyph_data[glyph * size], size); if (invert) for (i = 0; i < size; i++) data[i] ^= 0xFF; if (round) { yoff = (font->height - 1) * linesize; xoff = (font->width - 1) / 8; xbit = 0x80 >> ((font->width - 1) % 8); data[0] ^= 0x80; data[yoff] ^= 0x80; data[xoff] ^= xbit; data[yoff + xoff] ^= xbit; } return data; } static void printglyphrow(const struct libparsepsf_font *font, const uint8_t *gd, const char *bg, const char *fg) { uint8_t bit; size_t x; bit = 0x80; for (x = 0; x < font->width; x++) { printf("%s", (*gd & bit) ? fg : bg); bit >>= 1; if (!bit) { bit = 0x80; gd = &gd[1]; } } } static void printglyph(const struct libparsepsf_font *font, size_t glyph, const char *bg, const char *fg) { const uint8_t *gd; size_t width = font->width / 8 + (font->width % 8 ? 1 : 0); size_t glyphsize = width * font->height; size_t y; if (glyph > font->num_glyphs) { fprintf(stderr, "glyph does not exist!\n"); exit(1); } for (y = 0; y < font->height; y++) { gd = &font->glyph_data[glyph * glyphsize + y * width]; printglyphrow(font, gd, bg, fg); printf("\033[0m\n"); } } static void printline(const struct libparsepsf_font *font, const char *line, size_t linelen) { const char *c, *bg, *fg; const uint8_t *gd; size_t width = font->width / 8 + (font->width % 8 ? 1 : 0); size_t glyphsize = width * font->height; size_t glyph, rem, y; uint8_t *replacement = genreplacement(font); for (y = 0; y < font->height; y++) { rem = linelen; for (c = line; rem;) { glyph = libparsepsf_get_glyph(font, c, &rem, &c); if (!glyph) { do { c = &c[1]; rem -= 1; } while ((*c & 0xC0) == 0x80); bg = "\033[1;30;40m[]"; fg = "\033[1;31;41m[]"; gd = &replacement[y * width]; } else { glyph -= 1; bg = "\033[1;30;40m[]"; fg = "\033[1;37;47m[]"; gd = &font->glyph_data[glyph * glyphsize + y * width]; } printglyphrow(font, gd, bg, fg); } printf("\033[0m\n"); } free(replacement); } int main(int argc, char *argv[]) { unsigned long int glyph; uint32_t uver; char *data = NULL; size_t len, size = 0; struct libparsepsf_font font; if (argc) { argc--; argv++; } len = readfile(STDIN_FILENO, &data, &size); if (libparsepsf_parse_font(data, len, &font, &uver)) { perror("libparsepsf_parse_font"); free(data); exit(1); } free(data); if (uver) { fprintf(stderr, "WARNING: Font format version is not fully supported: " "version 2.%lu\n", (unsigned long int)uver); } printf("#glyphs = %zu\n", font.num_glyphs); printf("width = %zu\n", font.width); printf("height = %zu\n", font.height); if (!argc) { printline(&font, "", 1); } else if (argc == 2 && !strcmp(argv[0], "-g")) { glyph = strtoul(argv[1], NULL, 0); printglyph(&font, (size_t)glyph, "\033[1;30;40m[]", "\033[1;37;47m[]"); } else if (argc == 2 && !strcmp(argv[0], "-x")) { glyph = strtoul(argv[1], NULL, 16); printglyph(&font, (size_t)glyph, "\033[1;30;40m[]", "\033[1;37;47m[]"); } else { for (; argc--; argv++) printline(&font, *argv, strlen(*argv)); } libparsepsf_destroy_font(&font); return 0; }