Lines 44-54
__FBSDID("$FreeBSD: head/usr.bin/vtfontcvt/vtfontcvt.c 331935 2018-04-03 18:43:0
Link Here
|
44 |
#include <string.h> |
44 |
#include <string.h> |
45 |
#include <unistd.h> |
45 |
#include <unistd.h> |
46 |
|
46 |
|
47 |
#define VFNT_MAPS 4 |
47 |
#define VFNT_MAPS 4 |
48 |
#define VFNT_MAP_NORMAL 0 |
48 |
#define VFNT_MAP_NORMAL 0 |
49 |
#define VFNT_MAP_NORMAL_RH 1 |
49 |
#define VFNT_MAP_NORMAL_RIGHT 1 |
50 |
#define VFNT_MAP_BOLD 2 |
50 |
#define VFNT_MAP_BOLD 2 |
51 |
#define VFNT_MAP_BOLD_RH 3 |
51 |
#define VFNT_MAP_BOLD_RIGHT 3 |
|
|
52 |
#define VFNT_MAXGLYPHS 131072 |
53 |
#define VFNT_MAXDIMENSION 128 |
52 |
|
54 |
|
53 |
static unsigned int width = 8, wbytes, height = 16; |
55 |
static unsigned int width = 8, wbytes, height = 16; |
54 |
|
56 |
|
Lines 63-72
struct glyph {
Link Here
|
63 |
TAILQ_HEAD(glyph_list, glyph); |
65 |
TAILQ_HEAD(glyph_list, glyph); |
64 |
static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; |
66 |
static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; |
65 |
static struct glyph_list glyphs[VFNT_MAPS] = { |
67 |
static struct glyph_list glyphs[VFNT_MAPS] = { |
66 |
TAILQ_HEAD_INITIALIZER(glyphs[0]), |
68 |
TAILQ_HEAD_INITIALIZER(glyphs[0]), |
67 |
TAILQ_HEAD_INITIALIZER(glyphs[1]), |
69 |
TAILQ_HEAD_INITIALIZER(glyphs[1]), |
68 |
TAILQ_HEAD_INITIALIZER(glyphs[2]), |
70 |
TAILQ_HEAD_INITIALIZER(glyphs[2]), |
69 |
TAILQ_HEAD_INITIALIZER(glyphs[3]), |
71 |
TAILQ_HEAD_INITIALIZER(glyphs[3]), |
70 |
}; |
72 |
}; |
71 |
static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; |
73 |
static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; |
72 |
|
74 |
|
Lines 79-91
struct mapping {
Link Here
|
79 |
|
81 |
|
80 |
TAILQ_HEAD(mapping_list, mapping); |
82 |
TAILQ_HEAD(mapping_list, mapping); |
81 |
static struct mapping_list maps[VFNT_MAPS] = { |
83 |
static struct mapping_list maps[VFNT_MAPS] = { |
82 |
TAILQ_HEAD_INITIALIZER(maps[0]), |
84 |
TAILQ_HEAD_INITIALIZER(maps[0]), |
83 |
TAILQ_HEAD_INITIALIZER(maps[1]), |
85 |
TAILQ_HEAD_INITIALIZER(maps[1]), |
84 |
TAILQ_HEAD_INITIALIZER(maps[2]), |
86 |
TAILQ_HEAD_INITIALIZER(maps[2]), |
85 |
TAILQ_HEAD_INITIALIZER(maps[3]), |
87 |
TAILQ_HEAD_INITIALIZER(maps[3]), |
86 |
}; |
88 |
}; |
87 |
static unsigned int mapping_total, map_count[4], map_folded_count[4], |
89 |
static unsigned int mapping_total, map_count[4], map_folded_count[4], |
88 |
mapping_unique, mapping_dupe; |
90 |
mapping_unique, mapping_dupe; |
89 |
|
91 |
|
90 |
static void |
92 |
static void |
91 |
usage(void) |
93 |
usage(void) |
Lines 103-115
xmalloc(size_t size)
Link Here
|
103 |
|
105 |
|
104 |
if ((m = malloc(size)) == NULL) |
106 |
if ((m = malloc(size)) == NULL) |
105 |
errx(1, "memory allocation failure"); |
107 |
errx(1, "memory allocation failure"); |
|
|
108 |
memset(m, 0, size); |
109 |
|
106 |
return (m); |
110 |
return (m); |
107 |
} |
111 |
} |
108 |
|
112 |
|
109 |
static int |
113 |
static int |
110 |
add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) |
114 |
add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) |
111 |
{ |
115 |
{ |
112 |
struct mapping *mp; |
116 |
struct mapping *mp, *mp_temp = NULL; |
113 |
struct mapping_list *ml; |
117 |
struct mapping_list *ml; |
114 |
|
118 |
|
115 |
mapping_total++; |
119 |
mapping_total++; |
Lines 120-129
add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx)
Link Here
|
120 |
mp->m_length = 0; |
124 |
mp->m_length = 0; |
121 |
|
125 |
|
122 |
ml = &maps[map_idx]; |
126 |
ml = &maps[map_idx]; |
123 |
if (TAILQ_LAST(ml, mapping_list) != NULL && |
127 |
TAILQ_FOREACH(mp_temp, ml, m_list) { |
124 |
TAILQ_LAST(ml, mapping_list)->m_char >= c) |
128 |
if (mp_temp->m_char >= c) |
125 |
errx(1, "Bad ordering at character %u", c); |
129 |
break; |
126 |
TAILQ_INSERT_TAIL(ml, mp, m_list); |
130 |
} |
|
|
131 |
if (mp_temp == NULL) |
132 |
TAILQ_INSERT_TAIL(ml, mp, m_list); |
133 |
else |
134 |
TAILQ_INSERT_BEFORE(mp_temp, mp, m_list); |
127 |
|
135 |
|
128 |
map_count[map_idx]++; |
136 |
map_count[map_idx]++; |
129 |
mapping_unique++; |
137 |
mapping_unique++; |
Lines 137-143
dedup_mapping(unsigned int map_idx)
Link Here
|
137 |
struct mapping *mp_bold, *mp_normal, *mp_temp; |
145 |
struct mapping *mp_bold, *mp_normal, *mp_temp; |
138 |
unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; |
146 |
unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; |
139 |
|
147 |
|
140 |
assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RH); |
148 |
assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RIGHT); |
141 |
mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); |
149 |
mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); |
142 |
TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { |
150 |
TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { |
143 |
while (mp_normal->m_char < mp_bold->m_char) |
151 |
while (mp_normal->m_char < mp_bold->m_char) |
Lines 153-158
dedup_mapping(unsigned int map_idx)
Link Here
|
153 |
free(mp_bold); |
161 |
free(mp_bold); |
154 |
mapping_dupe++; |
162 |
mapping_dupe++; |
155 |
} |
163 |
} |
|
|
164 |
|
156 |
return (0); |
165 |
return (0); |
157 |
} |
166 |
} |
158 |
|
167 |
|
Lines 183-188
add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback)
Link Here
|
183 |
SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); |
192 |
SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); |
184 |
|
193 |
|
185 |
glyph_unique++; |
194 |
glyph_unique++; |
|
|
195 |
|
196 |
if (glyph_unique > VFNT_MAXGLYPHS) |
197 |
errx(1, "Too large number of glyphs %u!", glyph_unique); |
198 |
|
186 |
return (gl); |
199 |
return (gl); |
187 |
} |
200 |
} |
188 |
|
201 |
|
Lines 201-320
add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r)
Link Here
|
201 |
return (1); |
214 |
return (1); |
202 |
if (bytes_r != NULL) { |
215 |
if (bytes_r != NULL) { |
203 |
gl = add_glyph(bytes_r, map_idx + 1, 0); |
216 |
gl = add_glyph(bytes_r, map_idx + 1, 0); |
204 |
if (add_mapping(gl, curchar, |
217 |
if (add_mapping(gl, curchar, map_idx + 1) != 0) |
205 |
map_idx + 1) != 0) |
|
|
206 |
return (1); |
218 |
return (1); |
207 |
} |
219 |
} |
208 |
} |
220 |
} |
|
|
221 |
|
209 |
return (0); |
222 |
return (0); |
210 |
} |
223 |
} |
211 |
|
224 |
|
212 |
|
|
|
213 |
static int |
225 |
static int |
214 |
parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, |
226 |
rshift_bitmap_line(uint8_t *line, size_t size, size_t len, size_t shift) |
215 |
unsigned int dwidth) |
|
|
216 |
{ |
227 |
{ |
217 |
uint8_t *p; |
228 |
size_t d, s, i; |
218 |
unsigned int i, subline; |
229 |
uint16_t t; |
219 |
|
230 |
|
220 |
if (dwidth != width && dwidth != width * 2) |
231 |
assert(size > 0 && len > 0); |
221 |
errx(1, "Bitmap with unsupported width %u!", dwidth); |
232 |
assert(size * 8 >= len); |
222 |
|
233 |
|
223 |
/* Move pixel data right to simplify splitting double characters. */ |
234 |
if (shift == 0) |
224 |
line >>= (howmany(dwidth, 8) * 8) - dwidth; |
235 |
return (0); |
225 |
|
236 |
|
226 |
for (i = dwidth / width; i > 0; i--) { |
237 |
d = shift / 8; |
227 |
p = (i == 2) ? right : left; |
238 |
s = 8 - shift % 8; |
|
|
239 |
i = howmany(len, 8); |
228 |
|
240 |
|
229 |
subline = line & ((1 << width) - 1); |
241 |
while (i > 0) { |
230 |
subline <<= (howmany(width, 8) * 8) - width; |
242 |
i--; |
231 |
|
243 |
|
232 |
if (wbytes == 1) { |
244 |
t = *(line + i); |
233 |
*p = subline; |
245 |
*(line + i) = 0; |
234 |
} else if (wbytes == 2) { |
246 |
|
235 |
*p++ = subline >> 8; |
247 |
t <<= s; |
236 |
*p = subline; |
248 |
|
237 |
} else { |
249 |
if (i + d + 1 < size) |
238 |
errx(1, "Unsupported wbytes %u!", wbytes); |
250 |
*(line + i + d + 1) |= (uint8_t) t; |
239 |
} |
251 |
if (i + d < size) |
|
|
252 |
*(line + i + d) = t >> 8; |
253 |
} |
254 |
|
255 |
return (0); |
256 |
} |
257 |
|
258 |
static int |
259 |
split_bitmap_line(uint8_t *left, uint8_t *right, uint8_t *line, size_t w) |
260 |
{ |
261 |
size_t s, i; |
262 |
|
263 |
s = 8 - width % 8; |
264 |
|
265 |
memcpy(left, line, wbytes); |
266 |
*(left + wbytes - 1) &= 0xFF << s; |
240 |
|
267 |
|
241 |
line >>= width; |
268 |
if (w > width) { /* Double-width character. */ |
|
|
269 |
uint8_t t; |
270 |
|
271 |
for (i = 0; i < wbytes; i++) { |
272 |
t = *(line + wbytes + i - 1); |
273 |
t <<= 8 - s; |
274 |
t |= *(line + wbytes + i) >> s; |
275 |
*(right + i) = t; |
276 |
} |
277 |
*(right + wbytes - 1) &= 0xFF << s; |
242 |
} |
278 |
} |
243 |
|
279 |
|
244 |
return (0); |
280 |
return (0); |
245 |
} |
281 |
} |
246 |
|
282 |
|
|
|
283 |
static void |
284 |
set_width(int v) |
285 |
{ |
286 |
if (v < 1 || v > VFNT_MAXDIMENSION) |
287 |
errx(1, "invalid width %d", v); |
288 |
width = v; |
289 |
wbytes = howmany(width, 8); |
290 |
} |
291 |
|
292 |
static void |
293 |
set_height(int v) |
294 |
{ |
295 |
if (v < 1 || v > VFNT_MAXDIMENSION) |
296 |
errx(1, "invalid height %d", v); |
297 |
height = v; |
298 |
} |
299 |
|
247 |
static int |
300 |
static int |
248 |
parse_bdf(FILE *fp, unsigned int map_idx) |
301 |
parse_bdf(FILE *fp, unsigned int map_idx) |
249 |
{ |
302 |
{ |
250 |
char *ln; |
303 |
char *ln, *p;; |
251 |
size_t length; |
304 |
size_t length; |
252 |
uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; |
305 |
unsigned int linenum = 0, i, j; |
253 |
unsigned int curchar = 0, dwidth = 0, i, line; |
306 |
int rv = 0; |
|
|
307 |
|
308 |
char spacing = '\0'; |
309 |
int fbbw, fbbh, fbbox, fbboy, dwx, dwy; |
310 |
|
311 |
fbbw = fbbh = fbbox = fbboy = dwx = dwy = 0; |
254 |
|
312 |
|
255 |
while ((ln = fgetln(fp, &length)) != NULL) { |
313 |
while ((ln = fgetln(fp, &length)) != NULL) { |
|
|
314 |
linenum++; |
256 |
ln[length - 1] = '\0'; |
315 |
ln[length - 1] = '\0'; |
257 |
|
316 |
|
258 |
if (strncmp(ln, "ENCODING ", 9) == 0) { |
317 |
if (strncmp(ln, "FONT ", 5) == 0) { |
259 |
curchar = atoi(ln + 9); |
318 |
p = ln + 5; i = 0; |
|
|
319 |
while ((p = strchr(p, '-')) != NULL) { |
320 |
p++; i++; |
321 |
if (i == 11) { |
322 |
spacing = *p; |
323 |
break; |
324 |
} |
325 |
} |
326 |
} else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0 && |
327 |
sscanf(ln + 16, "%d %d %d %d", |
328 |
&fbbw, &fbbh, &fbbox, &fbboy) == 4) { |
329 |
set_width(fbbw); |
330 |
set_height(fbbh); |
331 |
break; |
260 |
} |
332 |
} |
|
|
333 |
} |
334 |
|
335 |
if (fbbw == 0 && fbbh == 0) |
336 |
errx(1, "Broken font header!"); |
337 |
if (spacing != 'c' && spacing != 'C') |
338 |
errx(1, "Font spacing \"C\" (Character cell) required"); |
339 |
|
340 |
while ((ln = fgetln(fp, &length)) != NULL) { |
341 |
linenum++; |
342 |
ln[length - 1] = '\0'; |
261 |
|
343 |
|
262 |
if (strncmp(ln, "DWIDTH ", 7) == 0) { |
344 |
if (strncmp(ln, "DWIDTH ", 7) == 0 && |
263 |
dwidth = atoi(ln + 7); |
345 |
sscanf(ln + 7, "%d %d", &dwx, &dwy) == 1) { |
|
|
346 |
if (dwy != 0 || (dwx != fbbw && dwx * 2 != fbbw)) |
347 |
errx(1, "Bitmap with unsupported " |
348 |
"DWIDTH %d %d at line %u", |
349 |
dwx, dwy, linenum); |
350 |
else if (dwx < fbbw) |
351 |
set_width(dwx); |
264 |
} |
352 |
} |
|
|
353 |
} |
265 |
|
354 |
|
266 |
if (strncmp(ln, "BITMAP", 6) == 0 && |
355 |
uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; |
|
|
356 |
unsigned int curchar = 0, bbwbytes; |
357 |
int bbw, bbh, bbox, bboy; |
358 |
|
359 |
linenum = 0; |
360 |
dwx = bbw = bbh = 0; |
361 |
rewind(fp); |
362 |
while ((ln = fgetln(fp, &length)) != NULL) { |
363 |
linenum++; |
364 |
ln[length - 1] = '\0'; |
365 |
|
366 |
if (strncmp(ln, "ENCODING ", 9) == 0) |
367 |
curchar = atoi(ln + 9); |
368 |
else if (strncmp(ln, "DWIDTH ", 7) == 0) |
369 |
dwx = atoi(ln + 7); |
370 |
else if (strncmp(ln, "BBX ", 4) == 0 && |
371 |
sscanf(ln + 4, "%d %d %d %d", |
372 |
&bbw, &bbh, &bbox, &bboy) == 4) { |
373 |
if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh || |
374 |
bbox < fbbox || bboy < fbboy) |
375 |
errx(1, "Broken bitmap with " |
376 |
"BBX %d %d %d %d at line %u", |
377 |
bbw, bbh, bbox, bboy, linenum); |
378 |
bbwbytes = howmany(bbw, 8); |
379 |
} else if (strncmp(ln, "BITMAP", 6) == 0 && |
267 |
(ln[6] == ' ' || ln[6] == '\0')) { |
380 |
(ln[6] == ' ' || ln[6] == '\0')) { |
|
|
381 |
if (dwx == 0 || bbw == 0 || bbh == 0) |
382 |
errx(1, "Broken char header at line %u!", |
383 |
linenum); |
384 |
if (bytes == NULL) { |
385 |
bytes = xmalloc(wbytes * height); |
386 |
bytes_r = xmalloc(wbytes * height); |
387 |
line = xmalloc(wbytes * 2); |
388 |
} else { |
389 |
memset(bytes, 0, wbytes * height); |
390 |
memset(bytes_r, 0, wbytes * height); |
391 |
} |
392 |
|
268 |
/* |
393 |
/* |
269 |
* Assume that the next _height_ lines are bitmap |
394 |
* Assume that the next _bbh_ lines are bitmap data. |
270 |
* data. ENDCHAR is allowed to terminate the bitmap |
395 |
* ENDCHAR is allowed to terminate the bitmap |
271 |
* early but is not otherwise checked; any extra data |
396 |
* early but is not otherwise checked; any extra data |
272 |
* is ignored. |
397 |
* is ignored. |
273 |
*/ |
398 |
*/ |
274 |
for (i = 0; i < height; i++) { |
399 |
for (i = (fbbh + fbboy) - (bbh + bboy); |
|
|
400 |
i < (unsigned int) ((fbbh + fbboy) - bboy); i++) { |
275 |
if ((ln = fgetln(fp, &length)) == NULL) |
401 |
if ((ln = fgetln(fp, &length)) == NULL) |
276 |
errx(1, "Unexpected EOF!"); |
402 |
errx(1, "Unexpected EOF!"); |
|
|
403 |
linenum++; |
277 |
ln[length - 1] = '\0'; |
404 |
ln[length - 1] = '\0'; |
278 |
if (strcmp(ln, "ENDCHAR") == 0) { |
405 |
|
279 |
memset(bytes + i * wbytes, 0, |
406 |
if (strcmp(ln, "ENDCHAR") == 0) |
280 |
(height - i) * wbytes); |
|
|
281 |
memset(bytes_r + i * wbytes, 0, |
282 |
(height - i) * wbytes); |
283 |
break; |
407 |
break; |
|
|
408 |
|
409 |
if (strlen(ln) < bbwbytes * 2) |
410 |
errx(1, "Broken bitmap at line %u!", |
411 |
linenum); |
412 |
memset(line, 0, wbytes * 2); |
413 |
for (j = 0; j < bbwbytes; j++) { |
414 |
unsigned int val; |
415 |
if (sscanf(ln + j * 2, "%2x", &val) == 0) |
416 |
break; |
417 |
*(line + j) = (uint8_t) val; |
284 |
} |
418 |
} |
285 |
sscanf(ln, "%x", &line); |
419 |
|
286 |
if (parse_bitmap_line(bytes + i * wbytes, |
420 |
rv = rshift_bitmap_line(line, wbytes * 2, |
287 |
bytes_r + i * wbytes, line, dwidth) != 0) |
421 |
bbw, bbox - fbbox); |
288 |
return (1); |
422 |
if (rv != 0) |
|
|
423 |
goto out; |
424 |
|
425 |
rv = split_bitmap_line(bytes + i * wbytes, |
426 |
bytes_r + i * wbytes, line, dwx); |
427 |
if (rv != 0) |
428 |
goto out; |
289 |
} |
429 |
} |
290 |
|
430 |
|
291 |
if (add_char(curchar, map_idx, bytes, |
431 |
rv = add_char(curchar, map_idx, bytes, |
292 |
dwidth == width * 2 ? bytes_r : NULL) != 0) |
432 |
dwx > (int) width ? bytes_r : NULL); |
293 |
return (1); |
433 |
if (rv != 0) |
|
|
434 |
goto out; |
435 |
|
436 |
dwx = bbw = bbh = 0; |
294 |
} |
437 |
} |
295 |
} |
438 |
} |
296 |
|
439 |
|
297 |
return (0); |
440 |
out: |
298 |
} |
441 |
free(bytes); |
299 |
|
442 |
free(bytes_r); |
300 |
static void |
443 |
free(line); |
301 |
set_width(int w) |
|
|
302 |
{ |
303 |
|
444 |
|
304 |
if (w <= 0 || w > 128) |
445 |
return (rv); |
305 |
errx(1, "invalid width %d", w); |
|
|
306 |
width = w; |
307 |
wbytes = howmany(width, 8); |
308 |
} |
446 |
} |
309 |
|
447 |
|
310 |
static int |
448 |
static int |
311 |
parse_hex(FILE *fp, unsigned int map_idx) |
449 |
parse_hex(FILE *fp, unsigned int map_idx) |
312 |
{ |
450 |
{ |
313 |
char *ln, *p; |
451 |
char *ln, *p; |
314 |
char fmt_str[8]; |
|
|
315 |
size_t length; |
452 |
size_t length; |
316 |
uint8_t *bytes = NULL, *bytes_r = NULL; |
453 |
uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; |
317 |
unsigned curchar = 0, i, line, chars_per_row, dwidth; |
454 |
unsigned int curchar = 0, gwidth, gwbytes, i, j, chars_per_row; |
318 |
int rv = 0; |
455 |
int rv = 0; |
319 |
|
456 |
|
320 |
while ((ln = fgetln(fp, &length)) != NULL) { |
457 |
while ((ln = fgetln(fp, &length)) != NULL) { |
Lines 322-367
parse_hex(FILE *fp, unsigned int map_idx)
Link Here
|
322 |
|
459 |
|
323 |
if (strncmp(ln, "# Height: ", 10) == 0) { |
460 |
if (strncmp(ln, "# Height: ", 10) == 0) { |
324 |
if (bytes != NULL) |
461 |
if (bytes != NULL) |
325 |
errx(1, "malformed input: Height tag after font data"); |
462 |
errx(1, "malformed input: " |
326 |
height = atoi(ln + 10); |
463 |
"Height tag after font data"); |
|
|
464 |
set_height(atoi(ln + 10)); |
327 |
} else if (strncmp(ln, "# Width: ", 9) == 0) { |
465 |
} else if (strncmp(ln, "# Width: ", 9) == 0) { |
328 |
if (bytes != NULL) |
466 |
if (bytes != NULL) |
329 |
errx(1, "malformed input: Width tag after font data"); |
467 |
errx(1, "malformed input: " |
|
|
468 |
"Width tag after font data"); |
330 |
set_width(atoi(ln + 9)); |
469 |
set_width(atoi(ln + 9)); |
331 |
} else if (sscanf(ln, "%6x:", &curchar)) { |
470 |
} else if (sscanf(ln, "%6x:", &curchar)) { |
332 |
if (bytes == NULL) { |
471 |
if (bytes == NULL) { |
333 |
bytes = xmalloc(wbytes * height); |
472 |
bytes = xmalloc(wbytes * height); |
334 |
bytes_r = xmalloc(wbytes * height); |
473 |
bytes_r = xmalloc(wbytes * height); |
|
|
474 |
line = xmalloc(wbytes * 2); |
335 |
} |
475 |
} |
|
|
476 |
|
336 |
/* ln is guaranteed to have a colon here. */ |
477 |
/* ln is guaranteed to have a colon here. */ |
337 |
p = strchr(ln, ':') + 1; |
478 |
p = strchr(ln, ':') + 1; |
338 |
chars_per_row = strlen(p) / height; |
479 |
chars_per_row = strlen(p) / height; |
339 |
dwidth = width; |
480 |
if (chars_per_row < wbytes * 2) |
340 |
if (chars_per_row / 2 > (width + 7) / 8) |
481 |
errx(1, "malformed input: " |
341 |
dwidth *= 2; /* Double-width character. */ |
482 |
"Broken bitmap, character %06x", |
342 |
snprintf(fmt_str, sizeof(fmt_str), "%%%ux", |
483 |
curchar); |
343 |
chars_per_row); |
484 |
gwidth = width * 2; |
|
|
485 |
gwbytes = howmany(gwidth, 8); |
486 |
if (chars_per_row < gwbytes * 2 || gwidth <= 8) { |
487 |
gwidth = width; /* Single-width character. */ |
488 |
gwbytes = wbytes; |
489 |
} |
344 |
|
490 |
|
345 |
for (i = 0; i < height; i++) { |
491 |
for (i = 0; i < height; i++) { |
346 |
sscanf(p, fmt_str, &line); |
492 |
for (j = 0; j < gwbytes; j++) { |
347 |
p += chars_per_row; |
493 |
unsigned int val; |
348 |
if (parse_bitmap_line(bytes + i * wbytes, |
494 |
if (sscanf(p + j * 2, "%2x", &val) == 0) |
349 |
bytes_r + i * wbytes, line, dwidth) != 0) { |
495 |
break; |
350 |
rv = 1; |
496 |
*(line + j) = (uint8_t) val; |
351 |
goto out; |
|
|
352 |
} |
497 |
} |
|
|
498 |
rv = split_bitmap_line(bytes + i * wbytes, |
499 |
bytes_r + i * wbytes, line, gwidth); |
500 |
if (rv != 0) |
501 |
goto out; |
502 |
p += gwbytes * 2; |
353 |
} |
503 |
} |
354 |
|
504 |
|
355 |
if (add_char(curchar, map_idx, bytes, |
505 |
rv = add_char(curchar, map_idx, bytes, |
356 |
dwidth == width * 2 ? bytes_r : NULL) != 0) { |
506 |
gwidth != width ? bytes_r : NULL); |
357 |
rv = 1; |
507 |
if (rv != 0) |
358 |
goto out; |
508 |
goto out; |
359 |
} |
|
|
360 |
} |
509 |
} |
361 |
} |
510 |
} |
|
|
511 |
|
362 |
out: |
512 |
out: |
363 |
free(bytes); |
513 |
free(bytes); |
364 |
free(bytes_r); |
514 |
free(bytes_r); |
|
|
515 |
free(line); |
516 |
|
365 |
return (rv); |
517 |
return (rv); |
366 |
} |
518 |
} |
367 |
|
519 |
|
Lines 383-388
parse_file(const char *filename, unsigned int map_idx)
Link Here
|
383 |
else |
535 |
else |
384 |
rv = parse_bdf(fp, map_idx); |
536 |
rv = parse_bdf(fp, map_idx); |
385 |
fclose(fp); |
537 |
fclose(fp); |
|
|
538 |
|
386 |
return (rv); |
539 |
return (rv); |
387 |
} |
540 |
} |
388 |
|
541 |
|
Lines 454-460
write_mappings(FILE *fp, unsigned int map_idx)
Link Here
|
454 |
return (1); |
607 |
return (1); |
455 |
} |
608 |
} |
456 |
} |
609 |
} |
|
|
610 |
|
457 |
assert(i == j); |
611 |
assert(i == j); |
|
|
612 |
|
458 |
return (0); |
613 |
return (0); |
459 |
} |
614 |
} |
460 |
|
615 |
|
Lines 496-504
write_fnt(const char *filename)
Link Here
|
496 |
|
651 |
|
497 |
if (write_glyphs(fp) != 0 || |
652 |
if (write_glyphs(fp) != 0 || |
498 |
write_mappings(fp, VFNT_MAP_NORMAL) != 0 || |
653 |
write_mappings(fp, VFNT_MAP_NORMAL) != 0 || |
499 |
write_mappings(fp, 1) != 0 || |
654 |
write_mappings(fp, VFNT_MAP_NORMAL_RIGHT) != 0 || |
500 |
write_mappings(fp, VFNT_MAP_BOLD) != 0 || |
655 |
write_mappings(fp, VFNT_MAP_BOLD) != 0 || |
501 |
write_mappings(fp, 3) != 0) { |
656 |
write_mappings(fp, VFNT_MAP_BOLD_RIGHT) != 0) { |
502 |
perror(filename); |
657 |
perror(filename); |
503 |
fclose(fp); |
658 |
fclose(fp); |
504 |
return (1); |
659 |
return (1); |
Lines 512-554
static void
Link Here
|
512 |
print_font_info(void) |
667 |
print_font_info(void) |
513 |
{ |
668 |
{ |
514 |
printf( |
669 |
printf( |
515 |
"Statistics:\n" |
670 |
"Statistics:\n" |
516 |
"- glyph_total: %6u\n" |
671 |
"- font_width: %6u\n" |
517 |
"- glyph_normal: %6u\n" |
672 |
"- font_height: %6u\n" |
518 |
"- glyph_normal_right: %6u\n" |
673 |
"- glyph_total: %6u\n" |
519 |
"- glyph_bold: %6u\n" |
674 |
"- glyph_normal: %6u\n" |
520 |
"- glyph_bold_right: %6u\n" |
675 |
"- glyph_normal_right: %6u\n" |
521 |
"- glyph_unique: %6u\n" |
676 |
"- glyph_bold: %6u\n" |
522 |
"- glyph_dupe: %6u\n" |
677 |
"- glyph_bold_right: %6u\n" |
523 |
"- mapping_total: %6u\n" |
678 |
"- glyph_unique: %6u\n" |
524 |
"- mapping_normal: %6u\n" |
679 |
"- glyph_dupe: %6u\n" |
525 |
"- mapping_normal_folded: %6u\n" |
680 |
"- mapping_total: %6u\n" |
526 |
"- mapping_normal_right: %6u\n" |
681 |
"- mapping_normal: %6u\n" |
527 |
"- mapping_normal_right_folded: %6u\n" |
682 |
"- mapping_normal_folded: %6u\n" |
528 |
"- mapping_bold: %6u\n" |
683 |
"- mapping_normal_right: %6u\n" |
529 |
"- mapping_bold_folded: %6u\n" |
684 |
"- mapping_normal_right_folded: %6u\n" |
530 |
"- mapping_bold_right: %6u\n" |
685 |
"- mapping_bold: %6u\n" |
531 |
"- mapping_bold_right_folded: %6u\n" |
686 |
"- mapping_bold_folded: %6u\n" |
532 |
"- mapping_unique: %6u\n" |
687 |
"- mapping_bold_right: %6u\n" |
533 |
"- mapping_dupe: %6u\n", |
688 |
"- mapping_bold_right_folded: %6u\n" |
534 |
glyph_total, |
689 |
"- mapping_unique: %6u\n" |
535 |
glyph_count[0], |
690 |
"- mapping_dupe: %6u\n", |
536 |
glyph_count[1], |
691 |
width, height, |
537 |
glyph_count[2], |
692 |
glyph_total, |
538 |
glyph_count[3], |
693 |
glyph_count[0], |
539 |
glyph_unique, glyph_dupe, |
694 |
glyph_count[1], |
540 |
mapping_total, |
695 |
glyph_count[2], |
541 |
map_count[0], map_folded_count[0], |
696 |
glyph_count[3], |
542 |
map_count[1], map_folded_count[1], |
697 |
glyph_unique, glyph_dupe, |
543 |
map_count[2], map_folded_count[2], |
698 |
mapping_total, |
544 |
map_count[3], map_folded_count[3], |
699 |
map_count[0], map_folded_count[0], |
545 |
mapping_unique, mapping_dupe); |
700 |
map_count[1], map_folded_count[1], |
|
|
701 |
map_count[2], map_folded_count[2], |
702 |
map_count[3], map_folded_count[3], |
703 |
mapping_unique, mapping_dupe |
704 |
); |
546 |
} |
705 |
} |
547 |
|
706 |
|
548 |
int |
707 |
int |
549 |
main(int argc, char *argv[]) |
708 |
main(int argc, char *argv[]) |
550 |
{ |
709 |
{ |
551 |
int ch, val, verbose = 0; |
710 |
int ch, verbose = 0; |
552 |
|
711 |
|
553 |
assert(sizeof(struct file_header) == 32); |
712 |
assert(sizeof(struct file_header) == 32); |
554 |
assert(sizeof(struct file_mapping) == 8); |
713 |
assert(sizeof(struct file_mapping) == 8); |
Lines 556-571
main(int argc, char *argv[])
Link Here
|
556 |
while ((ch = getopt(argc, argv, "h:vw:")) != -1) { |
715 |
while ((ch = getopt(argc, argv, "h:vw:")) != -1) { |
557 |
switch (ch) { |
716 |
switch (ch) { |
558 |
case 'h': |
717 |
case 'h': |
559 |
val = atoi(optarg); |
718 |
height = atoi(optarg); |
560 |
if (val <= 0 || val > 128) |
|
|
561 |
errx(1, "Invalid height %d", val); |
562 |
height = val; |
563 |
break; |
719 |
break; |
564 |
case 'v': |
720 |
case 'v': |
565 |
verbose = 1; |
721 |
verbose = 1; |
566 |
break; |
722 |
break; |
567 |
case 'w': |
723 |
case 'w': |
568 |
set_width(atoi(optarg)); |
724 |
width = atoi(optarg); |
569 |
break; |
725 |
break; |
570 |
case '?': |
726 |
case '?': |
571 |
default: |
727 |
default: |
Lines 578-584
main(int argc, char *argv[])
Link Here
|
578 |
if (argc < 2 || argc > 3) |
734 |
if (argc < 2 || argc > 3) |
579 |
usage(); |
735 |
usage(); |
580 |
|
736 |
|
581 |
wbytes = howmany(width, 8); |
737 |
set_width(width); |
|
|
738 |
set_height(height); |
582 |
|
739 |
|
583 |
if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) |
740 |
if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) |
584 |
return (1); |
741 |
return (1); |
Lines 592-598
main(int argc, char *argv[])
Link Here
|
592 |
} |
749 |
} |
593 |
number_glyphs(); |
750 |
number_glyphs(); |
594 |
dedup_mapping(VFNT_MAP_BOLD); |
751 |
dedup_mapping(VFNT_MAP_BOLD); |
595 |
dedup_mapping(VFNT_MAP_BOLD_RH); |
752 |
dedup_mapping(VFNT_MAP_BOLD_RIGHT); |
596 |
fold_mappings(0); |
753 |
fold_mappings(0); |
597 |
fold_mappings(1); |
754 |
fold_mappings(1); |
598 |
fold_mappings(2); |
755 |
fold_mappings(2); |