rewrite mkfont_bdf
This commit is contained in:
parent
46847f4cc8
commit
4489a65a3e
5 changed files with 360 additions and 284 deletions
175
tools/bdf.h
175
tools/bdf.h
|
@ -2,52 +2,37 @@ int pre_match(const char *buf, const char *str) {
|
|||
return !strncmp(buf, str, strlen(str));
|
||||
}
|
||||
|
||||
void print_bitmap(uint32_t *bitmap)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < MAX_HEIGHT; i++) {
|
||||
for (j = 1; j <= sizeof(uint32_t) * BITS_PER_BYTE; j++) {
|
||||
if (bitmap[i] & (1 << (sizeof(uint32_t) * BITS_PER_BYTE - j)))
|
||||
fprintf(stderr, "@");
|
||||
else
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
int bit2byte(int bits)
|
||||
{
|
||||
return (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
|
||||
}
|
||||
|
||||
void shift_glyph(struct bdf_t *bdf, struct bdf_glyph_t *glyph)
|
||||
void shift_glyph(struct bdf_header_t *bdf_header, struct bdf_char_t *bdf_char)
|
||||
{
|
||||
int i, byte, shift;
|
||||
uint32_t tmp;
|
||||
bitmap_width_t bitmap;
|
||||
|
||||
for (i = 0; i < glyph->bbh; i++) {
|
||||
tmp = glyph->bitmap[i];
|
||||
byte = bit2byte(glyph->bbw);
|
||||
tmp <<= (bit2byte(glyph->dwidth) - byte) * BITS_PER_BYTE;
|
||||
if (glyph->bbx >= 0)
|
||||
tmp >>= glyph->bbx;
|
||||
for (i = 0; i < bdf_char->bbh; i++) {
|
||||
bitmap = bdf_char->bitmap[i];
|
||||
byte = bit2byte(bdf_char->bbw);
|
||||
bitmap <<= (bit2byte(bdf_char->dwidth) - byte) * BITS_PER_BYTE;
|
||||
if (bdf_char->bbx >= 0)
|
||||
bitmap >>= bdf_char->bbx;
|
||||
else {
|
||||
fprintf(stderr, "maybe overlapping (glpyh:%X bbx:%d)\n", glyph->encoding, glyph->bbx);
|
||||
tmp <<= abs(glyph->bbx);
|
||||
logging(ERROR, "maybe overlapping (glpyh:%X bbx:%d)\n", bdf_char->encoding, bdf_char->bbx);
|
||||
bitmap <<= abs(bdf_char->bbx);
|
||||
}
|
||||
glyph->bitmap[i] = tmp;
|
||||
bdf_char->bitmap[i] = bitmap;
|
||||
}
|
||||
|
||||
shift = bdf->ascent - (glyph->bbh + glyph->bby);
|
||||
shift = bdf_header->ascent - (bdf_char->bbh + bdf_char->bby);
|
||||
if (shift >= 0) {
|
||||
memmove(glyph->bitmap + shift, glyph->bitmap, sizeof(uint32_t) * glyph->bbh);
|
||||
memset(glyph->bitmap, 0, sizeof(uint32_t) * shift);
|
||||
memmove(bdf_char->bitmap + shift, bdf_char->bitmap, sizeof(bitmap_width_t) * bdf_char->bbh);
|
||||
memset(bdf_char->bitmap, 0, sizeof(bitmap_width_t) * shift);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "maybe overlapping (glpyh:%X vertical shift:%d)\n", glyph->encoding, shift);
|
||||
memmove(glyph->bitmap, glyph->bitmap + abs(shift), sizeof(uint32_t) * glyph->bbh);
|
||||
logging(ERROR, "maybe overlapping (glpyh:%X vertical shift:%d)\n", bdf_char->encoding, shift);
|
||||
memmove(bdf_char->bitmap, bdf_char->bitmap + abs(shift), sizeof(bitmap_width_t) * bdf_char->bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,60 +59,66 @@ void load_table(char *path, enum encode_t encode)
|
|||
if ((cp = strchr(buf, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
sscanf(buf, "%X %X", &from, &to);
|
||||
sscanf(buf, "%X %X", (unsigned int *) &from, (unsigned int *) &to);
|
||||
convert_table[from] = to;
|
||||
}
|
||||
}
|
||||
|
||||
int read_header(char *buf, struct bdf_t *bdf)
|
||||
int read_header(char *buf, struct bdf_header_t *bdf_header)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (pre_match(buf, "FONTBOUNDINGBOX "))
|
||||
sscanf(buf + strlen("FONTBOUNDINGBOX "), "%d %d %d %d",
|
||||
&bdf->bbw, &bdf->bbh, &bdf->bbx, &bdf->bby);
|
||||
&bdf_header->bbw, &bdf_header->bbh, &bdf_header->bbx, &bdf_header->bby);
|
||||
else if (pre_match(buf, "FONT_ASCENT "))
|
||||
bdf->ascent = atoi(buf + strlen("FONT_ASCENT "));
|
||||
bdf_header->ascent = atoi(buf + strlen("FONT_ASCENT "));
|
||||
else if (pre_match(buf, "FONT_DESCENT "))
|
||||
bdf->descent = atoi(buf + strlen("FONT_DESCENT "));
|
||||
bdf_header->descent = atoi(buf + strlen("FONT_DESCENT "));
|
||||
else if (pre_match(buf, "DEFAULT_CHAR "))
|
||||
bdf->default_char = atoi(buf + strlen("DEFAULT_CHAR "));
|
||||
bdf_header->default_char = atoi(buf + strlen("DEFAULT_CHAR "));
|
||||
else if (pre_match(buf, "PIXEL_SIZE "))
|
||||
bdf->pixel_size = atoi(buf + strlen("PIXEL_SIZE "));
|
||||
bdf_header->pixel_size = atoi(buf + strlen("PIXEL_SIZE "));
|
||||
else if (pre_match(buf, "CHARSET_REGISTRY ")) {
|
||||
strncpy(bdf->charset, buf + strlen("CHARSET_REGISTRY "), BUFSIZE - 1);
|
||||
fprintf(stderr, "%s\n", bdf->charset);
|
||||
for (cp = bdf->charset; *cp != '\0'; cp++)
|
||||
*cp = toupper(*cp);
|
||||
strncpy(bdf_header->charset, buf + strlen("CHARSET_REGISTRY "), BUFSIZE - 1);
|
||||
logging(DEBUG, "%s\n", bdf_header->charset);
|
||||
|
||||
if (strstr(bdf->charset, "X68000") != NULL || strstr(bdf->charset, "x68000") != NULL)
|
||||
for (cp = bdf_header->charset; *cp != '\0'; cp++)
|
||||
*cp = (char) toupper((int) *cp);
|
||||
|
||||
if (strstr(bdf_header->charset, "X68000") != NULL
|
||||
|| strstr(bdf_header->charset, "x68000") != NULL)
|
||||
load_table("./table/X68000", X68000);
|
||||
else if (strstr(bdf->charset, "JISX0201") != NULL || strstr(bdf->charset, "jisx0201") != NULL)
|
||||
else if (strstr(bdf_header->charset, "JISX0201") != NULL
|
||||
|| strstr(bdf_header->charset, "jisx0201") != NULL)
|
||||
load_table("./table/JISX0201", JISX0201);
|
||||
else if (strstr(bdf->charset, "JISX0208") != NULL || strstr(bdf->charset, "jisx0208") != NULL)
|
||||
else if (strstr(bdf_header->charset, "JISX0208") != NULL
|
||||
|| strstr(bdf_header->charset, "jisx0208") != NULL)
|
||||
load_table("./table/JISX0208", JISX0208);
|
||||
else if (strstr(bdf->charset, "ISO8859") != NULL || strstr(bdf->charset, "iso8859") != NULL)
|
||||
else if (strstr(bdf_header->charset, "ISO8859") != NULL
|
||||
|| strstr(bdf_header->charset, "iso8859") != NULL)
|
||||
load_table("./table/ISO8859", ISO8859);
|
||||
else /* assume "ISO10646" */
|
||||
load_table("./table/ISO10646", ISO10646);
|
||||
}
|
||||
else if (pre_match(buf, "CHARS ")) {
|
||||
bdf->chars = atoi(buf + strlen("CHARS "));
|
||||
bdf_header->chars = atoi(buf + strlen("CHARS "));
|
||||
return BDF_CHAR;
|
||||
}
|
||||
|
||||
return BDF_HEADER;
|
||||
}
|
||||
|
||||
int read_char(char *buf, struct bdf_glyph_t *glyph)
|
||||
int read_char(char *buf, struct bdf_char_t *bdf_char)
|
||||
{
|
||||
if (pre_match(buf, "BBX "))
|
||||
sscanf(buf + strlen("BBX "), "%d %d %d %d", &glyph->bbw, &glyph->bbh, &glyph->bbx, &glyph->bby);
|
||||
sscanf(buf + strlen("BBX "), "%d %d %d %d",
|
||||
&bdf_char->bbw, &bdf_char->bbh, &bdf_char->bbx, &bdf_char->bby);
|
||||
else if (pre_match(buf, "DWIDTH "))
|
||||
glyph->dwidth = atoi(buf + strlen("DWIDTH "));
|
||||
bdf_char->dwidth = atoi(buf + strlen("DWIDTH "));
|
||||
else if (pre_match(buf, "ENCODING ")) {
|
||||
glyph->encoding = atoi(buf + strlen("ENCODING "));
|
||||
//fprintf(stderr, "reading char:%d\n", glyph->encoding);
|
||||
bdf_char->encoding = atoi(buf + strlen("ENCODING "));
|
||||
//logging(DEBUG, "reading char:%d\n", bdf_char->encoding);
|
||||
}
|
||||
else if (pre_match(buf, "BITMAP")) {
|
||||
return BDF_BITMAP;
|
||||
|
@ -136,67 +127,85 @@ int read_char(char *buf, struct bdf_glyph_t *glyph)
|
|||
return BDF_CHAR;
|
||||
}
|
||||
|
||||
int read_bitmap(struct glyph_t *fonts, char *buf, struct bdf_t *bdf, struct bdf_glyph_t *glyph)
|
||||
int read_bitmap(struct glyph_list_t **glist_head, struct glyph_t *default_glyph,
|
||||
char *buf, struct bdf_header_t *bdf_header, struct bdf_char_t *bdf_char)
|
||||
{
|
||||
int i;
|
||||
static int count = 0;
|
||||
uint32_t code;
|
||||
uint8_t width, height;
|
||||
|
||||
static int count = 0;
|
||||
struct glyph_list_t *listp;
|
||||
struct glyph_t *glyph;
|
||||
|
||||
if (pre_match(buf, "ENDCHAR")) {
|
||||
shift_glyph(bdf, glyph);
|
||||
count = 0;
|
||||
|
||||
code = convert_table[glyph->encoding];
|
||||
width = glyph->dwidth;
|
||||
height = bdf->ascent + bdf->descent;
|
||||
shift_glyph(bdf_header, bdf_char);
|
||||
|
||||
//fprintf(stderr, "code:%d width:%d height:%d\n", code, width, height);
|
||||
code = convert_table[bdf_char->encoding];
|
||||
width = bdf_char->dwidth;
|
||||
height = bdf_header->ascent + bdf_header->descent;
|
||||
|
||||
if (code < UCS2_CHARS) {
|
||||
fonts[code].width = width;
|
||||
fonts[code].height = height;
|
||||
fonts[code].bitmap = (uint32_t *) ecalloc(fonts[code].height, sizeof(uint32_t));
|
||||
//logging(DEBUG, "code:%d width:%d height:%d\n", code, width, height);
|
||||
|
||||
for (i = 0; i < fonts[code].height; i++)
|
||||
fonts[code].bitmap[i] = glyph->bitmap[i];
|
||||
if (code < UCS2_CHARS && width <= 64) {
|
||||
listp = ecalloc(1, sizeof(struct glyph_list_t));
|
||||
glyph = ecalloc(1, sizeof(struct glyph_t));
|
||||
|
||||
glyph->width = width;
|
||||
glyph->height = height;
|
||||
/* XXX: max width 64 pixels (wide char) */
|
||||
glyph->bitmap = (bitmap_width_t *) ecalloc(glyph->height, sizeof(bitmap_width_t));
|
||||
|
||||
for (int i = 0; i < glyph->height; i++)
|
||||
glyph->bitmap[i] = bdf_char->bitmap[i];
|
||||
|
||||
/* add new element to glyph list */
|
||||
listp->code = code;
|
||||
listp->glyph = glyph;
|
||||
listp->next = *glist_head;
|
||||
*glist_head = listp;
|
||||
|
||||
if (code == DEFAULT_CHAR)
|
||||
*default_glyph = *glyph;
|
||||
}
|
||||
memset(glyph, 0, sizeof(struct bdf_glyph_t));
|
||||
memset(bdf_char, 0, sizeof(struct bdf_char_t));
|
||||
return BDF_CHAR;
|
||||
}
|
||||
else
|
||||
sscanf(buf, "%X", &glyph->bitmap[count++]);
|
||||
sscanf(buf, "%X", (unsigned int *) &bdf_char->bitmap[count++]);
|
||||
|
||||
return BDF_BITMAP;
|
||||
}
|
||||
|
||||
void load_bdf_glyph(struct glyph_t *fonts, char *path)
|
||||
bool load_bdf_glyph(struct glyph_list_t **glist_head, struct glyph_t *default_glyph, char *path)
|
||||
{
|
||||
int mode = BDF_HEADER;
|
||||
char buf[BUFSIZE], *cp;
|
||||
char lbuf[BUFSIZE], *cp;
|
||||
FILE *fp;
|
||||
struct bdf_t bdf;
|
||||
struct bdf_glyph_t glyph;
|
||||
struct bdf_header_t bdf_header;
|
||||
struct bdf_char_t bdf_char;
|
||||
|
||||
fp = efopen(path, "r");
|
||||
if ((fp = efopen(path, "r")) == NULL)
|
||||
return false;
|
||||
|
||||
memset(&bdf, 0, sizeof(struct bdf_t));
|
||||
memset(&glyph, 0, sizeof(struct bdf_glyph_t));
|
||||
memset(&bdf_header, 0, sizeof(struct bdf_header_t));
|
||||
memset(&bdf_char, 0, sizeof(struct bdf_char_t));
|
||||
|
||||
fprintf(stderr, "read bdf: %s\n", path);
|
||||
logging(DEBUG, "read bdf: %s\n", path);
|
||||
|
||||
while (fgets(buf, BUFSIZE, fp) != NULL) {
|
||||
if ((cp = strchr(buf, '\n')) != NULL)
|
||||
while (fgets(lbuf, BUFSIZE, fp) != NULL) {
|
||||
if ((cp = strchr(lbuf, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
//fprintf(stderr, "%s\n", buf);
|
||||
//fprintf(stderr, "%s\n", lbuf);
|
||||
|
||||
if (mode == BDF_HEADER)
|
||||
mode = read_header(buf, &bdf);
|
||||
mode = read_header(lbuf, &bdf_header);
|
||||
else if (mode == BDF_CHAR)
|
||||
mode = read_char(buf, &glyph);
|
||||
mode = read_char(lbuf, &bdf_char);
|
||||
else if (mode == BDF_BITMAP)
|
||||
mode = read_bitmap(fonts, buf, &bdf, &glyph);
|
||||
mode = read_bitmap(glist_head, default_glyph, lbuf, &bdf_header, &bdf_char);
|
||||
}
|
||||
efclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
|
183
tools/font.h
183
tools/font.h
|
@ -1,183 +0,0 @@
|
|||
void fatal(char *str)
|
||||
{
|
||||
perror(str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
FILE *efopen(char *path, char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
errno = 0;
|
||||
|
||||
if ((fp = fopen(path, mode)) == NULL) {
|
||||
fprintf(stderr, "cannot open \"%s\"\n", path);
|
||||
fatal("fopen");
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
void efclose(FILE *fp)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
if (fclose(fp) < 0)
|
||||
fatal("fclose");
|
||||
}
|
||||
|
||||
void *ecalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
errno = 0;
|
||||
|
||||
if ((ptr = calloc(nmemb, size)) == NULL)
|
||||
fatal("calloc");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* for yaft original font format: not used
|
||||
|
||||
CODE
|
||||
WIDTH HEIGHT
|
||||
BITMAP
|
||||
BITMAP
|
||||
BITMAP
|
||||
CODE
|
||||
WIDTH HEIGHT
|
||||
....
|
||||
|
||||
void load_glyph(struct glyph_t *fonts, char *path)
|
||||
{
|
||||
int count = 0, state = 0;
|
||||
char buf[BUFSIZE], *endp;
|
||||
FILE *fp;
|
||||
uint16_t code = DEFAULT_CHAR;
|
||||
|
||||
fp = efopen(path, "r");
|
||||
|
||||
while (fgets(buf, BUFSIZE, fp) != NULL) {
|
||||
if (strlen(buf) == 0 || buf[0] == '#')
|
||||
continue;
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
code = atoi(buf);
|
||||
if (fonts[code].bitmap != NULL) {
|
||||
free(fonts[code].bitmap);
|
||||
fonts[code].bitmap = NULL;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
sscanf(buf, "%hhu %hhu", &fonts[code].width, &fonts[code].height);
|
||||
fonts[code].bitmap = (uint32_t *) emalloc(fonts[code].height * sizeof(uint32_t));
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
fonts[code].bitmap[count++] = strtol(buf, &endp, 16);
|
||||
if (count >= fonts[code].height)
|
||||
state = count = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
efclose(fp);
|
||||
}
|
||||
*/
|
||||
|
||||
void load_alias(struct glyph_t *fonts, char *alias)
|
||||
{
|
||||
unsigned int dst, src;
|
||||
char buf[BUFSIZE];
|
||||
FILE *fp;
|
||||
|
||||
fp = efopen(alias, "r");
|
||||
|
||||
while (fgets(buf, BUFSIZE, fp) != NULL) {
|
||||
if (strlen(buf) == 0 || buf[0] == '#')
|
||||
continue;
|
||||
|
||||
sscanf(buf, "%X %X", &dst, &src);
|
||||
if ((dst >= UCS2_CHARS) || (src >= UCS2_CHARS))
|
||||
continue;
|
||||
|
||||
if (fonts[src].bitmap != NULL) {
|
||||
fprintf(stderr, "swapped: use U+%.4X for U+%.4X\n", src, dst);
|
||||
|
||||
free(fonts[dst].bitmap);
|
||||
fonts[dst].width = fonts[src].width;
|
||||
fonts[dst].height = fonts[src].height;
|
||||
fonts[dst].bitmap = fonts[src].bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
efclose(fp);
|
||||
}
|
||||
|
||||
void set_empty_glyph(struct glyph_t *fonts, uint32_t code, enum glyph_width_t wide)
|
||||
{
|
||||
fonts[code].width = fonts[DEFAULT_CHAR].width * wide;
|
||||
fonts[code].height = fonts[DEFAULT_CHAR].height;
|
||||
fonts[code].bitmap = (uint32_t *) ecalloc(fonts[DEFAULT_CHAR].height, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void check_fonts(struct glyph_t *fonts)
|
||||
{
|
||||
if (fonts[DEFAULT_CHAR].bitmap == NULL) {
|
||||
fprintf(stderr, "default glyph(U+%.4X) not found\n", DEFAULT_CHAR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fonts[SUBSTITUTE_HALF].bitmap == NULL) {
|
||||
fprintf(stderr, "half substitute glyph(U+%.4X) not found, use empty glyph\n", SUBSTITUTE_HALF);
|
||||
set_empty_glyph(fonts, SUBSTITUTE_HALF, HALF);
|
||||
}
|
||||
|
||||
if (fonts[SUBSTITUTE_WIDE].bitmap == NULL) {
|
||||
fprintf(stderr, "wide substitute glyph(U+%.4X) not found, use empty glyph\n", SUBSTITUTE_WIDE);
|
||||
set_empty_glyph(fonts, SUBSTITUTE_WIDE, WIDE);
|
||||
}
|
||||
|
||||
if (fonts[REPLACEMENT_CHAR].bitmap == NULL) {
|
||||
fprintf(stderr, "replacement glyph(U+%.4X) not found, use empty glyph\n", REPLACEMENT_CHAR);
|
||||
set_empty_glyph(fonts, REPLACEMENT_CHAR, HALF);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_fonts(struct glyph_t *fonts)
|
||||
{
|
||||
int i, j, width;
|
||||
uint8_t cell_width, cell_height;
|
||||
|
||||
cell_width = fonts[DEFAULT_CHAR].width;
|
||||
cell_height = fonts[DEFAULT_CHAR].height;
|
||||
|
||||
fprintf(stdout,
|
||||
"struct glyph_t {\n"
|
||||
"\tuint32_t code;\n"
|
||||
"\tuint8_t width;\n"
|
||||
"\tuint%d_t bitmap[%d];\n"
|
||||
"};\n\n", ((cell_width + BITS_PER_BYTE - 1) / BITS_PER_BYTE) * BITS_PER_BYTE * 2, cell_height);
|
||||
|
||||
fprintf(stdout, "enum {\n\tCELL_WIDTH = %d,\n\tCELL_HEIGHT = %d\n};\n\n",
|
||||
cell_width, cell_height);
|
||||
|
||||
fprintf(stdout, "static const struct glyph_t glyphs[] = {\n");
|
||||
for (i = 0; i < UCS2_CHARS; i++) {
|
||||
width = wcwidth(i);
|
||||
|
||||
if ((width <= 0) /* not printable */
|
||||
|| (fonts[i].bitmap == NULL) /* glyph not found */
|
||||
|| (fonts[i].height != cell_height) /* invalid font height */
|
||||
|| (fonts[i].width != (cell_width * width))) /* invalid font width */
|
||||
continue;
|
||||
|
||||
fprintf(stdout, "\t{%d, %d, {", i, width);
|
||||
for (j = 0; j < cell_height; j++)
|
||||
fprintf(stdout, "0x%X%s", fonts[i].bitmap[j], (j == (cell_height - 1)) ? "": ", ");
|
||||
fprintf(stdout, "}},\n");
|
||||
}
|
||||
fprintf(stdout, "};\n");
|
||||
}
|
|
@ -1,31 +1,201 @@
|
|||
#include "mkfont_bdf.h"
|
||||
#include "../conf.h"
|
||||
#include "font.h"
|
||||
#include "util.h"
|
||||
#include "bdf.h"
|
||||
|
||||
/* mkfont_bdf functions */
|
||||
bool map_glyph(struct glyph_t *font[],
|
||||
struct glyph_list_t *glist_head, struct glyph_t *default_glyph)
|
||||
{
|
||||
int width, cell_width = 0, cell_height = 0;
|
||||
struct glyph_t *glyph;
|
||||
struct glyph_list_t *listp;
|
||||
|
||||
if (default_glyph == NULL) {
|
||||
logging(ERROR, "default glyph(U+%.4X) not found\n", DEFAULT_CHAR);
|
||||
return false;
|
||||
}
|
||||
|
||||
cell_width = default_glyph->width;
|
||||
cell_height = default_glyph->height;
|
||||
|
||||
for (listp = glist_head; listp != NULL; listp = listp->next) {
|
||||
if (listp->code >= UCS2_CHARS)
|
||||
continue;
|
||||
|
||||
width = wcwidth(listp->code);
|
||||
glyph = listp->glyph;
|
||||
if ((width <= 0) /* not printable */
|
||||
|| (glyph->height != cell_height) /* invalid font height */
|
||||
|| (glyph->width != (cell_width * width))) /* invalid font width */
|
||||
continue;
|
||||
|
||||
font[listp->code] = glyph;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_alias(struct glyph_t *font[], char *alias)
|
||||
{
|
||||
unsigned int dst, src;
|
||||
char buf[BUFSIZE];
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = efopen(alias, "r")) == NULL)
|
||||
return false;
|
||||
|
||||
while (fgets(buf, BUFSIZE, fp) != NULL) {
|
||||
if (strlen(buf) == 0 || buf[0] == '#')
|
||||
continue;
|
||||
|
||||
sscanf(buf, "%X %X", &dst, &src);
|
||||
if ((dst >= UCS2_CHARS) || (src >= UCS2_CHARS))
|
||||
continue;
|
||||
|
||||
if (font[src] != NULL && font[dst] != NULL) {
|
||||
logging(DEBUG, "swapped: use U+%.4X for U+%.4X\n", src, dst);
|
||||
|
||||
//free(font[dst]->bitmap);
|
||||
font[dst]->width = font[src]->width;
|
||||
font[dst]->height = font[src]->height;
|
||||
//font[dst]->bitmap = font[src]->bitmap;
|
||||
memcpy(font[dst]->bitmap, font[src]->bitmap, sizeof(bitmap_width_t) * font[src]->height);
|
||||
}
|
||||
}
|
||||
efclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_font(struct glyph_t **font, struct glyph_t *empty_half, struct glyph_t *empty_wide)
|
||||
{
|
||||
empty_half->bitmap = (bitmap_width_t *) ecalloc(font[DEFAULT_CHAR]->height, sizeof(bitmap_width_t));
|
||||
empty_wide->bitmap = (bitmap_width_t *) ecalloc(font[DEFAULT_CHAR]->height, sizeof(bitmap_width_t));
|
||||
|
||||
if (!empty_half->bitmap || !empty_wide->bitmap)
|
||||
return false;
|
||||
|
||||
empty_half->width = font[DEFAULT_CHAR]->width;
|
||||
empty_wide->width = font[DEFAULT_CHAR]->width * WIDE;
|
||||
empty_half->height = font[DEFAULT_CHAR]->height;
|
||||
empty_wide->height = font[DEFAULT_CHAR]->height;
|
||||
|
||||
if (font[SUBSTITUTE_HALF] == NULL) {
|
||||
logging(WARN, "half substitute glyph(U+%.4X) not found, use empty glyph\n", SUBSTITUTE_HALF);
|
||||
font[SUBSTITUTE_HALF] = empty_half;
|
||||
}
|
||||
if (font[SUBSTITUTE_WIDE] == NULL) {
|
||||
logging(WARN, "wide substitute glyph(U+%.4X) not found, use empty glyph\n", SUBSTITUTE_WIDE);
|
||||
font[SUBSTITUTE_HALF] = empty_wide;
|
||||
}
|
||||
if (font[REPLACEMENT_CHAR] == NULL) {
|
||||
logging(WARN, "replacement glyph(U+%.4X) not found, use empty glyph\n", REPLACEMENT_CHAR);
|
||||
font[SUBSTITUTE_HALF] = empty_half;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dump_font(struct glyph_t *font[])
|
||||
{
|
||||
int i, j, width, int_type;
|
||||
uint8_t cell_width, cell_height;
|
||||
|
||||
cell_width = font[DEFAULT_CHAR]->width;
|
||||
cell_height = font[DEFAULT_CHAR]->height;
|
||||
|
||||
int_type = my_ceil(cell_width, BITS_PER_BYTE) /* minimum byte for containing half glyph */
|
||||
* 2 /* minimum byte for containing wide glyph */
|
||||
* BITS_PER_BYTE; /* minimum bits for containing wide glyph */
|
||||
|
||||
/* int_type: 16, 32, 48, 64, 80... */
|
||||
if (int_type == 48) { /* uint48_t does not exist */
|
||||
int_type = 64;
|
||||
} else if (int_type >= 80) {
|
||||
logging(ERROR, "BDF width too large (uint%d_t does not exist)\n", int_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(stdout,
|
||||
"struct glyph_t {\n"
|
||||
"\tuint32_t code;\n"
|
||||
"\tuint8_t width;\n"
|
||||
"\tuint%d_t bitmap[%d];\n"
|
||||
"};\n\n", int_type, cell_height);
|
||||
|
||||
fprintf(stdout, "enum {\n\tCELL_WIDTH = %d,\n\tCELL_HEIGHT = %d\n};\n\n",
|
||||
cell_width, cell_height);
|
||||
|
||||
fprintf(stdout, "static const struct glyph_t glyphs[] = {\n");
|
||||
for (i = 0; i < UCS2_CHARS; i++) {
|
||||
width = wcwidth(i);
|
||||
|
||||
if (font[i] == NULL) /* glyph not found */
|
||||
continue;
|
||||
|
||||
fprintf(stdout, "\t{%d, %d, {", i, width);
|
||||
for (j = 0; j < cell_height; j++)
|
||||
fprintf(stdout, "0x%X%s", (unsigned int) font[i]->bitmap[j], (j == (cell_height - 1)) ? "": ", ");
|
||||
fprintf(stdout, "}},\n");
|
||||
}
|
||||
fprintf(stdout, "};\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup(struct glyph_list_t *glist_head, struct glyph_t *empty_half, struct glyph_t *empty_wide)
|
||||
{
|
||||
struct glyph_list_t *listp, *next;
|
||||
|
||||
for (listp = glist_head; listp != NULL; listp = next) {
|
||||
next = listp->next;
|
||||
|
||||
free(listp->glyph->bitmap);
|
||||
free(listp->glyph);
|
||||
free(listp);
|
||||
}
|
||||
free(empty_half->bitmap);
|
||||
free(empty_wide->bitmap);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct glyph_t fonts[UCS2_CHARS];
|
||||
struct glyph_list_t *glist_head = NULL;
|
||||
struct glyph_t *font[UCS2_CHARS], default_glyph, empty_wide, empty_half;
|
||||
|
||||
setlocale(LC_ALL, ""); /* set current locale for wcwidth() */
|
||||
if (!setlocale(LC_ALL, "")) /* set current locale for wcwidth() */
|
||||
logging(WARN, "setlocale() failed\n");
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "usage: ./mkfont ALIAS BDF1 [BDF2] [BDF3] ...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
logging(FATAL, "usage: ./mkfont ALIAS BDF1 [BDF2] [BDF3] ...\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < UCS2_CHARS; i++)
|
||||
fonts[i].bitmap = NULL;
|
||||
for (int i = 0; i < UCS2_CHARS; i++)
|
||||
font[i] = NULL;
|
||||
|
||||
for (i = 2; i < argc; i++)
|
||||
load_bdf_glyph(fonts, argv[i]);
|
||||
for (int i = 2; i < argc; i++)
|
||||
load_bdf_glyph(&glist_head, &default_glyph, argv[i]);
|
||||
|
||||
load_alias(fonts, argv[1]);
|
||||
if (!map_glyph(font, glist_head, &default_glyph)) {
|
||||
logging(FATAL, "map_glyph() failed\n");
|
||||
goto err_occured;
|
||||
}
|
||||
|
||||
check_fonts(fonts);
|
||||
if (!load_alias(font, argv[1]))
|
||||
logging(WARN, "font alias does not work\n");
|
||||
|
||||
dump_fonts(fonts);
|
||||
if (!check_font(font, &empty_half, &empty_wide)) {
|
||||
logging(FATAL, "map_glyph() failed\n");
|
||||
goto err_occured;
|
||||
}
|
||||
|
||||
if (!dump_font(font)) {
|
||||
logging(FATAL, "map_glyph() failed\n");
|
||||
goto err_occured;
|
||||
}
|
||||
|
||||
cleanup(glist_head, &empty_half, &empty_wide);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
err_occured:
|
||||
cleanup(glist_head, &empty_half, &empty_wide);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
@ -10,6 +11,8 @@
|
|||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef uint64_t bitmap_width_t;
|
||||
|
||||
enum char_code {
|
||||
/* 7 bit control char */
|
||||
BEL = 0x07, BS = 0x08, HT = 0x09,
|
||||
|
@ -25,7 +28,7 @@ enum misc {
|
|||
BUFSIZE = 1024, /* read, esc, various buffer size */
|
||||
UCS2_CHARS = 0x10000, /* number of UCS2 glyph */
|
||||
DEFAULT_CHAR = SPACE, /* used for erase char, cell_size */
|
||||
MAX_HEIGHT = 32,
|
||||
MAX_HEIGHT = 64,
|
||||
BDF_HEADER = 0,
|
||||
BDF_CHAR = 1,
|
||||
BDF_BITMAP = 2,
|
||||
|
@ -51,10 +54,16 @@ enum glyph_width_t {
|
|||
|
||||
struct glyph_t {
|
||||
uint8_t width, height;
|
||||
uint32_t *bitmap;
|
||||
bitmap_width_t *bitmap;
|
||||
};
|
||||
|
||||
struct bdf_t {
|
||||
struct glyph_list_t {
|
||||
uint32_t code;
|
||||
struct glyph_t *glyph;
|
||||
struct glyph_list_t *next;
|
||||
};
|
||||
|
||||
struct bdf_header_t {
|
||||
int bbw, bbh, bbx, bby;
|
||||
int ascent, descent;
|
||||
int default_char;
|
||||
|
@ -63,11 +72,11 @@ struct bdf_t {
|
|||
char charset[BUFSIZE];
|
||||
};
|
||||
|
||||
struct bdf_glyph_t {
|
||||
struct bdf_char_t {
|
||||
int bbw, bbh, bbx, bby;
|
||||
int dwidth;
|
||||
int encoding;
|
||||
uint32_t bitmap[MAX_HEIGHT];
|
||||
bitmap_width_t bitmap[MAX_HEIGHT];
|
||||
};
|
||||
|
||||
int convert_table[UCS2_CHARS];
|
||||
|
|
71
tools/util.h
Normal file
71
tools/util.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* wrapper of C functions */
|
||||
enum loglevel_t {
|
||||
DEBUG = 0,
|
||||
WARN,
|
||||
ERROR,
|
||||
FATAL,
|
||||
};
|
||||
|
||||
void logging(enum loglevel_t loglevel, char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
static const char *loglevel2str[] = {
|
||||
[DEBUG] = "DEBUG",
|
||||
[WARN] = "WARN",
|
||||
[ERROR] = "ERROR",
|
||||
[FATAL] = "FATAL",
|
||||
};
|
||||
|
||||
/* debug message is available on verbose mode */
|
||||
if ((loglevel == DEBUG) && (VERBOSE == false))
|
||||
return;
|
||||
|
||||
fprintf(stderr, ">>%s<<\t", loglevel2str[loglevel]);
|
||||
|
||||
va_start(arg, format);
|
||||
vfprintf(stderr, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
FILE *efopen(const char *path, char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
errno = 0;
|
||||
|
||||
if ((fp = fopen(path, mode)) == NULL) {
|
||||
logging(ERROR, "couldn't open \"%s\"\n", path);
|
||||
logging(ERROR, "fopen: %s\n", strerror(errno));
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int efclose(FILE *fp)
|
||||
{
|
||||
int ret;
|
||||
errno = 0;
|
||||
|
||||
if ((ret = fclose(fp)) < 0)
|
||||
logging(ERROR, "fclose: %s\n", strerror(errno));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *ecalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
errno = 0;
|
||||
|
||||
if ((ptr = calloc(nmemb, size)) == NULL)
|
||||
logging(ERROR, "calloc: %s\n", strerror(errno));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int my_ceil(int val, int div)
|
||||
{
|
||||
if (div == 0)
|
||||
//return 0;
|
||||
return -1;
|
||||
else
|
||||
return (val + div - 1) / div;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue