61307cd85fd4311b5806688e96762126521f852e
[bertos.git] / fonts / convbdf
1 #! /usr/bin/perl -w
2 #
3 # Convert BDF files to nano-X font files
4 # modified by G Haerr from bdftobogl for 16 bit MWIMAGEBITS
5 # modified on 2/10/00 by K Harris to accept any size input character
6 # modified on 3/26/00 by G Haerr added ascent field, fixed $IMAGE_BITS
7 # modified on 2/15/06 by <bernie@develer.com> for DevLib.
8 # originally from BOGL - Ben's Own Graphics Library <pfaffben@debian.org>.
9 #
10
11 use POSIX;
12
13 if ($#ARGV < 0) {
14         print "Usage: convbdf font.bdf > font.c\n";
15         exit -1;
16 }
17
18 $LAST_CHAR = 0xff;
19 $IMAGE_BITS = 8;
20 $IMAGE_NIBBLES = $IMAGE_BITS/4;
21 $IMAGE_MASK = 0xff;
22 $IMAGE_VERTICAL = 1;
23
24 $file = $ARGV[0];
25
26 $font = $file;
27 $font =~ s#.*/##; # remove path name
28 $font =~ s/\.bdf//;
29 $font =~ tr/a-zA-Z0-9_/_/cs;
30
31 print "/* Generated by convbdf on ", substr(`date`, 0, -1), ". */\n";
32 print "#include <gfx/font.h>\n\n";
33
34 open BDF, "<$file" || die;
35 while (<BDF>) {
36         chop;
37         $pixel_size = $1 if /^PIXEL_SIZE (\d+)$/;
38         $font_ascent = $1 if /^FONT_ASCENT (\d+)$/;
39         $font_descent = $1 if /^FONT_DESCENT (\d+)$/;
40         $font_name = $1 if /^FONT (.*)$/;
41         $default_char = $1 if /^DEFAULT_CHAR (\d+)$/;
42
43         last if /^CHARS /;
44 }
45
46 print "/* Font information:\n\n";
47 print "   name: $font_name\n";
48 print "   pixel size: $pixel_size\n";
49 print "   ascent: $font_ascent\n";
50 print "   descent: $font_descent\n";
51 print "*/\n\n";
52
53 print "/* Font character bitmap data. */\n";
54 print "static const PROGMEM uint8_t font_${font}_glyphs[] = {\n";
55
56 $ch_height = $font_ascent + $font_descent;
57 $ofs = 0;
58 $maxwidth = 0;
59 $proportional = 0;
60 $firstchar = -1;
61 while (<BDF>) {
62         chop;
63         undef $encoding, undef $width, undef $bbx, undef $bby, undef $bbw, undef $bbh if /^STARTCHAR /;
64         $encoding = $1 if /^ENCODING (\d+)/;
65         last if defined $encoding && $encoding > $LAST_CHAR;
66         $width = $1 if /^DWIDTH (-?\d+)/;
67         ($bbw, $bbh, $bbx, $bby) = ($1, $2, $3, $4) if /^BBX (-?\d+) (-?\d+) (-?\d+) (-?\d+)/;
68
69         if (/^BITMAP$/) {
70                 next if !defined $encoding;
71                 $firstchar = $encoding if $firstchar < 0;
72                 $encoding_tab[$encoding] = $ofs;
73                 $width -= $bbx, $bbx = 0 if $bbx < 0;
74                 $width[$encoding] = $width;
75                 $maxwidth != 0 and $width != $maxwidth and $proportional = 1;
76                 $maxwidth = $width if $width > $maxwidth;
77                 $ch_words  = int (($width+$IMAGE_BITS-1)/$IMAGE_BITS);
78                 $ch_bits   = $ch_words*$IMAGE_BITS;
79                 for (my $i = 0; $i < $ch_height; $i++) {
80                         for (my $k = 0; $k < $ch_words; $k++) {
81                                 $bm[$i][$k] = 0;
82                         }
83                 }
84                 for (my $i = 0; ; $i++) {
85                         $_ = <BDF>;
86                         chop;
87                         last if /^ENDCHAR$/;
88
89                         @hexnibbles = split //,$_;
90                         for (my $k=0; $k<$ch_words; $k++) {
91                                 $ndx = $k*$IMAGE_NIBBLES;
92                                 $padnibbles = @hexnibbles - $ndx;
93                                 # if bbx pushes bits into next word
94                                 # and no more bits from bdf file
95                                 last if $padnibbles <= 0;
96                                 $padnibbles = 0 if $padnibbles >= $IMAGE_NIBBLES;
97                                 $value = hex join '',@hexnibbles[$ndx..($ndx+$IMAGE_NIBBLES-1-$padnibbles)];
98                                 $value = $value << ($padnibbles*$IMAGE_NIBBLES);        
99                                 $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k] |= 
100                                         $value >> ($bbx);       
101                                 if ($bbx) {     # handle overflow into next image_word
102                                         $bm[$ch_height - $font_descent - $bby - $bbh + $i][$k+1] =
103                                                 ($value << ($IMAGE_BITS - $bbx)) & $IMAGE_MASK; 
104                                 }
105                         }
106                 }
107
108                 # GLYPH PREVIEW
109 ###             printf "\n/* Character %c (0x%02x): ", $encoding, $encoding;
110                 printf "\n/* Character (0x%02x): ", $encoding;
111                 print "bbw=$bbw, bbh=$bbh, bbx=$bbx, bby=$bby, width=$width */\n";
112         
113                 # GLYPH DATA
114                 if ($IMAGE_VERTICAL) {
115                         my $bitstring = "";
116                         for (my $k = 0; $k < int(($ch_height + $IMAGE_BITS - 1) / $IMAGE_BITS); $k++) {
117                                 for (my $x = 0; $x < $width; $x++) {
118                                         my $v = 0;
119                                         for (my $y = 0; $y < $IMAGE_BITS && ($y + $k * $IMAGE_BITS < $ch_height); ++$y) {
120                                                 my $bit = ($bm[$k * $IMAGE_BITS + $y][int($x / $IMAGE_BITS)] & (1 << ($IMAGE_BITS - ($x % $IMAGE_BITS) - 1))) ? 1 : 0;
121                                                 $bitstring .= $bit ? '*' : ' ';
122                                                 $v |= $bit << $y;
123                                         }
124                                         $ofs++;
125                                         printf "0x%02x, ", $v;
126                                 }
127                                 # Preview
128                                 printf "/* $bitstring */\n";
129                         }
130                         
131                 }
132                 else { # IMAGE_HORIZONTAL
133
134                         # Preview
135                         print "   +", ("-" x $ch_bits), "+\n";
136                         for (my $i = 0; $i < $ch_height; $i++) {
137                                 print "   |";
138                                 for (my $k = 0; $k < $ch_words; $k++) {
139                                         for (my $j = $IMAGE_BITS - 1; $j >= 0; $j--) {
140                                                 print $bm[$i][$k] & (1 << $j) ? "*" : " ";
141                                         }
142                                 }
143                                 print "|\n";
144                         }
145                         print "   +", ("-" x $ch_bits), "+ */\n";
146
147                         for (my $i = 0; $i < $ch_height; $i++) {
148                                 for (my $k=0; $k<$ch_words; $k++) {
149                                         $ofs++;
150                                         printf "0x%02x, ", $bm[$i][$k];
151                                 }
152                                 printf "\n";
153                         }
154                 }
155    }
156 }
157
158 print "};\n\n";
159
160 #print STDERR "Maximum character width=$maxwidth\n";
161
162 if ($proportional) {
163         print "/* Character->glyph data. */\n";
164         print "static const PROGMEM uint16_t ${font}_offset[] = {\n";
165         for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) {
166                 my $char = $i;
167                 my $ofs = $encoding_tab[$i];
168                 $ofs = $encoding_tab[$default_char], $char = $default_char if !defined $ofs;
169                 ### printf "  $ofs,\t/* %c (0x%02x) */\n", $char, $i;
170                 printf "  $ofs,\t/* (0x%02x) */\n", $i;
171         }
172         print "};\n\n";
173
174         print "/* Character width data. */\n";
175         print "static const PROGMEM uint8_t ${font}_width[] = {\n";
176         for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) {
177                 my $char = $i;
178                 my $width = $width[$i];
179                 $width = $width[$default_char], $char = $default_char if !defined $encoding_tab[$i];
180                 ### printf "  $width,\t/* %c (0x%02x) */\n", $char, $i;
181                 printf "  $width,\t/* (0x%02x) */\n", $i;
182         }
183         print "};\n\n";
184
185         $font_offset = "${font}_offset";
186         $font_width = "${font}_width";
187 } else {
188         $font_offset = "NULL";
189         $font_width = "NULL";
190 }
191
192 $lastchar = $LAST_CHAR;
193 #$size = $lastchar - $firstchar + 1;
194
195 print <<EOF
196 /* Font structure definition. */
197 EXTERN_CONST Font font_${font} =
198 {
199         /* .glyph  = */ font_${font}_glyphs,
200         /* .name   =    "$font", */
201         /* .width  = */ $maxwidth,
202         /* .height = */ $ch_height,
203         /* .ascent =    $font_ascent, */
204         /* .first  = */ $firstchar,
205         /* .last   = */ $lastchar,
206         /* .offset = */ $font_offset,
207         /* .width  = */ $font_width,
208 };
209 EOF