#! /usr/bin/perl -w
#
# Convert BDF files to nano-X font files
# modified by G Haerr from bdftobogl for 16 bit MWIMAGEBITS
# modified on 2/10/00 by K Harris to accept any size input character
# modified on 3/26/00 by G Haerr added ascent field, fixed $IMAGE_BITS
# originally from BOGL - Ben's Own Graphics Library <pfaffben@debian.org>.
#

use POSIX;

if ($#ARGV < 0) {
    print "Usage: convbdf font.bdf > font.c\n";
    exit -1;
}

$LAST_CHAR = 0x7e;
$IMAGE_BITS = 16;
$IMAGE_NIBBLES = $IMAGE_BITS/4;
$IMAGE_MASK = 0xffff;

$file = $ARGV[0];

$font = $file;
$font =~ s/\.bdf//;
$font =~ tr/a-zA-Z0-9_/_/cs;

print "/* Generated by convbdf on ", substr(`date`, 0, -1), ". */\n";
print "#include \"device.h\"\n\n";

open BDF, "<$file" || die;
while (<BDF>) {
    chop;
    $pixel_size = $1 if /^PIXEL_SIZE (\d+)$/;
    $font_ascent = $1 if /^FONT_ASCENT (\d+)$/;
    $font_descent = $1 if /^FONT_DESCENT (\d+)$/;
    $font_name = $1 if /^FONT (.*)$/;
    $default_char = $1 if /^DEFAULT_CHAR (\d+)$/;
    
    last if /^CHARS /;
}

print "/* Font information:\n\n";
print "   name: $font_name\n";
print "   pixel size: $pixel_size\n";
print "   ascent: $font_ascent\n";
print "   descent: $font_descent\n";
print "*/\n\n";

print "/* Font character bitmap data. */\n";
print "static MWIMAGEBITS ${font}_bits[] = {\n";

$ch_height = $font_ascent + $font_descent;
$ofs = 0;
$maxwidth = 0;
$firstchar = -1;
while (<BDF>) {
    chop;
    undef $encoding, undef $width, undef $bbx, undef $bby, undef $bbw, undef $bbh if /^STARTCHAR /;
    $encoding = $1 if /^ENCODING (\d+)/;
	 last if defined $encoding && $encoding > $LAST_CHAR;
    $width = $1 if /^DWIDTH (-?\d+)/;
    ($bbw, $bbh, $bbx, $bby) = ($1, $2, $3, $4) if /^BBX (-?\d+) (-?\d+) (-?\d+) (-?\d+)/;

   if (/^BITMAP$/) {
		next if !defined $encoding;
		$firstchar = $encoding if $firstchar < 0;
		$encoding_tab[$encoding] = $ofs;
		$width -= $bbx, $bbx = 0 if $bbx < 0;
		$width[$encoding] = $width;
		$maxwidth = $width if $width > $maxwidth;
		$ch_words  = int (($width+$IMAGE_BITS-1)/$IMAGE_BITS);
		$ch_bits   = $ch_words*$IMAGE_BITS;
		for (my $i = 0; $i < $ch_height; $i++) {
			for (my $k = 0; $k < $ch_words; $k++) {
	    		$bm[$i][$k] = 0;
			}
		}
		for (my $i = 0; ; $i++) {
	    	$_ = <BDF>;
	    	chop;
	    	last if /^ENDCHAR$/;
		
		   @hexnibbles = split //,$_;
			for (my $k=0; $k<$ch_words; $k++) {
			   $ndx = $k*$IMAGE_NIBBLES;
				$padnibbles = @hexnibbles - $ndx;
				last if $padnibbles <= 0; # if bbx pushes bits into next word
												 # and no more bits from bdf file
				$padnibbles = 0 if $padnibbles >= $IMAGE_NIBBLES;
			   $value = hex join '',@hexnibbles[$ndx..($ndx+$IMAGE_NIBBLES-1-$padnibbles)];
	   		$value = $value << ($padnibbles*$IMAGE_NIBBLES);	
	   		$bm[$ch_height - $font_descent - $bby - $bbh + $i][$k] |= 
						$value >> ($bbx);	
				if ($bbx) {	# handle overflow into next image_word
	   			$bm[$ch_height - $font_descent - $bby - $bbh + $i][$k+1] =
						($value << ($IMAGE_BITS - $bbx)) & $IMAGE_MASK;	
				}
			}
		}
	
###		printf "\n/* Character %c (0x%02x):\n", $encoding, $encoding;
		printf "\n/* Character (0x%02x):\n", $encoding;
		print "   bbw=$bbw, bbh=$bbh, bbx=$bbx, bby=$bby, width=$width\n";
		print "   +", ("-" x $ch_bits), "+\n";
		for (my $i = 0; $i < $ch_height; $i++) {
			print "   |";
			for (my $k = 0; $k < $ch_words; $k++) {
	   		for (my $j = $IMAGE_BITS - 1; $j >= 0; $j--) {
					print $bm[$i][$k] & (1 << $j) ? "*" : " ";
	   		}
			}
	   	print "|\n";
		}
		print "   +", ("-" x $ch_bits), "+ */\n";
	
		for (my $i = 0; $i < $ch_height; $i++) {
			for ($k=0; $k<$ch_words; $k++) {
   			$ofs++;
	   		printf "0x%04x, ", $bm[$i][$k];
			}
	   	printf "\n";
		}
   }
}

print "};\n\n";

#print STDERR "Maximum character width=$maxwidth\n";

print "/* Character->glyph data. */\n";
print "static unsigned short ${font}_offset[] = {\n";
for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) {
    my $char = $i;
    my $ofs = $encoding_tab[$i];
    $ofs = $encoding_tab[$default_char], $char = $default_char if !defined $ofs;
### printf "  $ofs,\t/* %c (0x%02x) */\n", $char, $i;
    printf "  $ofs,\t/* (0x%02x) */\n", $i;
}
print "};\n\n";

print "/* Character width data. */\n";
print "static unsigned char ${font}_width[] = {\n";
for (my $i = $firstchar; $i <= $LAST_CHAR; $i++) {
    my $char = $i;
    my $width = $width[$i];
    $width = $width[$default_char], $char = $default_char if !defined $encoding_tab[$i];
### printf "  $width,\t/* %c (0x%02x) */\n", $char, $i;
    printf "  $width,\t/* (0x%02x) */\n", $i;
}
print "};\n\n";

$size = $LAST_CHAR - $firstchar + 1;

print "/* Exported structure definition. */\n";
print "MWCFONT font_${font} = {\n";
print "  \"$font\",\n";
print "  $maxwidth,\n";
print "  $ch_height,\n";
print "  $font_ascent,\n";
print "  $firstchar,\n";
print "  $size,\n";
print "  ${font}_bits,\n";
print "  ${font}_offset,\n";
print "  ${font}_width,\n";
print "};\n";
