Support for generating outline bitmap added.

Fixed bounding box bug.
This commit is contained in:
Johns 2009-03-19 21:12:38 +01:00
parent ebeaac6b0b
commit df59514df6
2 changed files with 277 additions and 39 deletions

28
bdf2c.1
View File

@ -1,5 +1,26 @@
.\"
.\" bdf2c.1 bdf2c man page
.\"
.\" 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.
.\"
.\" $Id: $
.\" ------------------------------------------------------------------------
.pc .pc
.TH "bdf2c" 1 "2009-02-16" "1" "bdf2c Manual" .TH "bdf2c" 1 "2009-03-19" "1" "bdf2c Manual"
.SH NAME .SH NAME
bdf2c \- converts bdf font files into C include files bdf2c \- converts bdf font files into C include files
@ -11,6 +32,7 @@ bdf2c \- converts bdf font files into C include files
.I [-c] .I [-c]
.I [-C file] .I [-C file]
.I [-n name] .I [-n name]
.I [-O]
.SH DESCRIPTION .SH DESCRIPTION
@ -34,7 +56,9 @@ Read and convert bdf font 'file'.
.TP .TP
.B -n name .B -n name
Name of the C font structure. 'name' should contain only valid identifier characters. f.e. font9x15b Name of the C font structure. 'name' should contain only valid identifier characters. f.e. font9x15b
.TP
.B -O
Create outline of the font.
.SH AUTHOR .SH AUTHOR
Johns (2009) <johns98@gmx.net>. Johns (2009) <johns98@gmx.net>.

288
bdf2c.c
View File

@ -36,7 +36,11 @@
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#define VERSION "2" ///< version of this application #define VERSION "3" ///< version of this application
//////////////////////////////////////////////////////////////////////////////
int Outline; ///< true generate outlined font
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -103,7 +107,7 @@ void WidthTable(FILE * out, const char *name, const unsigned *width_table,
"\t/// character width for each encoding\n" "\t/// character width for each encoding\n"
"static const unsigned char __%s_widths__[] = {\n", name); "static const unsigned char __%s_widths__[] = {\n", name);
while (chars--) { while (chars--) {
printf("\t%u,\n", *width_table++); fprintf(out, "\t%u,\n", *width_table++);
} }
} }
@ -119,7 +123,7 @@ void EncodingTable(FILE * out, const char *name,
"\t/// character encoding for each index entry\n" "\t/// character encoding for each index entry\n"
"static const unsigned short __%s_index__[] = {\n", name); "static const unsigned short __%s_index__[] = {\n", name);
while (chars--) { while (chars--) {
printf("\t%u,\n", *encoding_table++); fprintf(out, "\t%u,\n", *encoding_table++);
} }
} }
@ -140,10 +144,154 @@ void Footer(FILE * out, const char *name, int width, int height, int chars)
fprintf(out, "};\n\n"); fprintf(out, "};\n\n");
} }
// ///
// Read BDF font file. /// Dump character.
// ///
void ReadBdf(FILE * bdf, const char *name) void DumpCharacter(FILE * out, unsigned char *bitmap, int width, int height)
{
int x;
int y;
int c;
for (y = 0; y < height; ++y) {
fputc('\t', out);
for (x = 0; x < width; x += 8) {
c = bitmap[y * ((width + 7) / 8) + x / 8];
//printf("%d = %d\n", y * ((width+7)/8) + x/8, c);
if (c & 0x80) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x40) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x20) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x10) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x08) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x04) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x02) {
fputc('X', out);
} else {
fputc('_', out);
}
if (c & 0x01) {
fputc('X', out);
} else {
fputc('_', out);
}
fputc(',', out);
}
fputc('\n', out);
}
}
///
/// Hex ascii to integer
///
static inline int Hex2Int(const char *p)
{
if (*p <= '9') {
return *p - '0';
} else if (*p <= 'F') {
return *p - 'A' + 10;
} else {
return *p - 'a' + 10;
}
}
///
/// Rotate bitmap.
///
void RotateBitmap(unsigned char *bitmap, int shift, int width, int height)
{
int x;
int y;
int c;
int o;
if (shift < 0 || shift > 7) {
fprintf(stderr, "This shift isn't supported\n");
exit(-1);
}
for (y = 0; y < height; ++y) {
o = 0;
for (x = 0; x < width; x += 8) {
c = bitmap[y * ((width + 7) / 8) + x / 8];
bitmap[y * ((width + 7) / 8) + x / 8] = c >> shift | o;
o = c << (8 - shift);
}
}
}
///
/// Outline character.
///
void OutlineCharacter(unsigned char *bitmap, int width, int height)
{
int x;
int y;
unsigned char *outline;
outline = alloca(((width + 7) / 8) * height);
memset(outline, 0, ((width + 7) / 8) * height);
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
// Bit not set check surroundings
if (~bitmap[y * ((width + 7) / 8) + x / 8] & (0x80 >> x % 8)) {
// Upper row bit was set
if (y
&& bitmap[(y - 1) * ((width + 7) / 8) +
x / 8] & (0x80 >> x % 8)) {
outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
// Previous bit was set
} else if (x
&& bitmap[y * ((width + 7) / 8) + (x -
1) / 8] & (0x80 >> (x - 1) % 8)) {
outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
// Next bit was set
} else if (x < width - 1
&& bitmap[y * ((width + 7) / 8) + (x +
1) / 8] & (0x80 >> (x + 1) % 8)) {
outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
// below row was set
} else if (y < height - 1
&& bitmap[(y + 1) * ((width + 7) / 8) +
x / 8] & (0x80 >> x % 8)) {
outline[y * ((width + 7) / 8) + x / 8] |= (0x80 >> x % 8);
}
}
}
}
memcpy(bitmap, outline, ((width + 7) / 8) * height);
}
///
/// Read BDF font file.
///
///
/// @todo bbx isn't used to correct character position in bitmap
///
void ReadBdf(FILE * bdf, FILE * out, const char *name)
{ {
char linebuf[1024]; char linebuf[1024];
char *s; char *s;
@ -152,6 +300,7 @@ void ReadBdf(FILE * bdf, const char *name)
int fontboundingbox_height; int fontboundingbox_height;
int chars; int chars;
int i; int i;
int j;
int n; int n;
int scanline; int scanline;
char charname[1024]; char charname[1024];
@ -163,6 +312,7 @@ void ReadBdf(FILE * bdf, const char *name)
int width; int width;
unsigned *width_table; unsigned *width_table;
unsigned *encoding_table; unsigned *encoding_table;
unsigned char *bitmap;
fontboundingbox_width = 0; fontboundingbox_width = 0;
fontboundingbox_height = 0; fontboundingbox_height = 0;
@ -190,11 +340,24 @@ void ReadBdf(FILE * bdf, const char *name)
printf("%d * %dx%d\n", chars, fontboundingbox_width, printf("%d * %dx%d\n", chars, fontboundingbox_width,
fontboundingbox_height); fontboundingbox_height);
*/ */
//
// Some checks.
//
if (fontboundingbox_width <= 0 || fontboundingbox_height <= 0) {
fprintf(stderr, "Need to know the character size\n");
exit(-1);
}
if (chars <= 0) { if (chars <= 0) {
fprintf(stderr, "Need to know the number of characters\n"); fprintf(stderr, "Need to know the number of characters\n");
exit(-1); exit(-1);
} }
if (Outline) { // Reserve space for outline border
fontboundingbox_width++;
fontboundingbox_height++;
}
//
// Allocate tables
//
width_table = malloc(chars * sizeof(*width_table)); width_table = malloc(chars * sizeof(*width_table));
if (!width_table) { if (!width_table) {
fprintf(stderr, "Out of memory\n"); fprintf(stderr, "Out of memory\n");
@ -205,8 +368,21 @@ void ReadBdf(FILE * bdf, const char *name)
fprintf(stderr, "Out of memory\n"); fprintf(stderr, "Out of memory\n");
exit(-1); exit(-1);
} }
/* FIXME: needed for proportional fonts.
offset_table = malloc(chars * sizeof(*offset_table));
if (!offset_table) {
fprintf(stderr, "Out of memory\n");
exit(-1);
}
*/
bitmap =
malloc(((fontboundingbox_width + 7) / 8) * fontboundingbox_height);
if (!bitmap) {
fprintf(stderr, "Out of memory\n");
exit(-1);
}
Header(stdout, name); Header(out, name);
scanline = -1; scanline = -1;
n = 0; n = 0;
@ -244,56 +420,90 @@ void ReadBdf(FILE * bdf, const char *name)
p = strtok(NULL, " \t\n\r"); p = strtok(NULL, " \t\n\r");
bby = atoi(p); bby = atoi(p);
} else if (!strcasecmp(s, "BITMAP")) { } else if (!strcasecmp(s, "BITMAP")) {
fprintf(stdout, "// %3d $%02x '%s'\n", encoding, encoding, fprintf(out, "// %3d $%02x '%s'\n", encoding, encoding, charname);
charname); fprintf(out, "//\twidth %d, bbx %d, bby %d, bbw %d, bbh %d\n",
fprintf(stdout, "//\twidth %d, bbx %d, bby %d, bbw %d, bbh %d\n",
width, bbx, bby, bbw, bbh); width, bbx, bby, bbw, bbh);
if (n == chars) { if (n == chars) {
fprintf(stderr, "Too many bitmaps for characters\n"); fprintf(stderr, "Too many bitmaps for characters\n");
exit(-1); exit(-1);
} }
if (width == INT_MIN) {
fprintf(stderr, "character width not specified\n");
exit(-1);
}
//
// Adjust width based on bounding box
//
if (bbx < 0) {
width -= bbx;
bbx = 0;
}
if (bbx + bbw > width) {
width = bbx + bbw;
}
if (Outline) { // Reserve space for outline border
++width;
}
width_table[n] = width; width_table[n] = width;
encoding_table[n] = encoding; encoding_table[n] = encoding;
++n; ++n;
scanline = 0; if (Outline) { // Leave first row empty
scanline = 1;
} else {
scanline = 0;
}
memset(bitmap, 0,
((fontboundingbox_width + 7) / 8) * fontboundingbox_height);
} else if (!strcasecmp(s, "ENDCHAR")) { } else if (!strcasecmp(s, "ENDCHAR")) {
if (bbx) {
RotateBitmap(bitmap, bbx, fontboundingbox_width,
fontboundingbox_height);
}
if (Outline) {
RotateBitmap(bitmap, 1, fontboundingbox_width,
fontboundingbox_height);
OutlineCharacter(bitmap, fontboundingbox_width,
fontboundingbox_height);
}
DumpCharacter(out, bitmap, fontboundingbox_width,
fontboundingbox_height);
scanline = -1; scanline = -1;
width = INT_MIN;
} else { } else {
if (scanline >= 0) { if (scanline >= 0) {
p = s; p = s;
fprintf(stdout, "\t"); j = 0;
while (*p) { while (*p) {
if (*p <= '9') { i = Hex2Int(p);
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; ++p;
if (~(p - s) & 1) { if (*p) {
fprintf(stdout, ","); i = Hex2Int(p) | i * 16;
} else {
bitmap[j + scanline * ((fontboundingbox_width +
7) / 8)] = i;
break;
} }
/* printf("%d = %d\n",
j + scanline * ((fontboundingbox_width + 7)/8), i); */
bitmap[j + scanline * ((fontboundingbox_width + 7) / 8)] =
i;
++j;
++p;
} }
if ((p - s) & 1) { // fill last nibble
fprintf(stdout, "____,");
}
fprintf(stdout, "\n");
++scanline; ++scanline;
} }
} }
} }
// Output width table for proportional font. // Output width table for proportional font.
WidthTable(stdout, name, width_table, chars); WidthTable(out, name, width_table, chars);
// FIXME: Output offset table for proportional font.
// OffsetTable(out, name, offset_table, chars);
// Output encoding table for utf-8 support // Output encoding table for utf-8 support
EncodingTable(stdout, name, encoding_table, chars); EncodingTable(out, name, encoding_table, chars);
Footer(stdout, name, fontboundingbox_width, fontboundingbox_height, chars); Footer(out, name, fontboundingbox_width, fontboundingbox_height, chars);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -316,8 +526,9 @@ void PrintUsage(void)
printf("Usage: bdf2c [OPTIONs]\n" "\t-b\tRead bdf file from stdin\n" printf("Usage: bdf2c [OPTIONs]\n" "\t-b\tRead bdf file from stdin\n"
"\t-c\tCreate font header on stdout\n" "\t-c\tCreate font header on stdout\n"
"\t-C file\tCreate font header file\n" "\t-C file\tCreate font header file\n"
"\t-n name\tName of c font variable (place it before -b)\n"); "\t-n name\tName of c font variable (place it before -b)\n"
printf("\tOnly idiots print usage on stderr\n"); "-t-O\tCreate outline for the font.\n");
printf("\n\tOnly idiots print usage on stderr\n");
} }
// //
@ -332,9 +543,9 @@ int main(int argc, char *const argv[])
// Parse arguments. // Parse arguments.
// //
for (;;) { for (;;) {
switch (getopt(argc, argv, "bcC:n:h?-")) { switch (getopt(argc, argv, "bcC:n:hO?-")) {
case 'b': case 'b':
ReadBdf(stdin, name); ReadBdf(stdin, stdout, name);
continue; continue;
case 'c': case 'c':
CreateFontHeaderFile(stdout); CreateFontHeaderFile(stdout);
@ -355,6 +566,9 @@ int main(int argc, char *const argv[])
case 'n': case 'n':
name = optarg; name = optarg;
continue; continue;
case 'O':
Outline = 1;
continue;
case EOF: case EOF:
break; break;