Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/vtfontcvt/vtfontcvt.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <lz4.h> | #include <lz4.h> | ||||
#define VFNT_MAXGLYPHS 131072 | #define VFNT_MAXGLYPHS 131072 | ||||
#define VFNT_MAXDIMENSION 128 | #define VFNT_MAXDIMENSION 128 | ||||
static unsigned int width = 8, wbytes, height = 16; | static unsigned int width = 8, wbytes, height = 16; | ||||
struct glyph { | struct glyph { | ||||
TAILQ_ENTRY(glyph) g_list; | TAILQ_ENTRY(glyph) g_list; | ||||
domagoj.stolfa_gmail.com: This whole struct is not great. | |||||
SLIST_ENTRY(glyph) g_hash; | SLIST_ENTRY(glyph) g_hash; | ||||
uint8_t *g_data; | uint8_t *g_data; | ||||
unsigned int g_index; | unsigned int g_index; | ||||
}; | }; | ||||
#define FONTCVT_NHASH 4096 | #define FONTCVT_NHASH 4096 | ||||
TAILQ_HEAD(glyph_list, glyph); | TAILQ_HEAD(glyph_list, glyph); | ||||
static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; | static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; | ||||
static struct glyph_list glyphs[VFNT_MAPS] = { | static struct glyph_list glyphs[VFNT_MAPS] = { | ||||
Done Inline ActionsShould the brace be on a new line here? domagoj.stolfa_gmail.com: Should the brace be on a new line here? | |||||
TAILQ_HEAD_INITIALIZER(glyphs[0]), | TAILQ_HEAD_INITIALIZER(glyphs[0]), | ||||
TAILQ_HEAD_INITIALIZER(glyphs[1]), | TAILQ_HEAD_INITIALIZER(glyphs[1]), | ||||
TAILQ_HEAD_INITIALIZER(glyphs[2]), | TAILQ_HEAD_INITIALIZER(glyphs[2]), | ||||
TAILQ_HEAD_INITIALIZER(glyphs[3]), | TAILQ_HEAD_INITIALIZER(glyphs[3]), | ||||
}; | }; | ||||
static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; | static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; | ||||
struct mapping { | struct mapping { | ||||
TAILQ_ENTRY(mapping) m_list; | TAILQ_ENTRY(mapping) m_list; | ||||
unsigned int m_char; | unsigned int m_char; | ||||
unsigned int m_length; | unsigned int m_length; | ||||
struct glyph *m_glyph; | struct glyph *m_glyph; | ||||
}; | }; | ||||
TAILQ_HEAD(mapping_list, mapping); | TAILQ_HEAD(mapping_list, mapping); | ||||
static struct mapping_list maps[VFNT_MAPS] = { | static struct mapping_list maps[VFNT_MAPS] = { | ||||
TAILQ_HEAD_INITIALIZER(maps[0]), | TAILQ_HEAD_INITIALIZER(maps[0]), | ||||
TAILQ_HEAD_INITIALIZER(maps[1]), | TAILQ_HEAD_INITIALIZER(maps[1]), | ||||
TAILQ_HEAD_INITIALIZER(maps[2]), | TAILQ_HEAD_INITIALIZER(maps[2]), | ||||
TAILQ_HEAD_INITIALIZER(maps[3]), | TAILQ_HEAD_INITIALIZER(maps[3]), | ||||
}; | }; | ||||
static unsigned int mapping_total, map_count[4], map_folded_count[4], | static unsigned int mapping_total, map_count[4], map_folded_count[4], | ||||
mapping_unique, mapping_dupe; | mapping_unique, mapping_dupe; | ||||
enum output_format { | enum output_format { | ||||
VT_FONT, /* default */ | VT_FONT, /* default */ | ||||
VT_C_SOURCE, /* C source for built in fonts */ | VT_C_SOURCE, /* C source for built in fonts */ | ||||
VT_C_COMPRESSED /* C source with compressed font data */ | VT_C_COMPRESSED /* C source with compressed font data */ | ||||
}; | }; | ||||
struct whitelist { | struct whitelist { | ||||
uint32_t c; | uint32_t c; | ||||
uint32_t len; | uint32_t len; | ||||
}; | }; | ||||
/* | /* | ||||
* Compressed font glyph list. To be used with boot loader, we need to have | * Compressed font glyph list. To be used with boot loader, we need to have | ||||
* ascii set and box drawing chars. | * ascii set and box drawing chars. | ||||
*/ | */ | ||||
static struct whitelist c_list[] = { | static struct whitelist c_list[] = { | ||||
{ .c = 0, .len = 0 }, /* deault char */ | { .c = 0, .len = 0 }, /* deault char */ | ||||
{ .c = 0x20, .len = 0x5f }, | { .c = 0x20, .len = 0x5f }, | ||||
{ .c = 0x2500, .len = 0 }, /* single frame */ | { .c = 0x2500, .len = 0 }, /* single frame */ | ||||
{ .c = 0x2502, .len = 0 }, | { .c = 0x2502, .len = 0 }, | ||||
{ .c = 0x250c, .len = 0 }, | { .c = 0x250c, .len = 0 }, | ||||
{ .c = 0x2510, .len = 0 }, | { .c = 0x2510, .len = 0 }, | ||||
{ .c = 0x2514, .len = 0 }, | { .c = 0x2514, .len = 0 }, | ||||
{ .c = 0x2518, .len = 0 }, | { .c = 0x2518, .len = 0 }, | ||||
{ .c = 0x2550, .len = 1 }, /* double frame */ | { .c = 0x2550, .len = 1 },/* double frame */ | ||||
{ .c = 0x2554, .len = 0 }, | { .c = 0x2554, .len = 0 }, | ||||
{ .c = 0x2557, .len = 0 }, | { .c = 0x2557, .len = 0 }, | ||||
{ .c = 0x255a, .len = 0 }, | { .c = 0x255a, .len = 0 }, | ||||
{ .c = 0x255d, .len = 0 }, | { .c = 0x255d, .len = 0 }, | ||||
}; | }; | ||||
/* | /* | ||||
* Uncompressed source. For x86 we need cp437 so the vga text mode | * Uncompressed source. For x86 we need cp437 so the vga text mode | ||||
* can program font into the vga card. | * can program font into the vga card. | ||||
*/ | */ | ||||
static struct whitelist s_list[] = { | static struct whitelist s_list[] = { | ||||
{ .c = 0, .len = 0 }, /* deault char */ | { .c = 0, .len = 0 }, /* deault char */ | ||||
{ .c = 0x20, .len = 0x5f }, /* ascii set */ | { .c = 0x20, .len = 0x5f }, /* ascii set */ | ||||
{ .c = 0xA0, .len = 0x5f }, /* latin 1 */ | { .c = 0xA0, .len = 0x5f }, /* latin 1 */ | ||||
{ .c = 0x0192, .len = 0 }, | { .c = 0x0192, .len = 0 }, | ||||
{ .c = 0x0332, .len = 0 }, /* composing lower line */ | { .c = 0x0332, .len = 0 }, /* composing lower line */ | ||||
{ .c = 0x0393, .len = 0 }, | { .c = 0x0393, .len = 0 }, | ||||
{ .c = 0x0398, .len = 0 }, | { .c = 0x0398, .len = 0 }, | ||||
{ .c = 0x03A3, .len = 0 }, | { .c = 0x03A3, .len = 0 }, | ||||
{ .c = 0x03A6, .len = 0 }, | { .c = 0x03A6, .len = 0 }, | ||||
{ .c = 0x03A9, .len = 0 }, | { .c = 0x03A9, .len = 0 }, | ||||
{ .c = 0x03B1, .len = 1 }, | { .c = 0x03B1, .len = 1 }, | ||||
{ .c = 0x03B4, .len = 0 }, | { .c = 0x03B4, .len = 0 }, | ||||
{ .c = 0x03C0, .len = 0 }, | { .c = 0x03C0, .len = 0 }, | ||||
{ .c = 0x03C3, .len = 0 }, | { .c = 0x03C3, .len = 0 }, | ||||
{ .c = 0x03C4, .len = 0 }, | { .c = 0x03C4, .len = 0 }, | ||||
{ .c = 0x207F, .len = 0 }, | { .c = 0x207F, .len = 0 }, | ||||
{ .c = 0x20A7, .len = 0 }, | { .c = 0x20A7, .len = 0 }, | ||||
{ .c = 0x2205, .len = 0 }, | { .c = 0x2205, .len = 0 }, | ||||
{ .c = 0x220A, .len = 0 }, | { .c = 0x220A, .len = 0 }, | ||||
{ .c = 0x2219, .len = 1 }, | { .c = 0x2219, .len = 1 }, | ||||
{ .c = 0x221E, .len = 0 }, | { .c = 0x221E, .len = 0 }, | ||||
{ .c = 0x2229, .len = 0 }, | { .c = 0x2229, .len = 0 }, | ||||
{ .c = 0x2248, .len = 0 }, | { .c = 0x2248, .len = 0 }, | ||||
{ .c = 0x2261, .len = 0 }, | { .c = 0x2261, .len = 0 }, | ||||
{ .c = 0x2264, .len = 1 }, | { .c = 0x2264, .len = 1 }, | ||||
{ .c = 0x2310, .len = 0 }, | { .c = 0x2310, .len = 0 }, | ||||
{ .c = 0x2320, .len = 1 }, | { .c = 0x2320, .len = 1 }, | ||||
{ .c = 0x2500, .len = 0 }, | { .c = 0x2500, .len = 0 }, | ||||
{ .c = 0x2502, .len = 0 }, | { .c = 0x2502, .len = 0 }, | ||||
{ .c = 0x250C, .len = 0 }, | { .c = 0x250C, .len = 0 }, | ||||
{ .c = 0x2510, .len = 0 }, | { .c = 0x2510, .len = 0 }, | ||||
{ .c = 0x2514, .len = 0 }, | { .c = 0x2514, .len = 0 }, | ||||
{ .c = 0x2518, .len = 0 }, | { .c = 0x2518, .len = 0 }, | ||||
{ .c = 0x251C, .len = 0 }, | { .c = 0x251C, .len = 0 }, | ||||
{ .c = 0x2524, .len = 0 }, | { .c = 0x2524, .len = 0 }, | ||||
{ .c = 0x252C, .len = 0 }, | { .c = 0x252C, .len = 0 }, | ||||
{ .c = 0x2534, .len = 0 }, | { .c = 0x2534, .len = 0 }, | ||||
{ .c = 0x253C, .len = 0 }, | { .c = 0x253C, .len = 0 }, | ||||
{ .c = 0x2550, .len = 0x1c }, | { .c = 0x2550, .len = 0x1c }, | ||||
{ .c = 0x2580, .len = 0 }, | { .c = 0x2580, .len = 0 }, | ||||
{ .c = 0x2584, .len = 0 }, | { .c = 0x2584, .len = 0 }, | ||||
{ .c = 0x2588, .len = 0 }, | { .c = 0x2588, .len = 0 }, | ||||
{ .c = 0x258C, .len = 0 }, | { .c = 0x258C, .len = 0 }, | ||||
{ .c = 0x2590, .len = 3 }, | { .c = 0x2590, .len = 3 }, | ||||
{ .c = 0x25A0, .len = 0 }, | { .c = 0x25A0, .len = 0 }, | ||||
}; | }; | ||||
static bool filter = true; | static bool filter = true; | ||||
static enum output_format format = VT_FONT; | static enum output_format format = VT_FONT; | ||||
/* Type for write callback. */ | /* Type for write callback. */ | ||||
typedef size_t (*vt_write)(const void *, size_t, size_t, FILE *); | typedef size_t (*vt_write)(const void *, size_t, size_t, FILE *); | ||||
static uint8_t *uncompressed; | static uint8_t *uncompressed; | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
(void)fprintf(stderr, "usage: vtfontcvt " | (void)fprintf(stderr, "usage: vtfontcvt " | ||||
"[-n] [-f font|source|compressed-source] [-w width] " | "[-n] [-f font|source|compressed-source] [-w width] " | ||||
"[-h height]\n\t[-v] normal.bdf [bold.bdf] out.fnt\n"); | "[-h height]\n\t[-v] normal.bdf [bold.bdf] out.fnt\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
static void * | static void * | ||||
xmalloc(size_t size) | xmalloc(size_t size) | ||||
{ | { | ||||
void *m; | void *m; | ||||
if ((m = calloc(1, size)) == NULL) | if ((m = calloc(1, size)) == NULL) | ||||
errx(1, "memory allocation failure"); | errx(1, "memory allocation failure"); | ||||
return (m); | return (m); | ||||
} | } | ||||
static int | static int | ||||
add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) | add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) | ||||
{ | { | ||||
struct mapping *mp, *mp_temp; | struct mapping *mp, *mp_temp; | ||||
struct mapping_list *ml; | struct mapping_list *ml; | ||||
mapping_total++; | mapping_total++; | ||||
mp = xmalloc(sizeof *mp); | mp = xmalloc(sizeof *mp); | ||||
mp->m_char = c; | mp->m_char = c; | ||||
mp->m_glyph = gl; | mp->m_glyph = gl; | ||||
mp->m_length = 0; | mp->m_length = 0; | ||||
ml = &maps[map_idx]; | ml = &maps[map_idx]; | ||||
if (TAILQ_LAST(ml, mapping_list) == NULL || | if (TAILQ_LAST(ml, mapping_list) == NULL || | ||||
TAILQ_LAST(ml, mapping_list)->m_char < c) { | TAILQ_LAST(ml, mapping_list)->m_char < c) { | ||||
/* Common case: empty list or new char at end of list. */ | /* Common case: empty list or new char at end of list. */ | ||||
TAILQ_INSERT_TAIL(ml, mp, m_list); | TAILQ_INSERT_TAIL(ml, mp, m_list); | ||||
} else { | } else { | ||||
/* Find insertion point for char; cannot be at end. */ | /* Find insertion point for char; cannot be at end. */ | ||||
TAILQ_FOREACH(mp_temp, ml, m_list) { | TAILQ_FOREACH (mp_temp, ml, m_list) { | ||||
if (mp_temp->m_char >= c) { | if (mp_temp->m_char >= c) { | ||||
TAILQ_INSERT_BEFORE(mp_temp, mp, m_list); | TAILQ_INSERT_BEFORE(mp_temp, mp, m_list); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
Done Inline ActionsTAILQ_FOREACH is treated as a for loop here through: set FOR TAILQ_FOREACH should it be? domagoj.stolfa_gmail.com: `TAILQ_FOREACH` is treated as a for loop here through:
```
set FOR TAILQ_FOREACH
```
should… | |||||
} | } | ||||
map_count[map_idx]++; | map_count[map_idx]++; | ||||
mapping_unique++; | mapping_unique++; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
dedup_mapping(unsigned int map_idx) | dedup_mapping(unsigned int map_idx) | ||||
{ | { | ||||
struct mapping *mp_bold, *mp_normal, *mp_temp; | struct mapping *mp_bold, *mp_normal, *mp_temp; | ||||
unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; | unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; | ||||
assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RIGHT); | assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RIGHT); | ||||
mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); | mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); | ||||
TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { | TAILQ_FOREACH_SAFE (mp_bold, &maps[map_idx], m_list, mp_temp) { | ||||
while (mp_normal->m_char < mp_bold->m_char) | while (mp_normal->m_char < mp_bold->m_char) | ||||
mp_normal = TAILQ_NEXT(mp_normal, m_list); | mp_normal = TAILQ_NEXT(mp_normal, m_list); | ||||
if (mp_bold->m_char != mp_normal->m_char) | if (mp_bold->m_char != mp_normal->m_char) | ||||
errx(1, "Character %u not in normal font!", | errx(1, "Character %u not in normal font!", | ||||
mp_bold->m_char); | mp_bold->m_char); | ||||
if (mp_bold->m_glyph != mp_normal->m_glyph) | if (mp_bold->m_glyph != mp_normal->m_glyph) | ||||
continue; | continue; | ||||
/* No mapping is needed if it's equal to the normal mapping. */ | /* No mapping is needed if it's equal to the normal mapping. */ | ||||
TAILQ_REMOVE(&maps[map_idx], mp_bold, m_list); | TAILQ_REMOVE(&maps[map_idx], mp_bold, m_list); | ||||
free(mp_bold); | free(mp_bold); | ||||
mapping_dupe++; | mapping_dupe++; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct glyph * | static struct glyph * | ||||
add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) | add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) | ||||
{ | { | ||||
struct glyph *gl; | struct glyph *gl; | ||||
int hash; | int hash; | ||||
glyph_total++; | glyph_total++; | ||||
glyph_count[map_idx]++; | glyph_count[map_idx]++; | ||||
/* Return existing glyph if we have an identical one. */ | /* Return existing glyph if we have an identical one. */ | ||||
hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; | hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; | ||||
SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) { | SLIST_FOREACH (gl, &glyph_hash[hash], g_hash) { | ||||
if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { | if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { | ||||
glyph_dupe++; | glyph_dupe++; | ||||
return (gl); | return (gl); | ||||
} | } | ||||
} | } | ||||
/* Allocate new glyph. */ | /* Allocate new glyph. */ | ||||
gl = xmalloc(sizeof *gl); | gl = xmalloc(sizeof *gl); | ||||
gl->g_data = xmalloc(wbytes * height); | gl->g_data = xmalloc(wbytes * height); | ||||
memcpy(gl->g_data, bytes, wbytes * height); | memcpy(gl->g_data, bytes, wbytes * height); | ||||
if (fallback) | if (fallback) | ||||
TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list); | TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list); | ||||
else | else | ||||
TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list); | TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list); | ||||
SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); | SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); | ||||
glyph_unique++; | glyph_unique++; | ||||
if (glyph_unique > VFNT_MAXGLYPHS) | if (glyph_unique > VFNT_MAXGLYPHS) | ||||
errx(1, "too many glyphs (%u)", glyph_unique); | errx(1, "too many glyphs (%u)", glyph_unique); | ||||
return (gl); | return (gl); | ||||
} | } | ||||
static bool | static bool | ||||
check_whitelist(unsigned c) | check_whitelist(unsigned c) | ||||
{ | { | ||||
struct whitelist *w = NULL; | struct whitelist *w = NULL; | ||||
int i, n = 0; | int i, n = 0; | ||||
if (filter == false) | if (filter == false) | ||||
return (true); | return (true); | ||||
if (format == VT_C_SOURCE) { | if (format == VT_C_SOURCE) { | ||||
w = s_list; | w = s_list; | ||||
n = sizeof (s_list) / sizeof (s_list[0]); | n = sizeof(s_list) / sizeof(s_list[0]); | ||||
} | } | ||||
if (format == VT_C_COMPRESSED) { | if (format == VT_C_COMPRESSED) { | ||||
w = c_list; | w = c_list; | ||||
n = sizeof (c_list) / sizeof (c_list[0]); | n = sizeof(c_list) / sizeof(c_list[0]); | ||||
} | } | ||||
if (w == NULL) | if (w == NULL) | ||||
return (true); | return (true); | ||||
for (i = 0; i < n; i++) { | for (i = 0; i < n; i++) { | ||||
if (c >= w[i].c && c <= w[i].c + w[i].len) | if (c >= w[i].c && c <= w[i].c + w[i].len) | ||||
return (true); | return (true); | ||||
} | } | ||||
return (false); | return (false); | ||||
} | } | ||||
static int | static int | ||||
add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) | add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) | ||||
{ | { | ||||
struct glyph *gl; | struct glyph *gl; | ||||
/* Prevent adding two glyphs for 0xFFFD */ | /* Prevent adding two glyphs for 0xFFFD */ | ||||
if (curchar == 0xFFFD) { | if (curchar == 0xFFFD) { | ||||
if (map_idx < VFNT_MAP_BOLD) | if (map_idx < VFNT_MAP_BOLD) | ||||
gl = add_glyph(bytes, 0, 1); | gl = add_glyph(bytes, 0, 1); | ||||
} else if (filter == false || curchar >= 0x20) { | } else if (filter == false || curchar >= 0x20) { | ||||
gl = add_glyph(bytes, map_idx, 0); | gl = add_glyph(bytes, map_idx, 0); | ||||
if (add_mapping(gl, curchar, map_idx) != 0) | if (add_mapping(gl, curchar, map_idx) != 0) | ||||
return (1); | return (1); | ||||
if (bytes_r != NULL) { | if (bytes_r != NULL) { | ||||
gl = add_glyph(bytes_r, map_idx + 1, 0); | 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 (1); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Right-shift glyph row. | * Right-shift glyph row. | ||||
*/ | */ | ||||
static void | static void | ||||
rshift_row(uint8_t *buf, size_t len, size_t shift) | rshift_row(uint8_t *buf, size_t len, size_t shift) | ||||
{ | { | ||||
ssize_t i, off_byte = shift / 8; | ssize_t i, off_byte = shift / 8; | ||||
size_t off_bit = shift % 8; | size_t off_bit = shift % 8; | ||||
if (shift == 0) | if (shift == 0) | ||||
return; | return; | ||||
for (i = len - 1; i >= 0; i--) | for (i = len - 1; i >= 0; i--) | ||||
buf[i] = (i >= off_byte ? buf[i - off_byte] >> off_bit : 0) | | buf[i] = (i >= off_byte ? buf[i - off_byte] >> off_bit : 0) | | ||||
(i > off_byte ? buf[i - off_byte - 1] << (8 - off_bit) : 0); | (i > off_byte ? buf[i - off_byte - 1] << (8 - off_bit) : 0); | ||||
} | } | ||||
/* | /* | ||||
* Split double-width characters into left and right half. Single-width | * Split double-width characters into left and right half. Single-width | ||||
* characters in _left_ only. | * characters in _left_ only. | ||||
*/ | */ | ||||
static int | static int | ||||
split_row(uint8_t *left, uint8_t *right, uint8_t *line, size_t w) | split_row(uint8_t *left, uint8_t *right, uint8_t *line, size_t w) | ||||
{ | { | ||||
size_t s, i; | size_t s, i; | ||||
Show All 12 Lines | for (i = 0; i < wbytes; i++) { | ||||
t |= *(line + wbytes + i) >> s; | t |= *(line + wbytes + i) >> s; | ||||
*(right + i) = t; | *(right + i) = t; | ||||
} | } | ||||
*(right + wbytes - 1) &= 0xFF << s; | *(right + wbytes - 1) &= 0xFF << s; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
set_height(int h) | set_height(int h) | ||||
{ | { | ||||
if (h <= 0 || h > VFNT_MAXDIMENSION) | if (h <= 0 || h > VFNT_MAXDIMENSION) | ||||
errx(1, "invalid height %d", h); | errx(1, "invalid height %d", h); | ||||
height = h; | height = h; | ||||
} | } | ||||
static void | static void | ||||
set_width(int w) | set_width(int w) | ||||
{ | { | ||||
if (w <= 0 || w > VFNT_MAXDIMENSION) | if (w <= 0 || w > VFNT_MAXDIMENSION) | ||||
errx(1, "invalid width %d", w); | errx(1, "invalid width %d", w); | ||||
width = w; | width = w; | ||||
wbytes = howmany(width, 8); | wbytes = howmany(width, 8); | ||||
} | } | ||||
static int | static int | ||||
parse_bdf(FILE *fp, unsigned int map_idx) | parse_bdf(FILE *fp, unsigned int map_idx) | ||||
{ | { | ||||
char *ln, *p; | char *ln, *p; | ||||
size_t length; | size_t length; | ||||
uint8_t *line, *bytes, *bytes_r; | uint8_t *line, *bytes, *bytes_r; | ||||
unsigned int curchar = 0, i, j, linenum = 0, bbwbytes; | unsigned int curchar = 0, i, j, linenum = 0, bbwbytes; | ||||
int bbw, bbh, bbox, bboy; /* Glyph bounding box. */ | int bbw, bbh, bbox, bboy; /* Glyph bounding box. */ | ||||
int fbbw = 0, fbbh, fbbox, fbboy; /* Font bounding box. */ | int fbbw = 0, fbbh, fbbox, fbboy; /* Font bounding box. */ | ||||
int dwidth = 0, dwy = 0; | int dwidth = 0, dwy = 0; | ||||
int rv = -1; | int rv = -1; | ||||
char spc = '\0'; | char spc = '\0'; | ||||
/* | /* | ||||
* Step 1: Parse FONT logical font descriptor and FONTBOUNDINGBOX | * Step 1: Parse FONT logical font descriptor and FONTBOUNDINGBOX | ||||
* bounding box. | * bounding box. | ||||
*/ | */ | ||||
Show All 31 Lines | parse_bdf(FILE *fp, unsigned int map_idx) | ||||
while ((ln = fgetln(fp, &length)) != NULL) { | while ((ln = fgetln(fp, &length)) != NULL) { | ||||
linenum++; | linenum++; | ||||
ln[length - 1] = '\0'; | ln[length - 1] = '\0'; | ||||
if (strncmp(ln, "DWIDTH ", 7) == 0) { | if (strncmp(ln, "DWIDTH ", 7) == 0) { | ||||
if (sscanf(ln + 7, "%d %d", &dwidth, &dwy) != 2) | if (sscanf(ln + 7, "%d %d", &dwidth, &dwy) != 2) | ||||
errx(1, "invalid DWIDTH at line %u", linenum); | errx(1, "invalid DWIDTH at line %u", linenum); | ||||
if (dwy != 0 || (dwidth != fbbw && dwidth * 2 != fbbw)) | if (dwy != 0 || (dwidth != fbbw && dwidth * 2 != fbbw)) | ||||
errx(1, "bitmap with unsupported DWIDTH %d %d at line %u", | errx(1, | ||||
"bitmap with unsupported DWIDTH %d %d at line %u", | |||||
dwidth, dwy, linenum); | dwidth, dwy, linenum); | ||||
if (dwidth < fbbw) | if (dwidth < fbbw) | ||||
set_width(dwidth); | set_width(dwidth); | ||||
} | } | ||||
} | } | ||||
/* Step 3: Restart at the beginning of the file and read glyph data. */ | /* Step 3: Restart at the beginning of the file and read glyph data. */ | ||||
dwidth = bbw = bbh = 0; | dwidth = bbw = bbh = 0; | ||||
rewind(fp); | rewind(fp); | ||||
linenum = 0; | linenum = 0; | ||||
bbwbytes = 0; /* GCC 4.2.1 "may be used uninitialized" workaround. */ | bbwbytes = 0; /* GCC 4.2.1 "may be used uninitialized" workaround. */ | ||||
bytes = xmalloc(wbytes * height); | bytes = xmalloc(wbytes * height); | ||||
bytes_r = xmalloc(wbytes * height); | bytes_r = xmalloc(wbytes * height); | ||||
line = xmalloc(wbytes * 2); | line = xmalloc(wbytes * 2); | ||||
while ((ln = fgetln(fp, &length)) != NULL) { | while ((ln = fgetln(fp, &length)) != NULL) { | ||||
linenum++; | linenum++; | ||||
ln[length - 1] = '\0'; | ln[length - 1] = '\0'; | ||||
if (strncmp(ln, "ENCODING ", 9) == 0) { | if (strncmp(ln, "ENCODING ", 9) == 0) { | ||||
curchar = atoi(ln + 9); | curchar = atoi(ln + 9); | ||||
} else if (strncmp(ln, "DWIDTH ", 7) == 0) { | } else if (strncmp(ln, "DWIDTH ", 7) == 0) { | ||||
dwidth = atoi(ln + 7); | dwidth = atoi(ln + 7); | ||||
} else if (strncmp(ln, "BBX ", 4) == 0) { | } else if (strncmp(ln, "BBX ", 4) == 0) { | ||||
if (sscanf(ln + 4, "%d %d %d %d", &bbw, &bbh, &bbox, | if (sscanf(ln + 4, "%d %d %d %d", &bbw, &bbh, &bbox, | ||||
&bboy) != 4) | &bboy) != 4) | ||||
errx(1, "invalid BBX at line %u", linenum); | errx(1, "invalid BBX at line %u", linenum); | ||||
if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh || | if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh || | ||||
bbox < fbbox || bboy < fbboy || | bbox < fbbox || bboy < fbboy || | ||||
bbh + bboy > fbbh + fbboy) | bbh + bboy > fbbh + fbboy) | ||||
errx(1, "broken bitmap with BBX %d %d %d %d at line %u", | errx(1, | ||||
"broken bitmap with BBX %d %d %d %d at line %u", | |||||
bbw, bbh, bbox, bboy, linenum); | bbw, bbh, bbox, bboy, linenum); | ||||
bbwbytes = howmany(bbw, 8); | bbwbytes = howmany(bbw, 8); | ||||
} else if (strncmp(ln, "BITMAP", 6) == 0 && | } else if (strncmp(ln, "BITMAP", 6) == 0 && | ||||
(ln[6] == ' ' || ln[6] == '\0')) { | (ln[6] == ' ' || ln[6] == '\0')) { | ||||
if (dwidth == 0 || bbw == 0 || bbh == 0) | if (dwidth == 0 || bbw == 0 || bbh == 0) | ||||
errx(1, "broken char header at line %u!", | errx(1, "broken char header at line %u!", | ||||
linenum); | linenum); | ||||
memset(bytes, 0, wbytes * height); | memset(bytes, 0, wbytes * height); | ||||
Show All 22 Lines | if (strncmp(ln, "ENCODING ", 9) == 0) { | ||||
if (sscanf(ln + j * 2, "%2x", &val) == | if (sscanf(ln + j * 2, "%2x", &val) == | ||||
0) | 0) | ||||
break; | break; | ||||
*(line + j) = (uint8_t)val; | *(line + j) = (uint8_t)val; | ||||
} | } | ||||
rshift_row(line, wbytes * 2, bbox - fbbox); | rshift_row(line, wbytes * 2, bbox - fbbox); | ||||
rv = split_row(bytes + i * wbytes, | rv = split_row(bytes + i * wbytes, | ||||
bytes_r + i * wbytes, line, dwidth); | bytes_r + i * wbytes, line, dwidth); | ||||
if (rv != 0) | if (rv != 0) | ||||
goto out; | goto out; | ||||
} | } | ||||
if (check_whitelist(curchar) == true) { | if (check_whitelist(curchar) == true) { | ||||
rv = add_char(curchar, map_idx, bytes, | rv = add_char(curchar, map_idx, bytes, | ||||
dwidth > (int)width ? bytes_r : NULL); | dwidth > (int)width ? bytes_r : NULL); | ||||
if (rv != 0) | if (rv != 0) | ||||
goto out; | goto out; | ||||
} | } | ||||
dwidth = bbw = bbh = 0; | dwidth = bbw = bbh = 0; | ||||
} | } | ||||
} | } | ||||
out: | out: | ||||
free(bytes); | free(bytes); | ||||
free(bytes_r); | free(bytes_r); | ||||
free(line); | free(line); | ||||
return (rv); | return (rv); | ||||
} | } | ||||
static int | static int | ||||
parse_hex(FILE *fp, unsigned int map_idx) | parse_hex(FILE *fp, unsigned int map_idx) | ||||
{ | { | ||||
char *ln, *p; | char *ln, *p; | ||||
size_t length; | size_t length; | ||||
uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; | uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL; | ||||
unsigned curchar = 0, gwidth, gwbytes, i, j, chars_per_row; | unsigned curchar = 0, gwidth, gwbytes, i, j, chars_per_row; | ||||
int rv = 0; | int rv = 0; | ||||
Done Inline ActionsThis is wrong domagoj.stolfa_gmail.com: This is wrong | |||||
while ((ln = fgetln(fp, &length)) != NULL) { | while ((ln = fgetln(fp, &length)) != NULL) { | ||||
ln[length - 1] = '\0'; | ln[length - 1] = '\0'; | ||||
if (strncmp(ln, "# Height: ", 10) == 0) { | if (strncmp(ln, "# Height: ", 10) == 0) { | ||||
if (bytes != NULL) | if (bytes != NULL) | ||||
errx(1, "malformed input: Height tag after font data"); | errx(1, | ||||
"malformed input: Height tag after font data"); | |||||
set_height(atoi(ln + 10)); | set_height(atoi(ln + 10)); | ||||
Done Inline ActionsSame as line 573 domagoj.stolfa_gmail.com: Same as line 573 | |||||
} else if (strncmp(ln, "# Width: ", 9) == 0) { | } else if (strncmp(ln, "# Width: ", 9) == 0) { | ||||
if (bytes != NULL) | 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)); | set_width(atoi(ln + 9)); | ||||
} else if (sscanf(ln, "%6x:", &curchar)) { | } else if (sscanf(ln, "%6x:", &curchar)) { | ||||
if (bytes == NULL) { | if (bytes == NULL) { | ||||
bytes = xmalloc(wbytes * height); | bytes = xmalloc(wbytes * height); | ||||
bytes_r = xmalloc(wbytes * height); | bytes_r = xmalloc(wbytes * height); | ||||
line = xmalloc(wbytes * 2); | line = xmalloc(wbytes * 2); | ||||
} | } | ||||
/* ln is guaranteed to have a colon here. */ | /* ln is guaranteed to have a colon here. */ | ||||
Show All 13 Lines | if (strncmp(ln, "# Height: ", 10) == 0) { | ||||
for (i = 0; i < height; i++) { | for (i = 0; i < height; i++) { | ||||
for (j = 0; j < gwbytes; j++) { | for (j = 0; j < gwbytes; j++) { | ||||
unsigned int val; | unsigned int val; | ||||
if (sscanf(p + j * 2, "%2x", &val) == 0) | if (sscanf(p + j * 2, "%2x", &val) == 0) | ||||
break; | break; | ||||
*(line + j) = (uint8_t)val; | *(line + j) = (uint8_t)val; | ||||
} | } | ||||
rv = split_row(bytes + i * wbytes, | rv = split_row(bytes + i * wbytes, | ||||
bytes_r + i * wbytes, line, gwidth); | bytes_r + i * wbytes, line, gwidth); | ||||
if (rv != 0) | if (rv != 0) | ||||
goto out; | goto out; | ||||
p += gwbytes * 2; | p += gwbytes * 2; | ||||
} | } | ||||
if (check_whitelist(curchar) == true) { | if (check_whitelist(curchar) == true) { | ||||
rv = add_char(curchar, map_idx, bytes, | rv = add_char(curchar, map_idx, bytes, | ||||
gwidth != width ? bytes_r : NULL); | gwidth != width ? bytes_r : NULL); | ||||
if (rv != 0) | if (rv != 0) | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
out: | out: | ||||
free(bytes); | free(bytes); | ||||
free(bytes_r); | free(bytes_r); | ||||
free(line); | free(line); | ||||
return (rv); | return (rv); | ||||
} | } | ||||
static int | static int | ||||
parse_file(const char *filename, unsigned int map_idx) | parse_file(const char *filename, unsigned int map_idx) | ||||
{ | { | ||||
FILE *fp; | FILE *fp; | ||||
size_t len; | size_t len; | ||||
int rv; | int rv; | ||||
fp = fopen(filename, "r"); | fp = fopen(filename, "r"); | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
perror(filename); | perror(filename); | ||||
return (1); | return (1); | ||||
} | } | ||||
len = strlen(filename); | len = strlen(filename); | ||||
if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0) | if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0) | ||||
rv = parse_hex(fp, map_idx); | rv = parse_hex(fp, map_idx); | ||||
else | else | ||||
rv = parse_bdf(fp, map_idx); | rv = parse_bdf(fp, map_idx); | ||||
fclose(fp); | fclose(fp); | ||||
return (rv); | return (rv); | ||||
} | } | ||||
static void | static void | ||||
number_glyphs(void) | number_glyphs(void) | ||||
{ | { | ||||
struct glyph *gl; | struct glyph *gl; | ||||
unsigned int i, idx = 0; | unsigned int i, idx = 0; | ||||
for (i = 0; i < VFNT_MAPS; i++) | for (i = 0; i < VFNT_MAPS; i++) | ||||
TAILQ_FOREACH(gl, &glyphs[i], g_list) | TAILQ_FOREACH (gl, &glyphs[i], g_list) | ||||
gl->g_index = idx++; | gl->g_index = idx++; | ||||
} | } | ||||
/* Note we only deal with byte stream here. */ | /* Note we only deal with byte stream here. */ | ||||
static size_t | static size_t | ||||
write_glyph_source(const void *ptr, size_t size, size_t nitems, FILE *stream) | write_glyph_source(const void *ptr, size_t size, size_t nitems, FILE *stream) | ||||
{ | { | ||||
const uint8_t *data = ptr; | const uint8_t *data = ptr; | ||||
size_t i; | size_t i; | ||||
size *= nitems; | size *= nitems; | ||||
for (i = 0; i < size; i++) { | for (i = 0; i < size; i++) { | ||||
if ((i % wbytes) == 0) { | if ((i % wbytes) == 0) { | ||||
if (fprintf(stream, "\n") < 0) | if (fprintf(stream, "\n") < 0) | ||||
return (0); | return (0); | ||||
} | } | ||||
if (fprintf(stream, "0x%02x, ", data[i]) < 0) | if (fprintf(stream, "0x%02x, ", data[i]) < 0) | ||||
return (0); | return (0); | ||||
} | } | ||||
if (fprintf(stream, "\n") < 0) | if (fprintf(stream, "\n") < 0) | ||||
nitems = 0; | nitems = 0; | ||||
return (nitems); | return (nitems); | ||||
} | } | ||||
/* Write to buffer */ | /* Write to buffer */ | ||||
static size_t | static size_t | ||||
write_glyph_buf(const void *ptr, size_t size, size_t nitems, | write_glyph_buf(const void *ptr, size_t size, size_t nitems, | ||||
FILE *stream __unused) | FILE *stream __unused) | ||||
{ | { | ||||
static size_t index = 0; | static size_t index = 0; | ||||
size *= nitems; | size *= nitems; | ||||
(void) memmove(uncompressed + index, ptr, size); | (void)memmove(uncompressed + index, ptr, size); | ||||
index += size; | index += size; | ||||
return (nitems); | return (nitems); | ||||
} | } | ||||
static int | static int | ||||
write_glyphs(FILE *fp, vt_write cb) | write_glyphs(FILE *fp, vt_write cb) | ||||
{ | { | ||||
struct glyph *gl; | struct glyph *gl; | ||||
unsigned int i; | unsigned int i; | ||||
for (i = 0; i < VFNT_MAPS; i++) { | for (i = 0; i < VFNT_MAPS; i++) { | ||||
TAILQ_FOREACH(gl, &glyphs[i], g_list) | TAILQ_FOREACH (gl, &glyphs[i], g_list) | ||||
if (cb(gl->g_data, wbytes * height, 1, fp) != 1) | if (cb(gl->g_data, wbytes * height, 1, fp) != 1) | ||||
return (1); | return (1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
fold_mappings(unsigned int map_idx) | fold_mappings(unsigned int map_idx) | ||||
{ | { | ||||
struct mapping_list *ml = &maps[map_idx]; | struct mapping_list *ml = &maps[map_idx]; | ||||
struct mapping *mn, *mp, *mbase; | struct mapping *mn, *mp, *mbase; | ||||
mp = mbase = TAILQ_FIRST(ml); | mp = mbase = TAILQ_FIRST(ml); | ||||
for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) { | for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) { | ||||
mn = TAILQ_NEXT(mp, m_list); | mn = TAILQ_NEXT(mp, m_list); | ||||
if (mn != NULL && mn->m_char == mp->m_char + 1 && | if (mn != NULL && mn->m_char == mp->m_char + 1 && | ||||
mn->m_glyph->g_index == mp->m_glyph->g_index + 1) | mn->m_glyph->g_index == mp->m_glyph->g_index + 1) | ||||
continue; | continue; | ||||
mbase->m_length = mp->m_char - mbase->m_char + 1; | mbase->m_length = mp->m_char - mbase->m_char + 1; | ||||
mbase = mp = mn; | mbase = mp = mn; | ||||
map_folded_count[map_idx]++; | map_folded_count[map_idx]++; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
write_mappings(FILE *fp, unsigned int map_idx) | write_mappings(FILE *fp, unsigned int map_idx) | ||||
{ | { | ||||
struct mapping_list *ml = &maps[map_idx]; | struct mapping_list *ml = &maps[map_idx]; | ||||
struct mapping *mp; | struct mapping *mp; | ||||
vfnt_map_t fm; | vfnt_map_t fm; | ||||
unsigned int i = 0, j = 0; | unsigned int i = 0, j = 0; | ||||
TAILQ_FOREACH(mp, ml, m_list) { | TAILQ_FOREACH (mp, ml, m_list) { | ||||
j++; | j++; | ||||
if (mp->m_length > 0) { | if (mp->m_length > 0) { | ||||
i += mp->m_length; | i += mp->m_length; | ||||
fm.vfm_src = htobe32(mp->m_char); | fm.vfm_src = htobe32(mp->m_char); | ||||
fm.vfm_dst = htobe16(mp->m_glyph->g_index); | fm.vfm_dst = htobe16(mp->m_glyph->g_index); | ||||
fm.vfm_len = htobe16(mp->m_length - 1); | fm.vfm_len = htobe16(mp->m_length - 1); | ||||
if (fwrite(&fm, sizeof fm, 1, fp) != 1) | if (fwrite(&fm, sizeof fm, 1, fp) != 1) | ||||
return (1); | return (1); | ||||
} | } | ||||
} | } | ||||
assert(i == j); | assert(i == j); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
write_source_mappings(FILE *fp, unsigned int map_idx) | write_source_mappings(FILE *fp, unsigned int map_idx) | ||||
{ | { | ||||
struct mapping_list *ml = &maps[map_idx]; | struct mapping_list *ml = &maps[map_idx]; | ||||
struct mapping *mp; | struct mapping *mp; | ||||
unsigned int i = 0, j = 0; | unsigned int i = 0, j = 0; | ||||
TAILQ_FOREACH(mp, ml, m_list) { | TAILQ_FOREACH (mp, ml, m_list) { | ||||
j++; | j++; | ||||
if (mp->m_length > 0) { | if (mp->m_length > 0) { | ||||
i += mp->m_length; | i += mp->m_length; | ||||
if (fprintf(fp, "\t{ 0x%08x, 0x%04x, 0x%04x },\n", | if (fprintf(fp, "\t{ 0x%08x, 0x%04x, 0x%04x },\n", | ||||
mp->m_char, mp->m_glyph->g_index, | mp->m_char, mp->m_glyph->g_index, | ||||
mp->m_length - 1) < 0) | mp->m_length - 1) < 0) | ||||
return (1); | return (1); | ||||
} | } | ||||
} | } | ||||
assert(i == j); | assert(i == j); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
write_fnt(const char *filename) | write_fnt(const char *filename) | ||||
{ | { | ||||
FILE *fp; | FILE *fp; | ||||
struct font_header fh = { | struct font_header fh = { | ||||
.fh_magic = FONT_HEADER_MAGIC, | .fh_magic = FONT_HEADER_MAGIC, | ||||
}; | }; | ||||
fp = fopen(filename, "wb"); | fp = fopen(filename, "wb"); | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
perror(filename); | perror(filename); | ||||
return (1); | return (1); | ||||
} | } | ||||
Show All 19 Lines | if (write_glyphs(fp, &fwrite) != 0 || | ||||
fclose(fp); | fclose(fp); | ||||
return (1); | return (1); | ||||
} | } | ||||
fclose(fp); | fclose(fp); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
write_fnt_source(bool lz4, const char *filename) | write_fnt_source(bool lz4, const char *filename) | ||||
{ | { | ||||
FILE *fp; | FILE *fp; | ||||
int rv = 1; | int rv = 1; | ||||
size_t uncompressed_size = wbytes * height * glyph_unique; | size_t uncompressed_size = wbytes * height * glyph_unique; | ||||
size_t compressed_size = uncompressed_size; | size_t compressed_size = uncompressed_size; | ||||
uint8_t *compressed = NULL; | uint8_t *compressed = NULL; | ||||
Show All 21 Lines | write_fnt_source(bool lz4, const char *filename) | ||||
/* Write font bytes. */ | /* Write font bytes. */ | ||||
if (fprintf(fp, "static uint8_t FONTDATA_%ux%u[] = {\n", | if (fprintf(fp, "static uint8_t FONTDATA_%ux%u[] = {\n", | ||||
width, height) < 0) | width, height) < 0) | ||||
goto done; | goto done; | ||||
if (lz4 == true) { | if (lz4 == true) { | ||||
if (write_glyphs(fp, &write_glyph_buf) != 0) | if (write_glyphs(fp, &write_glyph_buf) != 0) | ||||
goto done; | goto done; | ||||
compressed_size = lz4_compress(uncompressed, compressed, | compressed_size = lz4_compress(uncompressed, compressed, | ||||
uncompressed_size, compressed_size, 0); | uncompressed_size, compressed_size, 0); | ||||
if (write_glyph_source(compressed, compressed_size, 1, fp) != 1) | if (write_glyph_source(compressed, compressed_size, 1, fp) != 1) | ||||
goto done; | goto done; | ||||
free(uncompressed); | free(uncompressed); | ||||
free(compressed); | free(compressed); | ||||
} else { | } else { | ||||
if (write_glyphs(fp, &write_glyph_source) != 0) | if (write_glyphs(fp, &write_glyph_source) != 0) | ||||
goto done; | goto done; | ||||
} | } | ||||
if (fprintf(fp, "};\n\n") < 0) | if (fprintf(fp, "};\n\n") < 0) | ||||
goto done; | goto done; | ||||
/* Write font maps. */ | /* Write font maps. */ | ||||
if (!TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL])) { | if (!TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL])) { | ||||
if (fprintf(fp, "static vfnt_map_t " | if (fprintf(fp, "static vfnt_map_t " | ||||
"FONTMAP_NORMAL_%ux%u[] = {\n", width, height) < 0) | "FONTMAP_NORMAL_%ux%u[] = {\n", width, height) < 0) | ||||
goto done; | goto done; | ||||
if (write_source_mappings(fp, VFNT_MAP_NORMAL) != 0) | if (write_source_mappings(fp, VFNT_MAP_NORMAL) != 0) | ||||
goto done; | goto done; | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | write_fnt_source(bool lz4, const char *filename) | ||||
rv = 0; | rv = 0; | ||||
done: | done: | ||||
if (rv != 0) | if (rv != 0) | ||||
perror(filename); | perror(filename); | ||||
fclose(fp); | fclose(fp); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
print_font_info(void) | print_font_info(void) | ||||
{ | { | ||||
printf( | printf( | ||||
"Statistics:\n" | "Statistics:\n" | ||||
"- width: %6u\n" | "- width: %6u\n" | ||||
"- height: %6u\n" | "- height: %6u\n" | ||||
"- glyph_total: %6u\n" | "- glyph_total: %6u\n" | ||||
"- glyph_normal: %6u\n" | "- glyph_normal: %6u\n" | ||||
"- glyph_normal_right: %6u\n" | "- glyph_normal_right: %6u\n" | ||||
"- glyph_bold: %6u\n" | "- glyph_bold: %6u\n" | ||||
"- glyph_bold_right: %6u\n" | "- glyph_bold_right: %6u\n" | ||||
"- glyph_unique: %6u\n" | "- glyph_unique: %6u\n" | ||||
"- glyph_dupe: %6u\n" | "- glyph_dupe: %6u\n" | ||||
"- mapping_total: %6u\n" | "- mapping_total: %6u\n" | ||||
"- mapping_normal: %6u\n" | "- mapping_normal: %6u\n" | ||||
"- mapping_normal_folded: %6u\n" | "- mapping_normal_folded: %6u\n" | ||||
"- mapping_normal_right: %6u\n" | "- mapping_normal_right: %6u\n" | ||||
"- mapping_normal_right_folded: %6u\n" | "- mapping_normal_right_folded: %6u\n" | ||||
"- mapping_bold: %6u\n" | "- mapping_bold: %6u\n" | ||||
"- mapping_bold_folded: %6u\n" | "- mapping_bold_folded: %6u\n" | ||||
"- mapping_bold_right: %6u\n" | "- mapping_bold_right: %6u\n" | ||||
"- mapping_bold_right_folded: %6u\n" | "- mapping_bold_right_folded: %6u\n" | ||||
"- mapping_unique: %6u\n" | "- mapping_unique: %6u\n" | ||||
"- mapping_dupe: %6u\n", | "- mapping_dupe: %6u\n", | ||||
width, height, | width, height, | ||||
glyph_total, | glyph_total, | ||||
glyph_count[0], | glyph_count[0], | ||||
glyph_count[1], | glyph_count[1], | ||||
glyph_count[2], | glyph_count[2], | ||||
glyph_count[3], | glyph_count[3], | ||||
glyph_unique, glyph_dupe, | glyph_unique, glyph_dupe, | ||||
mapping_total, | mapping_total, | ||||
map_count[0], map_folded_count[0], | map_count[0], map_folded_count[0], | ||||
map_count[1], map_folded_count[1], | map_count[1], map_folded_count[1], | ||||
map_count[2], map_folded_count[2], | map_count[2], map_folded_count[2], | ||||
map_count[3], map_folded_count[3], | map_count[3], map_folded_count[3], | ||||
mapping_unique, mapping_dupe); | mapping_unique, mapping_dupe); | ||||
} | } | ||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
int ch, verbose = 0, rv = 0; | int ch, verbose = 0, rv = 0; | ||||
char *outfile = NULL; | char *outfile = NULL; | ||||
assert(sizeof(struct font_header) == 32); | assert(sizeof(struct font_header) == 32); | ||||
assert(sizeof(vfnt_map_t) == 8); | assert(sizeof(vfnt_map_t) == 8); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (outfile == NULL) { | ||||
argc--; | argc--; | ||||
} | } | ||||
set_width(width); | set_width(width); | ||||
set_height(height); | set_height(height); | ||||
if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) | if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) | ||||
return (1); | return (1); | ||||
argc--; | argc--; | ||||
argv++; | argv++; | ||||
if (argc == 1) { | if (argc == 1) { | ||||
if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) | if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) | ||||
Done Inline ActionsThis doesn't look right. domagoj.stolfa_gmail.com: This doesn't look right. | |||||
return (1); | return (1); | ||||
argc--; | argc--; | ||||
argv++; | argv++; | ||||
} | } | ||||
number_glyphs(); | number_glyphs(); | ||||
dedup_mapping(VFNT_MAP_BOLD); | dedup_mapping(VFNT_MAP_BOLD); | ||||
dedup_mapping(VFNT_MAP_BOLD_RIGHT); | dedup_mapping(VFNT_MAP_BOLD_RIGHT); | ||||
fold_mappings(0); | fold_mappings(0); | ||||
fold_mappings(1); | fold_mappings(1); | ||||
Show All 20 Lines |
This whole struct is not great.