[comp.lang.postscript] Getting at character outlines

ccc_ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) (07/16/90)

Here's a piece of PostScript code that lets you get at the outline
definitions for the characters in any font. It's a helluva hack,
in that it has to search the interpreter code for particular
instruction sequences, in order to obtain the address of the
the global flag that charpath sets, and pathforall tests. It
then defines a new operator called "unprotectpath", which clears
this flag; just call unprotectpath after doing a charpath, and
before using pathforall.

The cexec code returns a Boolean result on the stack, indicating
if it was successful in defining unprotectpath.

This code was written by a bearded sage who runs a cexec-writing
factory (with the help of a number of friends) at a secret location
in the Himalayas. His usual response to bug reports and suggestions
for improvement is to growl and snap at vulnerable parts of the
anatomy. Use at your own risk.

%
% define the "unprotectpath" operator
%
currentfile 1256 string readhexstring
6EA0339904E8000104020010000000002F172F6F000800044EFA041400000000205F43FA
FFF8229F4ED0207AFFF0D0FC00A020504E902040226F000422D822D84E7520572EAF0004
2F6F000800042F480008207AFFC8D0FC005020504E90508F4E75207AFFB8D0FC00802050
4ED020572EAF00042F480004207AFFA2D0FC00F820504E90588F4E7520572EAF00042F6F
000800042F480008207AFF82D0FC011C20504E90508F4E7520572EAF00042F480004207A
FF68D0FC00B420504E90588F2040226F000422D822D84E75207AFF4ED0FC009C20504E90
2040226F000422D822D84E7520572EAF00042F6F000800042F6F000C00082F6F0010000C
2F480010207AFF1AD0FC007420504E90DEFC00102040226F000422D822D84E752F6F0004
000C201F225F205F2F0070001018600212D851C8FFFC42194E75221F201F225F205F2F01
600212D851C8FFFC484051C800046004484060EE4E754E56FFFC48E7010849FA03582854
2E140687000000432D47FFFC286EFFFC42144CDF10804E5E4E754E56FEE848E70108486E
FEE8598F487A008C286E0008486CFF004EBAFF7E4EBAFF06588F2D6EFEE8FFF82D6EFEEC
FFFC486EFEE82F2EFFFC2F2EFFF8286E00082F2CFEFC2F2CFEF84EBAFF18588F2D6EFEE8
FFF02D6EFEECFFF43E2EFFF21D47FEF02F2EFFF4486EFEF142471E2EFEF048C72F074EBA
FF42486EFEF0487A00184EBA02BC57C744071D47000C4CDF10804E5E2E9F4E750432332E
30000776657273696F6E4E56FFFA48E70118286E0008286C00082E1406870000011C2847
2D54FFFC3D7C0180FFFA55AEFFFC286EFFFC0C944EF10E006600001859AEFFFC286E0008
197C0001FEF060000044600000222E2EFFFC598728470C94E780D0B966000010286E0008
197C0001FEF060000020536EFFFA4A6EFFFA6600000E286E0008422CFEF0600000081E3C
0000679A286E00084A2CFEF067000010286E0008266EFFFC26532953FEF44CDF18804E5E
2E9F4E754E56FFDE48E70118486EFFDE598F487A00DE286E0008486CFF004EBAFE2C4EBA
FDB4588F2D6EFFDEFFF82D6EFFE2FFFC486EFFDE2F2EFFFC2F2EFFF8286E00082F2CFEFC
2F2CFEF84EBAFDC6588F2D6EFFDEFFF02D6EFFE2FFF43E2EFFF2CFECFEF248C7DEACFEF4
28472D54FFEC3D7C007FFFE6286EFFEC0C542079660000262E2EFFEC5C8728470C944A28
00436600001454AEFFEC286E0008197C0001FEF06000002454AEFFEC536EFFE64A6EFFE6
6600000E286E0008422CFEF0600000081E3C000067AE286E00084A2CFEF06700001449FA
01142D4CFFE8286EFFE8266EFFEC28934CDF18804E5E2E9F4E750A70617468666F72616C
6C004E56FFF048E70108486EFFF04EBAFC4E588F2D6EFFF0FFF82D6EFFF4FFFC2F2EFFFC
2F2EFFF84EBAFC4C487AFD60598F487A0020286E0008486CFF004EBAFD104EBAFC784EBA
FC4E4CDF10804E5E2E9F4E750D756E70726F74656374706174684E56FEE848E70108286E
00082F144EBAFBE21D7C0001FEF0486EFEE84EBAFC80588F2D6EFEE8FEF82D6EFEECFEFC
558F2F0E4EBAFD201E1F670000143D7C0004FEF22D7C00497CCCFEF46000000E3D7C0008
FEF22F0E4EBAFDA04A2EFEF0670000082F0E4EBAFE404A2EFEF0670000082F0E4EBAFF2C
1E2EFEF0488748C72F074EBAFBBE4CDF10804E5E2E9F4E7500000000241F225F205F2F02
42401018424112193400B44163023401B4026002B10956CAFFFC6602B0414E75
pop
(BAB2CD7AD2DAABB1603D) eexec	% French for "cexec"

not
  {
    (Couldn't define unprotectpath) =
    quit
  }
if

% and here's an example use of unprotectpath

newpath
0 0 moveto
/Times-Roman findfont 72 scalefont setfont
(T) false charpath

/TempStr 255 string def

unprotectpath

  { % move
    exch TempStr cvs print ( ) print
    TempStr cvs print ( moveto) =
  }
  { % line
    exch TempStr cvs print ( ) print
    TempStr cvs print ( lineto) =
  }
  { % curve
    6 5 roll TempStr cvs print ( ) print
    5 4 roll TempStr cvs print ( ) print
    4 3 roll TempStr cvs print ( ) print
    3 2 roll TempStr cvs print ( ) print
    exch TempStr cvs print ( ) print
    TempStr cvs print ( curveto) =
  }
  { % close
    (closepath) =
  }
pathforall