#!/usr/bin/perl =head1 NAME bdf2fbcon - Convert Glyph Bitmap Distribution Format fonts to Linux fbcon fonts =cut use strict; use warnings; use Getopt::Long; use constant { BDF_2_1_SECTION_NONE => 0, BDF_2_1_SECTION_PROPERTIES => 1, BDF_2_1_SECTION_CHAR => 2, }; my $VERSION; $VERSION = '0.1.0'; sub main { my %opts; my %convert_opts; my $input; my $output; $SIG{'__WARN__'} = \&warning; Getopt::Long::Configure("no_ignore_case", "bundling", "gnu_compat", "no_getopt_compat"); if (not GetOptions(\%opts, "o=s", "s=s", "h|help", "V|version", )) { usage(*STDERR); exit(4); } if (exists($opts{'h'})) { help(*STDOUT); exit(0); } if (exists($opts{'V'})) { version(*STDOUT); exit(0); } if (exists($opts{'s'})) { $convert_opts{'w'} = $convert_opts{'h'} = $opts{'s'}; $convert_opts{'w'} =~ s/x.*//; $convert_opts{'h'} =~ s/.*x//; } if ($#ARGV lt 0) { error(4, "No input files\n"); } if (exists($opts{'o'})) { if ($#ARGV gt 0) { error(4, "Cannot specify -o with multiple files\n"); } convert($ARGV[0], $opts{'o'}, %convert_opts); } else { for $input (@ARGV) { $output = $input; $output =~ s/\.bdf$/.c/; convert($input, $output, %convert_opts); } } } sub usage { my ($fh) = @_; printf($fh "Usage: %s [-o ] ...\n", $0); } sub help { my ($fh) = @_; usage($fh); print($fh "Options:\n"); print($fh " -o Place the output into \n"); print($fh " -s x Override the font size\n"); print($fh " -h, --help Display this information\n"); print($fh " -V, --version Display version information\n"); } sub version { my ($fh) = @_; printf($fh "bdf2fbcon %s\n", $VERSION); print($fh "Copyright (C) 2013, 2014 Patrick \"P. J.\" McDermott\n"); print($fh "License GPLv3+: GNU GPL version 3 or later " . ".\n"); print($fh "This is free software: you are free to change and " . "redistribute it.\n"); print($fh "There is NO WARRANTY, to the extent permitted by law.\n"); } sub warning { my ($fmt, @args) = @_; printf(STDERR "bdf2fbcon: Warning: " . $fmt . "\n", @args); } sub error { my ($status, $fmt, @args) = @_; printf(STDERR "bdf2fbcon: Error: " . $fmt . "\n", @args); exit($status); } sub convert { my ($input, $output, %opts) = @_; my $input_fh; my $output_fh; my $line; if ($input eq $output and $input ne "-") { warning("Input and output files are equal"); } if ($input eq "-") { $input_fh = *STDIN; } else { if (not open($input_fh, "<", $input)) { error(4, "%s: %s", $input, $!); } } if ($output eq "-") { $output_fh = *STDOUT; } else { if (not open($output_fh, ">", $output . "~")) { error(4, "%s: %s", $output . "~", $!); } } $line = readline($input_fh); if ($line =~ m/^STARTFONT 2.[12]$/) { convert_bdf_2_1($input_fh, $output_fh, %opts); } else { error(4, "Unsupported input format"); } if ($input ne "-") { close($input_fh); } if ($output ne "-") { close($output_fh); if (not rename($output . "~", $output)) { error(4, "%s: %s", $output, $!); } } } sub convert_bdf_2_1 { my ($input_fh, $output_fh, %opts) = @_; my $font_w; my $font_h; my $section; my $found_end; my $line; my $stmt; my $arg; my @argv; my $font_idx; my $font_name; $font_w = $opts{'w'} if (exists($opts{'w'})); $font_h = $opts{'h'} if (exists($opts{'h'})); $section = BDF_2_1_SECTION_NONE; $found_end = 0; while ($line = readline($input_fh)) { chomp($line); ($stmt, $arg) = split(/[ \t]+/, $line, 2); $arg =~ s/^"(.*)"$/$1/ if ($arg); ($stmt, @argv) = split(/[ \t]+/, $line); if ($section == BDF_2_1_SECTION_NONE) { if ($stmt eq 'FONTBOUNDINGBOX') { $font_w = $argv[0] unless ($font_w); $font_h = $argv[1] unless ($font_h); } elsif ($stmt eq 'COMMENT') { printf($output_fh "/* %s */\n", $arg); } elsif ($stmt eq 'STARTPROPERTIES') { print($output_fh "/* Generated by bdf2fbcon */\n\n"); print($output_fh "#include \n\n"); $section = BDF_2_1_SECTION_PROPERTIES; } elsif ($stmt eq 'CHARS') { # XXX printf($output_fh "#define FONTDATAMAX %d\n\n", 0); printf($output_fh "static const unsigned char" . " fontdata_%s[FONTDATAMAX] = {\n", $font_name); } elsif ($stmt eq 'STARTCHAR') { $section = BDF_2_1_SECTION_CHAR; } elsif ($stmt eq 'ENDFONT') { $found_end = 1; last; } } elsif ($section == BDF_2_1_SECTION_PROPERTIES) { if ($stmt eq 'FONT_NAME') { $font_idx = uc($arg); $font_idx =~ s/[^A-Z0-9_]//g; $font_name = lc($arg); $font_name =~ s/[^a-z0-9_]/_/g; } elsif ($stmt eq 'ENDPROPERTIES') { $section = BDF_2_1_SECTION_NONE; } } elsif ($section == BDF_2_1_SECTION_CHAR) { if ($stmt eq 'ENDCHAR') { $section = BDF_2_1_SECTION_NONE; } } } warning("Missing end of font") unless ($found_end); printf($output_fh "\n};\n\n"); printf($output_fh "const struct font_desc font_%s = {\n", $font_name); printf($output_fh "\t.idx\t= %s_IDX,\n", $font_idx); printf($output_fh "\t.name\t= \"%s\",\n", $font_idx); printf($output_fh "\t.width\t= %d,\n", $font_w); printf($output_fh "\t.height\t= %d,\n", $font_h); printf($output_fh "\t.data\t= fontdata_%s,\n", $font_name); # XXX printf($output_fh "\t.pref\t= ???,\n"); printf($output_fh "};\n"); } main(); __END__ =head1 SYNOPSIS B [B<-o> I] [B<-s> IxI] I ... =head1 DESCRIPTION B converts Glyph Bitmap Distribution Format fonts to Linux fbcon fonts. =head1 OPTIONS =over 4 =item B<-o> I Place the output into I. =item B<-s> IxI Override the font size. =item B<-h>, B<--help> Display help information. =item B<-V>, B<--version> Display version information. =back =head1 COPYRIGHT Copyright (C) 2013, 2014 Patrick "P. J." McDermott This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =cut