FreeBSD Bugzilla – Attachment 194668 Details for
Bug 205707
Improve parsing of BDFs by vtfontcvt
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
More complex patch
patch-vtfontcvt.c (text/plain), 16.98 KB, created by
Dmitry Wagin
on 2018-06-27 09:02:16 UTC
(
hide
)
Description:
More complex patch
Filename:
MIME Type:
Creator:
Dmitry Wagin
Created:
2018-06-27 09:02:16 UTC
Size:
16.98 KB
patch
obsolete
>--- src/usr.bin/vtfontcvt.c.orig >+++ src/usr.bin/vtfontcvt.c >@@ -44,11 +44,13 @@ __FBSDID("$FreeBSD: head/usr.bin/vtfontcvt/vtfontcvt.c 331935 2018-04-03 18:43:0 > #include <string.h> > #include <unistd.h> > >-#define VFNT_MAPS 4 >-#define VFNT_MAP_NORMAL 0 >-#define VFNT_MAP_NORMAL_RH 1 >-#define VFNT_MAP_BOLD 2 >-#define VFNT_MAP_BOLD_RH 3 >+#define VFNT_MAPS 4 >+#define VFNT_MAP_NORMAL 0 >+#define VFNT_MAP_NORMAL_RIGHT 1 >+#define VFNT_MAP_BOLD 2 >+#define VFNT_MAP_BOLD_RIGHT 3 >+#define VFNT_MAXGLYPHS 131072 >+#define VFNT_MAXDIMENSION 128 > > static unsigned int width = 8, wbytes, height = 16; > >@@ -63,10 +65,10 @@ struct glyph { > TAILQ_HEAD(glyph_list, glyph); > static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; > static struct glyph_list glyphs[VFNT_MAPS] = { >- TAILQ_HEAD_INITIALIZER(glyphs[0]), >- TAILQ_HEAD_INITIALIZER(glyphs[1]), >- TAILQ_HEAD_INITIALIZER(glyphs[2]), >- TAILQ_HEAD_INITIALIZER(glyphs[3]), >+ TAILQ_HEAD_INITIALIZER(glyphs[0]), >+ TAILQ_HEAD_INITIALIZER(glyphs[1]), >+ TAILQ_HEAD_INITIALIZER(glyphs[2]), >+ TAILQ_HEAD_INITIALIZER(glyphs[3]), > }; > static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; > >@@ -79,13 +81,13 @@ struct mapping { > > TAILQ_HEAD(mapping_list, mapping); > static struct mapping_list maps[VFNT_MAPS] = { >- TAILQ_HEAD_INITIALIZER(maps[0]), >- TAILQ_HEAD_INITIALIZER(maps[1]), >- TAILQ_HEAD_INITIALIZER(maps[2]), >- TAILQ_HEAD_INITIALIZER(maps[3]), >+ TAILQ_HEAD_INITIALIZER(maps[0]), >+ TAILQ_HEAD_INITIALIZER(maps[1]), >+ TAILQ_HEAD_INITIALIZER(maps[2]), >+ TAILQ_HEAD_INITIALIZER(maps[3]), > }; > static unsigned int mapping_total, map_count[4], map_folded_count[4], >- mapping_unique, mapping_dupe; >+ mapping_unique, mapping_dupe; > > static void > usage(void) >@@ -103,13 +105,15 @@ xmalloc(size_t size) > > if ((m = malloc(size)) == NULL) > errx(1, "memory allocation failure"); >+ memset(m, 0, size); >+ > return (m); > } > > static int > add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) > { >- struct mapping *mp; >+ struct mapping *mp, *mp_temp = NULL; > struct mapping_list *ml; > > mapping_total++; >@@ -120,10 +124,14 @@ add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) > mp->m_length = 0; > > ml = &maps[map_idx]; >- if (TAILQ_LAST(ml, mapping_list) != NULL && >- TAILQ_LAST(ml, mapping_list)->m_char >= c) >- errx(1, "Bad ordering at character %u", c); >- TAILQ_INSERT_TAIL(ml, mp, m_list); >+ TAILQ_FOREACH(mp_temp, ml, m_list) { >+ if (mp_temp->m_char >= c) >+ break; >+ } >+ if (mp_temp == NULL) >+ TAILQ_INSERT_TAIL(ml, mp, m_list); >+ else >+ TAILQ_INSERT_BEFORE(mp_temp, mp, m_list); > > map_count[map_idx]++; > mapping_unique++; >@@ -137,7 +145,7 @@ dedup_mapping(unsigned int map_idx) > struct mapping *mp_bold, *mp_normal, *mp_temp; > unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; > >- assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RH); >+ assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RIGHT); > mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); > TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { > while (mp_normal->m_char < mp_bold->m_char) >@@ -153,6 +161,7 @@ dedup_mapping(unsigned int map_idx) > free(mp_bold); > mapping_dupe++; > } >+ > return (0); > } > >@@ -183,6 +192,10 @@ add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) > SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); > > glyph_unique++; >+ >+ if (glyph_unique > VFNT_MAXGLYPHS) >+ errx(1, "Too large number of glyphs %u!", glyph_unique); >+ > return (gl); > } > >@@ -201,120 +214,244 @@ add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) > return (1); > if (bytes_r != NULL) { > gl = add_glyph(bytes_r, map_idx + 1, 0); >- if (add_mapping(gl, curchar, >- 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) >+rshift_bitmap_line(uint8_t *line, size_t size, size_t len, size_t shift) > { >- uint8_t *p; >- unsigned int i, subline; >+ size_t d, s, i; >+ uint16_t t; > >- if (dwidth != width && dwidth != width * 2) >- errx(1, "Bitmap with unsupported width %u!", dwidth); >+ assert(size > 0 && len > 0); >+ assert(size * 8 >= len); > >- /* Move pixel data right to simplify splitting double characters. */ >- line >>= (howmany(dwidth, 8) * 8) - dwidth; >+ if (shift == 0) >+ return (0); > >- for (i = dwidth / width; i > 0; i--) { >- p = (i == 2) ? right : left; >+ d = shift / 8; >+ s = 8 - shift % 8; >+ i = howmany(len, 8); > >- subline = line & ((1 << width) - 1); >- subline <<= (howmany(width, 8) * 8) - width; >+ while (i > 0) { >+ i--; > >- if (wbytes == 1) { >- *p = subline; >- } else if (wbytes == 2) { >- *p++ = subline >> 8; >- *p = subline; >- } else { >- errx(1, "Unsupported wbytes %u!", wbytes); >- } >+ t = *(line + i); >+ *(line + i) = 0; >+ >+ t <<= s; >+ >+ if (i + d + 1 < size) >+ *(line + i + d + 1) |= (uint8_t) t; >+ if (i + d < size) >+ *(line + i + d) = t >> 8; >+ } >+ >+ return (0); >+} >+ >+static int >+split_bitmap_line(uint8_t *left, uint8_t *right, uint8_t *line, size_t w) >+{ >+ size_t s, i; >+ >+ s = 8 - width % 8; >+ >+ memcpy(left, line, wbytes); >+ *(left + wbytes - 1) &= 0xFF << s; > >- line >>= width; >+ if (w > width) { /* Double-width character. */ >+ uint8_t t; >+ >+ for (i = 0; i < wbytes; i++) { >+ t = *(line + wbytes + i - 1); >+ t <<= 8 - s; >+ t |= *(line + wbytes + i) >> s; >+ *(right + i) = t; >+ } >+ *(right + wbytes - 1) &= 0xFF << s; > } > > return (0); > } > >+static void >+set_width(int v) >+{ >+ if (v < 1 || v > VFNT_MAXDIMENSION) >+ errx(1, "invalid width %d", v); >+ width = v; >+ wbytes = howmany(width, 8); >+} >+ >+static void >+set_height(int v) >+{ >+ if (v < 1 || v > VFNT_MAXDIMENSION) >+ errx(1, "invalid height %d", v); >+ height = v; >+} >+ > static int > parse_bdf(FILE *fp, unsigned int map_idx) > { >- char *ln; >+ char *ln, *p;; > size_t length; >- uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; >- unsigned int curchar = 0, dwidth = 0, i, line; >+ unsigned int linenum = 0, i, j; >+ int rv = 0; >+ >+ char spacing = '\0'; >+ int fbbw, fbbh, fbbox, fbboy, dwx, dwy; >+ >+ fbbw = fbbh = fbbox = fbboy = dwx = dwy = 0; > > while ((ln = fgetln(fp, &length)) != NULL) { >+ linenum++; > ln[length - 1] = '\0'; > >- if (strncmp(ln, "ENCODING ", 9) == 0) { >- curchar = atoi(ln + 9); >+ if (strncmp(ln, "FONT ", 5) == 0) { >+ p = ln + 5; i = 0; >+ while ((p = strchr(p, '-')) != NULL) { >+ p++; i++; >+ if (i == 11) { >+ spacing = *p; >+ break; >+ } >+ } >+ } else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0 && >+ sscanf(ln + 16, "%d %d %d %d", >+ &fbbw, &fbbh, &fbbox, &fbboy) == 4) { >+ set_width(fbbw); >+ set_height(fbbh); >+ break; > } >+ } >+ >+ if (fbbw == 0 && fbbh == 0) >+ errx(1, "Broken font header!"); >+ if (spacing != 'c' && spacing != 'C') >+ errx(1, "Font spacing \"C\" (Character cell) required"); >+ >+ while ((ln = fgetln(fp, &length)) != NULL) { >+ linenum++; >+ ln[length - 1] = '\0'; > >- if (strncmp(ln, "DWIDTH ", 7) == 0) { >- dwidth = atoi(ln + 7); >+ if (strncmp(ln, "DWIDTH ", 7) == 0 && >+ sscanf(ln + 7, "%d %d", &dwx, &dwy) == 1) { >+ if (dwy != 0 || (dwx != fbbw && dwx * 2 != fbbw)) >+ errx(1, "Bitmap with unsupported " >+ "DWIDTH %d %d at line %u", >+ dwx, dwy, linenum); >+ else if (dwx < fbbw) >+ set_width(dwx); > } >+ } > >- if (strncmp(ln, "BITMAP", 6) == 0 && >+ uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; >+ unsigned int curchar = 0, bbwbytes; >+ int bbw, bbh, bbox, bboy; >+ >+ linenum = 0; >+ dwx = bbw = bbh = 0; >+ rewind(fp); >+ while ((ln = fgetln(fp, &length)) != NULL) { >+ linenum++; >+ ln[length - 1] = '\0'; >+ >+ if (strncmp(ln, "ENCODING ", 9) == 0) >+ curchar = atoi(ln + 9); >+ else if (strncmp(ln, "DWIDTH ", 7) == 0) >+ dwx = atoi(ln + 7); >+ else if (strncmp(ln, "BBX ", 4) == 0 && >+ sscanf(ln + 4, "%d %d %d %d", >+ &bbw, &bbh, &bbox, &bboy) == 4) { >+ if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh || >+ bbox < fbbox || bboy < fbboy) >+ errx(1, "Broken bitmap with " >+ "BBX %d %d %d %d at line %u", >+ bbw, bbh, bbox, bboy, linenum); >+ bbwbytes = howmany(bbw, 8); >+ } else if (strncmp(ln, "BITMAP", 6) == 0 && > (ln[6] == ' ' || ln[6] == '\0')) { >+ if (dwx == 0 || bbw == 0 || bbh == 0) >+ errx(1, "Broken char header at line %u!", >+ linenum); >+ if (bytes == NULL) { >+ bytes = xmalloc(wbytes * height); >+ bytes_r = xmalloc(wbytes * height); >+ line = xmalloc(wbytes * 2); >+ } else { >+ memset(bytes, 0, wbytes * height); >+ memset(bytes_r, 0, wbytes * height); >+ } >+ > /* >- * Assume that the next _height_ lines are bitmap >- * data. ENDCHAR is allowed to terminate the bitmap >+ * Assume that the next _bbh_ lines are bitmap data. >+ * ENDCHAR is allowed to terminate the bitmap > * early but is not otherwise checked; any extra data > * is ignored. > */ >- for (i = 0; i < height; i++) { >+ for (i = (fbbh + fbboy) - (bbh + bboy); >+ i < (unsigned int) ((fbbh + fbboy) - bboy); i++) { > if ((ln = fgetln(fp, &length)) == NULL) > errx(1, "Unexpected EOF!"); >+ linenum++; > ln[length - 1] = '\0'; >- if (strcmp(ln, "ENDCHAR") == 0) { >- memset(bytes + i * wbytes, 0, >- (height - i) * wbytes); >- memset(bytes_r + i * wbytes, 0, >- (height - i) * wbytes); >+ >+ if (strcmp(ln, "ENDCHAR") == 0) > break; >+ >+ if (strlen(ln) < bbwbytes * 2) >+ errx(1, "Broken bitmap at line %u!", >+ linenum); >+ memset(line, 0, wbytes * 2); >+ for (j = 0; j < bbwbytes; j++) { >+ unsigned int val; >+ if (sscanf(ln + j * 2, "%2x", &val) == 0) >+ break; >+ *(line + j) = (uint8_t) val; > } >- sscanf(ln, "%x", &line); >- if (parse_bitmap_line(bytes + i * wbytes, >- bytes_r + i * wbytes, line, dwidth) != 0) >- return (1); >+ >+ rv = rshift_bitmap_line(line, wbytes * 2, >+ bbw, bbox - fbbox); >+ if (rv != 0) >+ goto out; >+ >+ rv = split_bitmap_line(bytes + i * wbytes, >+ bytes_r + i * wbytes, line, dwx); >+ if (rv != 0) >+ goto out; > } > >- if (add_char(curchar, map_idx, bytes, >- dwidth == width * 2 ? bytes_r : NULL) != 0) >- return (1); >+ rv = add_char(curchar, map_idx, bytes, >+ dwx > (int) width ? bytes_r : NULL); >+ if (rv != 0) >+ goto out; >+ >+ dwx = bbw = bbh = 0; > } > } > >- return (0); >-} >- >-static void >-set_width(int w) >-{ >+out: >+ free(bytes); >+ free(bytes_r); >+ free(line); > >- if (w <= 0 || w > 128) >- errx(1, "invalid width %d", w); >- width = w; >- wbytes = howmany(width, 8); >+ return (rv); > } > > static int > parse_hex(FILE *fp, unsigned int map_idx) > { > char *ln, *p; >- char fmt_str[8]; > size_t length; >- uint8_t *bytes = NULL, *bytes_r = NULL; >- unsigned curchar = 0, i, line, chars_per_row, dwidth; >+ uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; >+ unsigned int curchar = 0, gwidth, gwbytes, i, j, chars_per_row; > int rv = 0; > > while ((ln = fgetln(fp, &length)) != NULL) { >@@ -322,46 +459,61 @@ parse_hex(FILE *fp, unsigned int map_idx) > > if (strncmp(ln, "# Height: ", 10) == 0) { > if (bytes != NULL) >- errx(1, "malformed input: Height tag after font data"); >- height = atoi(ln + 10); >+ errx(1, "malformed input: " >+ "Height tag after font data"); >+ set_height(atoi(ln + 10)); > } else if (strncmp(ln, "# Width: ", 9) == 0) { > if (bytes != NULL) >- errx(1, "malformed input: Width tag after font data"); >+ errx(1, "malformed input: " >+ "Width tag after font data"); > set_width(atoi(ln + 9)); > } else if (sscanf(ln, "%6x:", &curchar)) { > if (bytes == NULL) { > bytes = xmalloc(wbytes * height); > bytes_r = xmalloc(wbytes * height); >+ line = xmalloc(wbytes * 2); > } >+ > /* ln is guaranteed to have a colon here. */ > p = strchr(ln, ':') + 1; > chars_per_row = strlen(p) / height; >- dwidth = width; >- if (chars_per_row / 2 > (width + 7) / 8) >- dwidth *= 2; /* Double-width character. */ >- snprintf(fmt_str, sizeof(fmt_str), "%%%ux", >- chars_per_row); >+ if (chars_per_row < wbytes * 2) >+ errx(1, "malformed input: " >+ "Broken bitmap, character %06x", >+ curchar); >+ gwidth = width * 2; >+ gwbytes = howmany(gwidth, 8); >+ if (chars_per_row < gwbytes * 2 || gwidth <= 8) { >+ gwidth = width; /* Single-width character. */ >+ gwbytes = wbytes; >+ } > > 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) { >- rv = 1; >- goto out; >+ for (j = 0; j < gwbytes; j++) { >+ unsigned int val; >+ if (sscanf(p + j * 2, "%2x", &val) == 0) >+ break; >+ *(line + j) = (uint8_t) val; > } >+ rv = split_bitmap_line(bytes + i * wbytes, >+ bytes_r + i * wbytes, line, gwidth); >+ if (rv != 0) >+ goto out; >+ p += gwbytes * 2; > } > >- if (add_char(curchar, map_idx, bytes, >- dwidth == width * 2 ? bytes_r : NULL) != 0) { >- rv = 1; >+ rv = add_char(curchar, map_idx, bytes, >+ gwidth != width ? bytes_r : NULL); >+ if (rv != 0) > goto out; >- } > } > } >+ > out: > free(bytes); > free(bytes_r); >+ free(line); >+ > return (rv); > } > >@@ -383,6 +535,7 @@ parse_file(const char *filename, unsigned int map_idx) > else > rv = parse_bdf(fp, map_idx); > fclose(fp); >+ > return (rv); > } > >@@ -454,7 +607,9 @@ write_mappings(FILE *fp, unsigned int map_idx) > return (1); > } > } >+ > assert(i == j); >+ > return (0); > } > >@@ -496,9 +651,9 @@ write_fnt(const char *filename) > > if (write_glyphs(fp) != 0 || > write_mappings(fp, VFNT_MAP_NORMAL) != 0 || >- write_mappings(fp, 1) != 0 || >+ write_mappings(fp, VFNT_MAP_NORMAL_RIGHT) != 0 || > write_mappings(fp, VFNT_MAP_BOLD) != 0 || >- write_mappings(fp, 3) != 0) { >+ write_mappings(fp, VFNT_MAP_BOLD_RIGHT) != 0) { > perror(filename); > fclose(fp); > return (1); >@@ -512,43 +667,47 @@ static void > print_font_info(void) > { > printf( >-"Statistics:\n" >-"- glyph_total: %6u\n" >-"- glyph_normal: %6u\n" >-"- glyph_normal_right: %6u\n" >-"- glyph_bold: %6u\n" >-"- glyph_bold_right: %6u\n" >-"- glyph_unique: %6u\n" >-"- glyph_dupe: %6u\n" >-"- mapping_total: %6u\n" >-"- mapping_normal: %6u\n" >-"- mapping_normal_folded: %6u\n" >-"- mapping_normal_right: %6u\n" >-"- mapping_normal_right_folded: %6u\n" >-"- mapping_bold: %6u\n" >-"- mapping_bold_folded: %6u\n" >-"- mapping_bold_right: %6u\n" >-"- mapping_bold_right_folded: %6u\n" >-"- mapping_unique: %6u\n" >-"- mapping_dupe: %6u\n", >- glyph_total, >- glyph_count[0], >- glyph_count[1], >- glyph_count[2], >- glyph_count[3], >- glyph_unique, glyph_dupe, >- mapping_total, >- map_count[0], map_folded_count[0], >- map_count[1], map_folded_count[1], >- map_count[2], map_folded_count[2], >- map_count[3], map_folded_count[3], >- mapping_unique, mapping_dupe); >+ "Statistics:\n" >+ "- font_width: %6u\n" >+ "- font_height: %6u\n" >+ "- glyph_total: %6u\n" >+ "- glyph_normal: %6u\n" >+ "- glyph_normal_right: %6u\n" >+ "- glyph_bold: %6u\n" >+ "- glyph_bold_right: %6u\n" >+ "- glyph_unique: %6u\n" >+ "- glyph_dupe: %6u\n" >+ "- mapping_total: %6u\n" >+ "- mapping_normal: %6u\n" >+ "- mapping_normal_folded: %6u\n" >+ "- mapping_normal_right: %6u\n" >+ "- mapping_normal_right_folded: %6u\n" >+ "- mapping_bold: %6u\n" >+ "- mapping_bold_folded: %6u\n" >+ "- mapping_bold_right: %6u\n" >+ "- mapping_bold_right_folded: %6u\n" >+ "- mapping_unique: %6u\n" >+ "- mapping_dupe: %6u\n", >+ width, height, >+ glyph_total, >+ glyph_count[0], >+ glyph_count[1], >+ glyph_count[2], >+ glyph_count[3], >+ glyph_unique, glyph_dupe, >+ mapping_total, >+ map_count[0], map_folded_count[0], >+ map_count[1], map_folded_count[1], >+ map_count[2], map_folded_count[2], >+ map_count[3], map_folded_count[3], >+ mapping_unique, mapping_dupe >+ ); > } > > int > main(int argc, char *argv[]) > { >- int ch, val, verbose = 0; >+ int ch, verbose = 0; > > assert(sizeof(struct file_header) == 32); > assert(sizeof(struct file_mapping) == 8); >@@ -556,16 +715,13 @@ main(int argc, char *argv[]) > while ((ch = getopt(argc, argv, "h:vw:")) != -1) { > switch (ch) { > case 'h': >- val = atoi(optarg); >- if (val <= 0 || val > 128) >- errx(1, "Invalid height %d", val); >- height = val; >+ height = atoi(optarg); > break; > case 'v': > verbose = 1; > break; > case 'w': >- set_width(atoi(optarg)); >+ width = atoi(optarg); > break; > case '?': > default: >@@ -578,7 +734,8 @@ main(int argc, char *argv[]) > if (argc < 2 || argc > 3) > usage(); > >- wbytes = howmany(width, 8); >+ set_width(width); >+ set_height(height); > > if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) > return (1); >@@ -592,7 +749,7 @@ main(int argc, char *argv[]) > } > number_glyphs(); > dedup_mapping(VFNT_MAP_BOLD); >- dedup_mapping(VFNT_MAP_BOLD_RH); >+ dedup_mapping(VFNT_MAP_BOLD_RIGHT); > fold_mappings(0); > fold_mappings(1); > fold_mappings(2);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 205707
:
164832
|
164833
|
168728
|
180939
|
180943
|
194668
|
199764
|
199765
|
205123