#! /usr/bin/perl -w # # This script creates virtual subfonts in a font encoding given by a subfont # definition file, based on Unicode subfonts. # # As prerequisites, it needs the programs `tftopl' and `vptovf' which must # be in the path. # # Call the script as # # perl uni2sfd.pl uni-namestem sfd-file namestem codingscheme # # `uni-namestem' is the namestem of the Unicode subfonts; `uni2sfd.pl' # appends the Unicode suffixes and reads the corresponding TFM files. # `sfd-file' is the subfont definition file which maps Unicode input # characters to the target subfont scheme using `namestem' as the namestem. # `codingscheme' gives the value for the CODINGSCHEME parameter in the # VF files (always converted to uppercase). # # Example: # # perl uni2sfd.pl bsmiu UBig5.sfd bsmilp cjkbig5 # # A collection of useful subfont definition files for CJK fonts can be found # in the ttf2pk package. # Copyright (C) 1994-2021 Werner Lemberg # # 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 2 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 in doc/COPYING; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301 USA use strict; my $prog = $0; $prog =~ s@.*/@@; if ($#ARGV != 3) { die("usage: $prog uni-namestem sfd-file namestem codingscheme\n"); } my $uninamestem = $ARGV[0]; my $sfdfile = $ARGV[1]; my $namestem = $ARGV[2]; my $codingscheme = $ARGV[3]; # Read subfont definition file. my %sfd; my @subfonts; read_sfdfile($sfdfile, \%sfd, \@subfonts); # Read TFM files. my @unimetrics; foreach my $sub (0 .. 0xFF) { my $suffix = sprintf("%02x", $sub); my $tfmname = "$uninamestem$suffix.tfm"; if (-f $tfmname) { read_tfmfile($tfmname, \@unimetrics, $suffix); } } # Write VPL files. foreach my $sub (@subfonts) { my @entries; foreach my $i (0 .. 255) { if (defined ($sfd{"$sub $i"})) { my $index = $sfd{"$sub $i"}; if (defined ($unimetrics[$index])) { push(@entries, "$i $index $unimetrics[$index]"); } } } if ($#entries >= 0) { write_vplfile("$namestem$sub.vpl", \@entries); } } # Generate VF and TFM files, then remove the VPL files. my @vplfiles = glob("$namestem*.vpl"); foreach my $vplfile (@vplfiles) { print("Processing \`$vplfile'...\n"); my $arg = "vptovf $vplfile"; system($arg) == 0 || die("$prog: calling \`$arg' failed: $?\n"); print("Removing \`$vplfile'...\n"); unlink($vplfile); } # Read an SFD file. # # $1: Name of the SFD file. # $2: Reference to the target hash file, mapping from the character code # to the subfont index. The format of the key value is the # concatenation of the subfont suffix, a space, and the index. # $3: Reference to a target array which holds the subfont suffixes. sub read_sfdfile { my ($sfdfile, $sfdhash, $sfdarray) = @_; print("Reading subfont definition file \`$sfdfile'...\n"); open(SFD, $sfdfile) || die("$prog: can't open \`$sfdfile': $!\n"); my $line; my $continuation = 0; while () { chop; next if /^\s*$/; next if /^#/; if ($continuation) { $line .= $_; } else { $line = $_; } $continuation = 0; if ($line =~ s/\\$//) { $continuation = 1; next; } $_ = $line; my @field = split(" "); my $suffix = $field[0]; push(@{$sfdarray}, $suffix); shift(@field); my $index = 0; while (@field) { if ($field[0] =~ /(.*):$/) { $index = $1; } elsif ($field[0] =~ /(.*)_(.*)/) { my $start = $1; my $end = $2; $start = oct($start) if ($start =~ /^0/); $end = oct($end) if ($end =~ /^0/); foreach my $i ($start .. $end) { $sfdhash->{"$suffix $index"} = $i; $index++; } } else { my $value = $field[0]; $value = oct($value) if ($value =~ /^0/); $sfdhash->{"$suffix $index"} = $value; $index++; } shift(@field); } } close(SFD); } # Read TFM file. # # $1: Name of the TFM file. # $2: Reference to the target array holding metric information in the form # ` '. # $3: Subfont suffix. sub read_tfmfile { my ($tfmfile, $unicarray, $suffix) = @_; print("Processing metrics file \`$tfmfile'...\n"); my $arg = "tftopl $tfmfile > $tfmfile.pl"; system($arg) == 0 || die("$prog: calling \`$arg' failed: $?\n"); print("Reading property list file \`$tfmfile.pl'...\n"); open(PL, "$tfmfile.pl") || die("$prog: can't open \`$tfmfile.pl': $!\n"); while () { my $idx; if (/^\(CHARACTER O (\d+)/) { $idx = oct($1); } elsif (/^\(CHARACTER C (.)/) { $idx = ord($1); } else { next; } $idx += hex($suffix) * 256; my $wd = "0"; my $ht = "0"; my $dp = "0"; $_ = ; if (/\(CHARWD R (.*)\)/) { $wd = "$1"; $_ = ; } if (/\(CHARHT R (.*)\)/) { $ht = "$1"; $_ = ; } if (/\(CHARDP R (.*)\)/) { $dp = "$1"; } $unicarray->[$idx] = "$wd $ht $dp"; } close(PL); print("Removing \`$tfmfile.pl'...\n"); unlink("$tfmfile.pl"); } # Write VPL file. # # $1: Name of the VPL file. # $2: Reference to list which holds the font entries. An entry has the # form ` '. sub write_vplfile { my ($vplfile, $glypharray) = @_; my %subfonts; my $subcount = 0; foreach my $entry (@{$glypharray}) { my @field = split(" ", $entry); my $subfont = int($field[1] / 256); if (!defined ($subfonts{$subfont})) { $subfonts{$subfont} = $subcount; $subcount++; } } print("Writing virtual property list file \`$vplfile'...\n"); open(VPL, ">", $vplfile) || die("$prog: can't open \`$vplfile': $!\n"); my $oldfh = select(VPL); print("(VTITLE Created by \`$prog " . join(" ", @ARGV) . "')\n"); print("(FAMILY TEX-\U$namestem\E)\n"); print("(CODINGSCHEME \U$codingscheme\E)\n"); print("(FONTDIMEN\n"); print(" (SPACE R 0.5)\n"); print(" (XHEIGHT R 0.4)\n"); print(" (QUAD R 1)\n"); print(" )\n"); foreach my $subfont (sort { $subfonts{$a} <=> $subfonts{$b} } keys %subfonts) { print("(MAPFONT D $subfonts{$subfont}\n"); print(" (FONTNAME $uninamestem" . sprintf("%02x", $subfont) . ")\n"); print(" )\n"); } foreach my $entry (@{$glypharray}) { my @field = split(" ", $entry); my $index = $field[0]; my $subnumber = $subfonts{int($field[1] / 256)}; my $subindex = $field[1] % 256; my $width = $field[2]; my $height = $field[3]; my $depth = $field[4]; print("(CHARACTER D $index\n"); print(" (CHARWD R $width)\n"); print(" (CHARHT R $height)\n"); print(" (CHARDP R $depth)\n"); print(" (MAP\n"); print(" (SELECTFONT D $subnumber)\n"); print(" (SETCHAR D $subindex)\n"); print(" )\n"); print(" )\n"); } close(VPL); select($oldfh); } # eof