#!/usr/bin/perl
use warnings;
use strict;

my %bitno = (0 => 0);
for (0 .. 31) {
    $bitno{1 << $_} = $_;
}

my $last_ch = -1;
open U, '<', '/usr/share/unifont/unifont.hex' or die $!;
open O, '>', 'unifont.pixelfont' or die $!;
while (<U>) {
    my ($ch, $hex) = /^([[:xdigit:]]+):([[:xdigit:]]+)$/;
    if (!defined $ch) {
	print "Bad line: $_";
	next;
    }
    $ch = hex($ch);
    if ($ch == 256) {
	close O;
	open O, '<', 'unifont.pixelfont' or die $!;
	open P, '>', 'preload_font.h' or die $!;
	print P "static const unsigned char fontdata_preloaded[] = {";
	my $c = 0;
	while (<O>) {
	    for (split //, $_) {
		if ($c++ % 8 == 0) {
		    print P "\n   ";
		}
		printf P "% 4d,", ord $_;
	    }
	}
	print P "\n};\n";
	close P;
	close O;
	open O, '>', 'unifont.pixelfont' or die $!;
    }

    while (++$last_ch < $ch) {
	# print "Missing entry for ".($last_ch - 1 )."\n";
	print O pack 'C', 0x00;
    }

    # $len is 0, 2 or 4
    my $len = length($hex) / 16;
    my $packcode;
    if ($len == 4) {
	$packcode = 'n';
    } elsif ($len == 2) {
	$packcode = 'C';
    } elsif ($len == 0) {
	$packcode = '';
    } else {
	die "No handling for len = $len\n";
    }
    my $data = '';
    my $start;
    my $n = 0;
    my $pixels_set = 0;
    my $width = $len * 4;
    if ($len) {
	my @data = ();
	for (0 .. 15) {
	    my $c = substr($hex, (15 - $_) * $len, $len);
	    my $row = hex($c);
	    $pixels_set |= $row;
	    if (!defined $start) {
		# Skip blank rows at the bottom.
		next unless $row;
		$start = $_;
	    }
	    $n = $_ if $row;
	    push @data, $row;

#	my $b = sprintf $fmt, $row;
#	$b =~ y/01/ @/;
#	print "\t$b\n";
	}

	my $left_gap = 0;
	my $lsb_used = $pixels_set & -$pixels_set;
	my $msb_used = 1 << ($len * 4 - 1);
	while ($msb_used > $pixels_set) {
	    $msb_used >>= 1;
	    ++$left_gap;
	}
	$data = join '', map {pack($packcode, $_ << $left_gap)} @data;
	my $right_gap = $bitno{$lsb_used} + $left_gap;
	$right_gap = 0 if ($left_gap == 16);
	$width -= $right_gap;
    } else {
	$width -= 2;
    }

    if (!defined $start) {
	# No set pixels.
	print O pack 'C', ($len * 4 - 4);
	die "not really empty!" unless $hex =~ /^0*$/;
    } else {
	die "really empty!" if $hex =~ /^0*$/;
	$n = $n + 1 - $start;
	print O pack 'C', (($len / 2) << 6) | $width;
	print O pack 'C', ($start << 4) | ($n - 1);
	die "too little data (".length($data)." < ".$n."*".($len/2).")" if length($data) < $n * $len/2;
	print O substr($data, 0, $n * $len / 2);
    }
}
close O or die $!;
