#! /bin/sh # Make a small-caps version of an AFM file # usage: mk-sc scale afm-file-name >new-afm-file-name # # scale is the ratio between the small and the large caps (e.g, 0.8) # # bugs: doesn't set these fields properly: # FontBBox # KPX data for lowercase is discarded # # rounding is done with int(x+0.5) --- this is wrong for -ve values trap "rm -f /tmp/afm$$0[012] /tmp/kern$$" 0 csplit -f /tmp/afm$$ -s $2 /StartKernPairs/+1 /EndKernPairs/ # chardata now in /tmp/afm$$00, kern in /tmp/afm$$01, # composites in /tmp/afm$$02 # first do the kern data awk 'BEGIN { lower= "abcdefghijklmnopqrstuvwxyz"; upper= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } /^$/ { next; } /^KPX/ && $2 ~ /^[A-Z]$/ && $3 ~ /^[A-Z]$/ { # insert extra kerning data for lower case, based on upper case lwr2=substr(lower, index(upper, $2), 1); lwr3=substr(lower, index(upper, $3), 1); print "KPX", lwr2, $3, $4 print "KPX", $2, lwr3, $4 print "KPX", lwr2, lwr3, $4 print $0 next; } /^KPX/ && ($2 ~ /^[a-z]$/ || $3 ~ /^[a-z]$/) { # filter out kerning applied to lower-case next; } { print ; }' /tmp/afm$$01 | sort +1 -3 | awk ' $2 != last { printf "\n" ; last= $2 } { print } ' >/tmp/kern$$ # now process the chardata, and put the bits together awk 'BEGIN {'scale=$1';} /^FontName/ { print $0 "-SmallCaps"; next; } /^FullName/ { print $0, "SmallCaps"; next; } /^CapHeight/ { print "XHeight", int($2*scale + 0.5) } /^XHeight/ { next;} /^Descender/ { print "Descender 0"; next; } /^C / { ch = $2; if (ch >= 65 && ch <= 90) { # it is an upper case letter, so save the (scaled) metric info ch += 32; w[ch] = int($5 * scale + 0.5); llx[ch] = int($11 * scale + 0.5); lly[ch] = int($12 * scale + 0.5); urx[ch] = int($13 * scale + 0.5); ury[ch] = int($14 * scale + 0.5); print; } else if (ch >= 97 && ch <= 122) { # it is a lower case letter -- substitute the saved info printf "C %d ; WX %d ; N %s ; B %d %d %d %d\n", \ ch, w[ch], $8, llx[ch], lly[ch], urx[ch], ury[ch], ";"; # do not want any ligature info } else print; next; } {print}' /tmp/afm$$00 | cat - /tmp/kern$$ /tmp/afm$$02