#! /usr/bin/perl # Title: HACKOS2.BAT # Author: M. Hosken # Description: # 1.001 MJPH 05-AUG-1997 Fix &makestr() to work properly # 1.002 MJPH 06-AUG-1997 Add -d & -q support # 1.1 MJPH 22-MAR-1998 Add -f support # 1.2 MJPH 11-JUN-1999 Add -t support # 1.3 MJPH 9-AUG-1999 Fix -d glob # 1.4 MJPH 17-FEB-2000 Fix typo for type 1 tables # 1.5 MJPH 19-SEP-2000 Add -n, -x # 1.6 MJPH 10-NOV-2000 Add -v # 1.7 RMH 2-Dec-2003 Add -w # 1.7.1 MJPH 27-APR-2006 Add docs for man pages, up version report # 1.8 MJPH 8-NOV-2007 Support v3 OS/2 tables and some handling of those beyond use Getopt::Std; require 'ttfmod.pl'; getopts("c:d:f:n:p:qt:u:v:x:w:"); if ((defined $opt_d && !defined $ARGV[0]) || (!defined $opt_d && !defined $ARGV[1])) { die 'HACKOS2 [-c hex] [-d directory] [-f fsSelection] [-p hex] [-q] [-t num] [-u hex] [-w width] v1.8, 8-NOV-2007 (c) martin_hosken@sil.org Hacks the OS/2 table of a ttf file copying from infile to outfile. -c change codepage information (a 64 bit hex number) -d specifies output directory for processing multiple files. In which case is not used and may be a list including wildcards. -f fsSelection value (16 bit hex) (e.g. 4240 for Thai fonts) -n sets usFirstCharIndex given a hex value -p change panose info (10 bytes of hex in reverse order: 0A090807060504030201) -q Quiet mode (do not list names as they are processed) -t Sets fsType (embedding) information (decimal) -u change unicode info (a 128 bit hex number) -v sets vendor tag to the first 4 chars of the string -w set average char width (decimal) -x sets usLastCharIndex given a hex value For example, to convert a Win3.1 ANSI font to Win95 use the following: hackos2 -c01 -u03 old.ttf new.ttf or for a Symbol font use: hackos2 -c80000000 -u0 old.ttf new.ttf Or to revert: hackos2 -cnone other.ttf new.ttf '; } $old = select(STDERR); $| = 1; select($old); if ($opt_c =~ m/^none/oi) { undef $opt_c; $revert = 1; } else { $revert = 0; } $fns{"OS/2"} = "hackos2"; if (defined $opt_d) { foreach $a (@ARGV) { foreach $f (glob($a)) { print STDERR "$f -> $opt_d/$f\n" unless (defined $opt_q); &ttfmod($f, "$opt_d/$f", *fns); } } } else { &ttfmod($ARGV[0], $ARGV[1], *fns); } sub hackos2 { local(*INFILE, *OUTFILE, $len) = @_; local($csum); read(INFILE, $dat, 78); $ver = unpack("n", substr($dat, 0, 2)); if ($revert) { if ($ver == 1) { substr($dat, 0, 2) = pack("n", 0); $len = 78; } } else { if ($ver == 2) { read(INFILE, $dat1, 8); $dat .= $dat1; } elsif ($ver == 1 || defined $opt_c) { substr($dat, 0, 2) = pack("n", 1); $dat .= pack("x8", 0); $len = 86; } else { read(INFILE, $dat1, 18); $dat .= $dat1; $len = 96; if ($ver > 3) { print "Warning, version of OS/2 table too recent. Reverting it to v3\n"; substr($dat, 0, 2) = pack('n', 3); } } } if (defined $opt_c) { substr($dat, 78, 8) = &makestr($opt_c, 8, 4); } # pack("NN", unpack("LL", &makestr($opt_c, 8))); } if (defined $opt_p) { substr($dat, 32, 10) = &makestr($opt_p, 10, 1); } if (defined $opt_u) { substr($dat, 42, 16) = &makestr($opt_u, 16, 4); } # pack("NNNN", unpack("LLLL", &makestr($opt_u, 16))); } if (defined $opt_f) { substr($dat, 62, 2) = &makestr($opt_f, 2, 2); } if (defined $opt_t) { substr($dat, 8, 2) = pack("n", $opt_t); } if (defined $opt_n) { substr($dat, 64, 2) = &makestr($opt_n, 2, 2); } if (defined $opt_x) { substr($dat, 66, 2) = &makestr($opt_x, 2, 2); } if (defined $opt_v) { substr($dat, 58, 4) = pack("A4", $opt_v); } if (defined $opt_w) { substr($dat, 2, 2) = pack("n", $opt_w); } $csum = unpack("%32N", $dat); print OUTFILE $dat; ($len, $csum); } # &makestr($string, $number_of_bytes, $granule) # converts $string as a big hex number into a packed string no longer than # $number_of_bytes long. The string is then swapped on the $granule byte # boundary so that the least significant bundle comes first. This is unless # $granule is 0 or -ve. # # returns its string in Network order. sub makestr { local($str, $len, $group) = @_; local($res, $have, $temp); $have = length($str); if ($have % 2) { $str = "0" . $str; $have++; } $have >>= 1; $have = $len if ($have > $len); $res = "\000" x ($len - $have); for ($i = 0; $i < $have; $i++) { $res .= pack("C", hex(substr($str, $i << 1, 2))); } if ($group > 0) { $temp = ""; for ($i = 0; $i < $len / $group; $i++) { $temp = substr($res, $i * $group, $group) . $temp; } $res = $temp; } ($res); } __END__ =head1 TITLE hackos2 - edit the OS/2 table in a TrueType Font =head1 SYNOPSIS HACKOS2 [-c hex] [-d directory] [-f fsSelection] [-p hex] [-q] [-t num] [-u hex] [-w width] =head1 OPTIONS Hacks the OS/2 table of a ttf file copying from infile to outfile. -c change codepage information (a 64 bit hex number) -d specifies output directory for processing multiple files. In which case is not used and may be a list including wildcards. -f fsSelection value (16 bit hex) (e.g. 4240 for Thai fonts) -n sets usFirstCharIndex given a hex value -p change panose info (10 bytes of hex in reverse order: 0A090807060504030201) -q Quiet mode (do not list names as they are processed) -t Sets fsType (embedding) information (decimal) -u change unicode info (a 128 bit hex number) -v sets vendor tag to the first 4 chars of the string -w set average char width (decimal) -x sets usLastCharIndex given a hex value For example, to convert a Win3.1 ANSI font to Win95 use the following: hackos2 -c01 -u03 old.ttf new.ttf or for a Symbol font use: hackos2 -c80000000 -u0 old.ttf new.ttf Or to revert: hackos2 -cnone other.ttf new.ttf =cut