diff --git a/.gitignore b/.gitignore index 27f6474..7939511 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # gitignore(5) file *.[oa] *~ +*.swp # generated files bdf2c diff --git a/bdf2c.1 b/bdf2c.1 index 5f8fdcc..e936043 100644 --- a/bdf2c.1 +++ b/bdf2c.1 @@ -7,18 +7,29 @@ bdf2c \- converts bdf font files into C include files .SH SYNOPSIS .B bdf2c .I [-?|-h] +.I [-b file] .I [-c] .I [-C file] -.I [-b] .SH DESCRIPTION +bdf2c creates C source and C header file from bdf font files. Which can be +used to embed fonts into the executable. + .SH OPTIONS .TP .B -?|-h -Show help options. +Show short help and exit. .TP +.B -c +Create C header file on stdout. +.TP +.B -C file +Creates C header file 'file'. +.TP +.B -b file +Read and convert bdf font 'file'. .SH AUTHOR Johns (2009) . diff --git a/bdf2c.c b/bdf2c.c index fa7a1ea..7cd4af6 100644 --- a/bdf2c.c +++ b/bdf2c.c @@ -20,10 +20,20 @@ /// $Id$ ////////////////////////////////////////////////////////////////////////////// +/// +/// @mainpage +/// bdf2c - converts bdf font files into C include files. +/// +/// The Bitmap Distribution Format (BDF) is a file format for +/// storing bitmap fonts. The content is presented as a text file +/// that is intended to be human and computer readable. +/// + #include #include #include #include +#include #include #define VERSION "1" @@ -37,7 +47,18 @@ void CreateFontHeaderFile(FILE * out) { register int i; - fprintf(out, "// (c) 2009 Johns, License: AGPLv3\n"); + fprintf(out, "// (c) 2009 Johns, License: AGPLv3\n\n"); + fprintf(out, "\t/// bitmap font structure\n" + "struct bitmap_font {\n" + "\tunsigned char Width;\t\t///< max. character width\n" + "\tunsigned char Height;\t\t///< character height\n" + "\tunsigned short Chars;\t\t///< number of characters in font\n" + "\tunsigned char *Widths;\t\t///< width of each character\n" + "\tunsigned short *Index;\t\t///< encoding to character index\n" + "\tunsigned char *Bitmap;\t\t///< bitmap of each character\n" + "};\n\n"); + + fprintf(out, "\t/// @{ defines to have human readable font files\n"); for (i = 0; i < 256; ++i) { fprintf(out, "#define %c%c%c%c%c%c%c%c 0x%02X\n", (i & 0x80) ? 'X' : '_', (i & 0x40) ? 'X' : '_', @@ -45,10 +66,74 @@ void CreateFontHeaderFile(FILE * out) (i & 0x08) ? 'X' : '_', (i & 0x04) ? 'X' : '_', (i & 0x02) ? 'X' : '_', (i & 0x01) ? 'X' : '_', i); } + fprintf(out, "\t/// @}\n"); } ////////////////////////////////////////////////////////////////////////////// +// +// Print header for c file. +// +void Header(FILE * out, const char *name) +{ + fprintf(out, + "// Created from bdf2c Version %s, (c) 2009 by Johns\n" + "//\tLicense AGPLv3: GNU Affero General Public License version 3\n" + "\n#include \"font.h\"\n\n", VERSION); + + fprintf(out, + "\t/// character bitmap for each encoding\n" + "static const unsigned char __%s_bitmap__[] = {\n", name); +} + +// +// Print width table for c file +// +void WidthTable(FILE * out, const char *name, const unsigned *width_table, + int chars) +{ + fprintf(out, "};\n\n"); + + fprintf(out, + "\t/// character width for each encoding\n" + "static const unsigned char __%s_widths__[] = {\n", name); + while (chars--) { + printf("\t%u,\n", *width_table++); + } +} + +// +// Print encoding table for c file +// +void EncodingTable(FILE * out, const char *name, + const unsigned *encoding_table, int chars) +{ + fprintf(out, "};\n\n"); + + fprintf(out, + "\t/// character encoding for each index entry\n" + "static const unsigned short __%s_index__[] = {\n", name); + while (chars--) { + printf("\t%u,\n", *encoding_table++); + } +} + +// +// Print footer for c file. +// +void Footer(FILE * out, const char *name, int width, int height, int chars) +{ + fprintf(out, "};\n\n"); + fprintf(out, "\t/// bitmap font structure\n" + "struct bitmap_font %s = {\n", name); + fprintf(out, "\t.Width %d, .Height %d,\n", width, height); + fprintf(out, "\t.Chars %d,\n", chars); + fprintf(out, "\t.Widths __%s_widths__,\n", name); + fprintf(out, "\t.Index __%s_index__,\n", name); + fprintf(out, "\t.Bitmap __%s_bitmap__,\n", name); + fprintf(out, "};\n\n"); +} + // // Read BDF font file. // @@ -56,7 +141,28 @@ void ReadBdf(FILE * bdf) { char linebuf[1024]; char *s; + char *p; + int fontboundingbox_width; + int fontboundingbox_height; + int chars; + int i; + int n; + int scanline; + char charname[1024]; + int encoding; + int bbx; + int bby; + int bbw; + int bbh; + int width; + unsigned *width_table; + unsigned *encoding_table; + const char *name; + name = "font"; + fontboundingbox_width = 0; + fontboundingbox_height = 0; + chars = 0; for (;;) { if (!fgets(linebuf, sizeof(linebuf), bdf)) { // EOF break; @@ -64,8 +170,126 @@ void ReadBdf(FILE * bdf) if (!(s = strtok(linebuf, " \t\n\r"))) { // empty line break; } - printf("token:%s\n", s); + // printf("token:%s\n", s); + if (!strcasecmp(s, "FONTBOUNDINGBOX")) { + p = strtok(NULL, " \t\n\r"); + fontboundingbox_width = atoi(p); + p = strtok(NULL, " \t\n\r"); + fontboundingbox_height = atoi(p); + } else if (!strcasecmp(s, "CHARS")) { + p = strtok(NULL, " \t\n\r"); + chars = atoi(p); + break; + } } + /* + printf("%d * %dx%d\n", chars, fontboundingbox_width, + fontboundingbox_height); + */ + + if (chars <= 0) { + fprintf(stderr, "Need to know the number of characters\n"); + exit(-1); + } + width_table = malloc(chars * sizeof(*width_table)); + if (!width_table) { + fprintf(stderr, "Out of memory\n"); + exit(-1); + } + encoding_table = malloc(chars * sizeof(*encoding_table)); + if (!encoding_table) { + fprintf(stderr, "Out of memory\n"); + exit(-1); + } + + Header(stdout, name); + + scanline = -1; + n = 0; + encoding = -1; + bbx = 0; + bby = 0; + bbw = 0; + bbh = 0; + width = INT_MIN; + strcpy(charname, "unknown character"); + for (;;) { + if (!fgets(linebuf, sizeof(linebuf), bdf)) { // EOF + break; + } + if (!(s = strtok(linebuf, " \t\n\r"))) { // empty line + break; + } + // printf("token:%s\n", s); + if (!strcasecmp(s, "STARTCHAR")) { + p = strtok(NULL, " \t\n\r"); + strcpy(charname, p); + } else if (!strcasecmp(s, "ENCODING")) { + p = strtok(NULL, " \t\n\r"); + encoding = atoi(p); + } else if (!strcasecmp(s, "DWIDTH")) { + p = strtok(NULL, " \t\n\r"); + width = atoi(p); + } else if (!strcasecmp(s, "BBX")) { + p = strtok(NULL, " \t\n\r"); + bbw = atoi(p); + p = strtok(NULL, " \t\n\r"); + bbh = atoi(p); + p = strtok(NULL, " \t\n\r"); + bbx = atoi(p); + p = strtok(NULL, " \t\n\r"); + bby = atoi(p); + } else if (!strcasecmp(s, "BITMAP")) { + fprintf(stdout, "// %3d $%02x '%s'\n", encoding, encoding, + charname); + fprintf(stdout, "//\twidth %d, bbx %d, bby %d, bbw %d, bbh %d\n", + width, bbx, bby, bbw, bbh); + + if (n == chars) { + fprintf(stderr, "Too many bitmaps for characters\n"); + exit(-1); + } + width_table[n] = width; + encoding_table[n] = encoding; + ++n; + scanline = 0; + } else if (!strcasecmp(s, "ENDCHAR")) { + scanline = -1; + } else { + if (scanline >= 0) { + p = s; + fprintf(stdout, "\t"); + while (*p) { + if (*p <= '9') { + i = *p - '0'; + } else if (*p <= 'F') { + i = *p - 'A' + 10; + } else { + i = *p - 'a' + 10; + } + fprintf(stdout, "%c%c%c%c", (i & 0x08) ? 'X' : '_', + (i & 0x04) ? 'X' : '_', (i & 0x02) ? 'X' : '_', + (i & 0x01) ? 'X' : '_'); + ++p; + if (~(p - s) & 1) { + fprintf(stdout, ","); + } + } + if ((p - s) & 1) { // fill last nibble + fprintf(stdout, "____,"); + } + fprintf(stdout, "\n"); + ++scanline; + } + } + } + + // Output width table for proportional font. + WidthTable(stdout, name, width_table, chars); + // Output encoding table for utf-8 support + EncodingTable(stdout, name, encoding_table, chars); + + Footer(stdout, name, fontboundingbox_width, fontboundingbox_height, chars); } ////////////////////////////////////////////////////////////////////////////// @@ -85,8 +309,9 @@ void PrintVersion(void) // void PrintUsage(void) { - printf("Usage: bdf2c [OPTIONs]\n" "\t-c\tCreate font header on stdout\n" + printf("Usage: bdf2c [OPTIONs]\n" "\t-b\tRead bdf file from stdin\n" + "\t-c\tCreate font header on stdout\n" "\t-C file\tCreate font header file\n"); printf("\tOnly idiots print usage on stderr\n"); } diff --git a/readme.txt b/readme.txt index e1f71d3..37f0d23 100644 --- a/readme.txt +++ b/readme.txt @@ -11,3 +11,15 @@ Usage: Create font.h, which contains #defines for fonts. + ./bdf2c -b < font.bdf > font.c + + Create font.c which contains the converted bdf font. + +The C file contains: + + Bitmap data for the characters. + Character width table for proportional font + Character codes table for utf-8 font + +TODO: + Proportional fonts (f.e. generated from ttf2bdf) aren't yet supported.