bdf2c/bdf2c.c

387 lines
9.4 KiB
C
Raw Normal View History

2009-01-23 10:17:49 +00:00
///
2009-01-23 10:18:59 +00:00
/// @file bdf2c.c BDF Font to C source convertor
2009-01-23 10:17:49 +00:00
///
/// Copyright (c) 2009 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
/// License: AGPLv3
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Affero General Public License for more details.
///
2009-01-26 12:34:30 +00:00
/// $Id$
2009-01-23 10:17:49 +00:00
//////////////////////////////////////////////////////////////////////////////
2009-02-18 14:32:05 +00:00
///
/// @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.
///
2009-01-23 10:17:49 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
2009-02-18 14:32:05 +00:00
#include <limits.h>
2009-01-23 10:17:49 +00:00
#include <errno.h>
2009-03-19 14:04:27 +00:00
#define VERSION "2" ///< version of this application
2009-01-23 10:17:49 +00:00
//////////////////////////////////////////////////////////////////////////////
2009-03-19 14:04:27 +00:00
///
/// Create our header file.
///
/// @param out File handle for output
///
2009-01-23 10:17:49 +00:00
void CreateFontHeaderFile(FILE * out)
{
register int i;
2009-02-18 14:32:05 +00:00
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"
"\tconst unsigned char *Widths;\t///< width of each character\n"
"\tconst unsigned short *Index;\t///< encoding to character index\n"
2009-03-19 14:04:27 +00:00
"\tconst unsigned char *Bitmap;\t///< bitmap of all characters\n"
2009-02-18 14:32:05 +00:00
"};\n\n");
fprintf(out, "\t/// @{ defines to have human readable font files\n");
2009-01-23 10:17:49 +00:00
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' : '_',
(i & 0x20) ? 'X' : '_', (i & 0x10) ? 'X' : '_',
(i & 0x08) ? 'X' : '_', (i & 0x04) ? 'X' : '_',
(i & 0x02) ? 'X' : '_', (i & 0x01) ? 'X' : '_', i);
}
2009-02-18 14:32:05 +00:00
fprintf(out, "\t/// @}\n");
2009-01-23 10:17:49 +00:00
}
//////////////////////////////////////////////////////////////////////////////
2009-03-19 14:04:27 +00:00
///
/// Print header for c file.
///
/// @param out File handle for output
/// @param name Font variable name in C source file
///
2009-02-18 14:32:05 +00:00
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" "const 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);
2009-02-18 14:32:05 +00:00
fprintf(out, "};\n\n");
}
2009-01-26 11:39:04 +00:00
//
// Read BDF font file.
//
void ReadBdf(FILE * bdf, const char *name)
2009-01-26 11:39:04 +00:00
{
2009-01-26 12:34:30 +00:00
char linebuf[1024];
char *s;
2009-02-18 14:32:05 +00:00
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;
2009-01-26 11:39:04 +00:00
2009-02-18 14:32:05 +00:00
fontboundingbox_width = 0;
fontboundingbox_height = 0;
chars = 0;
2009-01-26 12:34:30 +00:00
for (;;) {
if (!fgets(linebuf, sizeof(linebuf), bdf)) { // EOF
break;
2009-01-26 11:39:04 +00:00
}
2009-01-26 12:34:30 +00:00
if (!(s = strtok(linebuf, " \t\n\r"))) { // empty line
break;
}
2009-02-18 14:32:05 +00:00
// 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;
}
2009-01-26 12:34:30 +00:00
}
2009-02-18 14:32:05 +00:00
/*
printf("%d * %dx%d\n", chars, fontboundingbox_width,
fontboundingbox_height);
*/
2009-02-18 14:32:05 +00:00
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);
2009-01-26 11:39:04 +00:00
}
//////////////////////////////////////////////////////////////////////////////
2009-01-23 10:17:49 +00:00
//
// Print version
//
void PrintVersion(void)
{
printf("bdf2c Version %s, (c) 2009 by Johns\n"
"\tLicense AGPLv3: GNU Affero General Public License version 3\n",
VERSION);
}
//
// Print usage
//
void PrintUsage(void)
{
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"
"\t-n name\tName of c font variable (place it before -b)\n");
2009-01-23 10:17:49 +00:00
printf("\tOnly idiots print usage on stderr\n");
}
//
// Main test program for bdf2c.
//
int main(int argc, char *const argv[])
{
const char *name;
name = "font";
2009-01-23 10:17:49 +00:00
//
// Parse arguments.
//
for (;;) {
switch (getopt(argc, argv, "bcC:n:h?-")) {
2009-01-26 11:39:04 +00:00
case 'b':
ReadBdf(stdin, name);
continue;
2009-01-23 10:17:49 +00:00
case 'c':
CreateFontHeaderFile(stdout);
break;
case 'C':
{
FILE *out;
if (!(out = fopen(optarg, "w"))) {
fprintf(stderr, "Can't open file '%s': %s\n", optarg,
strerror(errno));
exit(-1);
}
CreateFontHeaderFile(out);
fclose(out);
}
continue;
case 'n':
name = optarg;
continue;
2009-01-23 10:17:49 +00:00
case EOF:
break;
case '?':
case 'h': // help usage
PrintVersion();
PrintUsage();
exit(0);
case '-':
fprintf(stderr, "We need no long options\n");
PrintUsage();
exit(-1);
case ':':
PrintVersion();
fprintf(stderr, "Missing argument for option '%c'\n", optopt);
exit(-1);
default:
PrintVersion();
fprintf(stderr, "Unkown option '%c'\n", optopt);
exit(-1);
}
break;
}
while (optind < argc) {
fprintf(stderr, "Unhandled argument '%s'\n", argv[optind++]);
}
return 0;
}