From f0c9cf4a0534c029bb94d7307aebffae42799b82 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 5 Jun 2014 18:38:27 +0000 Subject: [PATCH] Support "GNU Unifont" format font data The GNU Unifont .hex format is a text file. Each line represents one glyph and consists of a four-digit hex code point, a colon, and pairs of hex digits representing the bitmap. By default an 8x16 font is assumed, with 16x16 double-width glyphs, resulting in either 32 or 64 hex digits for the bitmap. Our version of the file format supports comments at the top of the file to set the height and width: # Height: # Width: Each row of bitmap data is rounded up to byte width - for example, a 10-pixel wide font uses 4 characters per row. See http://czyborra.com/unifont/ for more background on the original format. Sponsored by: The FreeBSD Foundation --- tools/tools/vt/fontcvt/fontcvt.c | 116 ++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/tools/tools/vt/fontcvt/fontcvt.c b/tools/tools/vt/fontcvt/fontcvt.c index 4e019cdc1926..f4f5499bbd64 100644 --- a/tools/tools/vt/fontcvt/fontcvt.c +++ b/tools/tools/vt/fontcvt/fontcvt.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 The FreeBSD Foundation + * Copyright (c) 2009, 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by Ed Schouten under sponsorship from the @@ -178,6 +178,30 @@ add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) return (gl); } +static int +add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) +{ + struct glyph *gl; + + /* Prevent adding two glyphs for 0xFFFD */ + if (curchar == 0xFFFD) { + if (map_idx < VFNT_MAP_BOLD) + gl = add_glyph(bytes, 0, 1); + } else if (curchar >= 0x20) { + gl = add_glyph(bytes, map_idx, 0); + if (add_mapping(gl, curchar, map_idx) != 0) + return (1); + if (bytes_r != NULL) { + gl = add_glyph(bytes_r, map_idx + 1, 0); + if (add_mapping(gl, curchar, + map_idx + 1) != 0) + return (1); + } + } + return (0); +} + + static int parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, unsigned int dwidth) @@ -218,20 +242,12 @@ parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, } static int -parse_bdf(const char *filename, unsigned int map_idx) +parse_bdf(FILE *fp, unsigned int map_idx) { - FILE *fp; char *ln; size_t length; uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; unsigned int curchar = 0, dwidth = 0, i, line; - struct glyph *gl; - - fp = fopen(filename, "r"); - if (fp == NULL) { - perror(filename); - return (1); - } while ((ln = fgetln(fp, &length)) != NULL) { ln[length - 1] = '\0'; @@ -257,27 +273,73 @@ parse_bdf(const char *filename, unsigned int map_idx) return (1); } - /* Prevent adding two glyphs for 0xFFFD */ - if (curchar == 0xFFFD) { - if (map_idx < VFNT_MAP_BOLD) - gl = add_glyph(bytes, 0, 1); - } else if (curchar >= 0x20) { - gl = add_glyph(bytes, map_idx, 0); - if (add_mapping(gl, curchar, map_idx) != 0) - return (1); - if (dwidth == width * 2) { - gl = add_glyph(bytes_r, map_idx + 1, 0); - if (add_mapping(gl, curchar, - map_idx + 1) != 0) - return (1); - } - } + if (add_char(curchar, map_idx, bytes, + dwidth == width * 2 ? bytes_r : NULL) != 0) + return (1); } } return (0); } +static int +parse_hex(FILE *fp, unsigned int map_idx) +{ + char *ln, *p; + char fmt_str[8]; + size_t length; + uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; + unsigned curchar = 0, i, line, chars_per_row, dwidth; + + while ((ln = fgetln(fp, &length)) != NULL) { + ln[length - 1] = '\0'; + + if (strncmp(ln, "# Height: ", 10) == 0) { + height = atoi(ln + 10); + } else if (strncmp(ln, "# Width: ", 9) == 0) { + width = atoi(ln + 9); + } else if (sscanf(ln, "%4x:", &curchar)) { + p = ln + 5; + chars_per_row = strlen(p) / height; + dwidth = width; + if (chars_per_row / 2 > width / 8) + dwidth *= 2; /* Double-width character. */ + snprintf(fmt_str, sizeof(fmt_str), "%%%ux", + chars_per_row); + + for (i = 0; i < height; i++) { + sscanf(p, fmt_str, &line); + p += chars_per_row; + if (parse_bitmap_line(bytes + i * wbytes, + bytes_r + i * wbytes, line, dwidth) != 0) + return (1); + } + + if (add_char(curchar, map_idx, bytes, + dwidth == width * 2 ? bytes_r : NULL) != 0) + return (1); + } + } + return (0); +} + +static int +parse_file(const char *filename, unsigned int map_idx) +{ + FILE *fp; + size_t len; + + fp = fopen(filename, "r"); + if (fp == NULL) { + perror(filename); + return (1); + } + len = strlen(filename); + if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0) + return parse_hex(fp, map_idx); + return parse_bdf(fp, map_idx); +} + static void number_glyphs(void) { @@ -416,12 +478,12 @@ main(int argc, char *argv[]) wbytes = howmany(width, 8); - if (parse_bdf(argv[0], VFNT_MAP_NORMAL) != 0) + if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) return (1); argc--; argv++; if (argc == 2) { - if (parse_bdf(argv[0], VFNT_MAP_BOLD) != 0) + if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) return (1); argc--; argv++;