1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#! /usr/local/bin/perl
#
# Usage: enc-afm afm-file enc-file > encoded-afm-file
#
# Where: afm-file is the original AFM file with an arbitrary
# encoding enc-file is the encoding file (in PS
# format, a la dvips .enc files) encoded-afm-file is
# the new AFM file with 'enc-file' encoding.
#
# what about .notdef?
$afmfile = @ARGV[0];
$encfile = @ARGV[1];
print STDERR "Reading encoding file: $encfile\n";
&read_encfile($encfile);
print STDERR "Reading AFM file: $afmfile\n";
&read_afmfile($afmfile);
# Assign the correct encoding position to each char
$missing = 0;
for ($count = 0; $count < $vectorlen; $count++) {
$missing_glyphs{@encoding[$count]} = 1, $missing = 1
if !defined($vectorplace{@encoding[$count]})
&& @encoding[$count] ne ".notdef";
$vectorplace{@encoding[$count]} = $count;
}
&print_long_list("Note: the following glyphs are missing "
. "from the AFM file: ",
sort (keys %missing_glyphs))
if $missing;
# Construct the CharMetrics lines
@output_encoding = ();
foreach $name (keys %metrics) {
push (@output_encoding,
sprintf("C %3d ; %s",
$vectorplace{$name}, $metrics{$name}));
}
# Sort the CharMetrics lines
@sorted_encoding = sort (@output_encoding);
# Move the unused characters to the end of the list
@output_encoding = grep(/^C\s+\d+/, @sorted_encoding);
@minusone_encoding = grep(/C\s+-1/, @sorted_encoding);
push(@output_encoding, @minusone_encoding);
# Print the new AFM file
print $line, "\n" while ($line = shift @preamble);
print "Comment Encoded with enc-afm from $encfile.\n";
print "EncodingScheme $encname\n";
printf "StartCharMetrics %d\n", $#output_encoding+1;
print $line, "\n" while ($line = shift @output_encoding);
print "EndCharMetrics\n";
print $line, "\n" while ($line = shift @postamble);
exit 0;
sub read_afmfile {
local ($afmfile) = @_;
local ($inpreamble, $inmetrics, $inpostamble) = (1,0);
local ($width, $name, $bbox, $prname);
@preamble = ();
%metrics = ();
%vectorplace = ();
@postamble = ();
open (AFM, $afmfile)
|| die "Can't open afm file: $afmfile\n";
while (<AFM>) {
chop;
push(@postamble, $_) if $inpostamble;
push(@preamble, $_)
if $inpreamble && ! /^EncodingScheme\s/i;
if (/^EndCharMetrics/) {
$inmetrics = 0;
$inpostamble = 1;
}
if ($inmetrics) {
$width = $1 if /[;\s]+WX\s+([0-9]+)[;\s]+/;
$name = $1 if /[;\s]+N\s+(\w+)[;\s]+/;
$bbox = $1 if /[;\s]+B\s+([^;]+)[;\s]+/;
die "Invalid line in AFM file: $_\n"
if ($name eq "");
$metrics{$name} = sprintf("WX %4d ; N %s ; B %s ;",
$width, $name, $bbox);
$vectorplace{$name} = -1;
}
if (/^StartCharMetrics/) {
$inpreamble = 0;
$inmetrics = 1;
}
}
}
sub read_encfile {
local ($encfile) = @_;
local ($place, $line);
open (ENC, $encfile)
|| die "Can't open encoding file: $encfile\n";
$encname = "";
@encoding = ();
$#encoding = 256; # set the array length
$vectorlen = 0;
$done = 0;
while (<ENC>) {
chop;
next if /^\s*%/;
$line = $_;
if ($encname eq "") {
die "Invalid line in encoding file: $_\n"
if ! /\s*\/(.*)\s*\[(.*)$/;
$encname = $1;
$line = $2;
}
$place = index($line, "%");
$line = substr($line,$[,$place-1) if $place >= $[;
$place = index($line, "]");
if ($place >= $[) {
$line = substr($line,$[,$place-1);
$done = 1;
}
while ($line =~ /^\s*\/(\S*)\s*(.*)$/) {
@encoding[$vectorlen++] = $1;
$line = $2;
}
last if $done;
}
}
############################################################
# This routine prints a message followed by a potentially
# long list of items, seperated by spaces. It will never
# allow "word wrap" to occur in the middle of a word. There
# has to be a better way, using Perl's report generation to
# do this, but I haven't looked yet.
#
sub print_long_list {
local ($message,@thelist) = @_;
local ($line) = $message;
local ($item, $displaystring) = ("", "");
foreach $item (@thelist) {
if (length($line . $item) < 73) {
$line .= $item . ", ";
} else {
$displaystring .= $line . "\n";
$line = $item . ", ";
}
}
$line =~ s/(.*),\s*$/$1/; # remove the last ", "...
$displaystring .= $line . "\n";
print STDERR $displaystring;
}
|