home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / GhostScript / !GhostScr / 6_01 / lib / wrfont.ps < prev    next >
Text File  |  2000-03-09  |  18KB  |  665 lines

  1. %    Copyright (C) 1991, 1995, 1996 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % $Id: wrfont.ps,v 1.1 2000/03/09 08:40:40 lpd Exp $
  16. % wrfont.ps
  17. % Write out a Type 1 font in readable, reloadable form.
  18. % Note that this does NOT work on protected fonts, such as Adobe fonts
  19. % (unless you have loaded unprot.ps first, in which case you may be
  20. % violating the Adobe license).
  21.  
  22. % ****** NOTE: This file must be kept consistent with gs_pfile.ps.
  23.  
  24. /wrfont_dict 100 dict def
  25. wrfont_dict begin
  26.  
  27. % ------ Options ------ %
  28.  
  29. % Define whether to use eexec encryption for the font.
  30. % eexec encryption is only useful for compatibility with Adobe Type Manager
  31. % and other programs; it only slows Ghostscript down.
  32.    /eexec_encrypt false def
  33.  
  34. % Define whether to write out the CharStrings in binary or in hex.
  35. % Binary takes less space on the file, but isn't guaranteed portable.
  36.    /binary_CharStrings false def
  37.  
  38. % Define whether to use binary token encodings when possible.
  39. % Binary tokens are smaller and load faster, but are a Level 2 feature.
  40.    /binary_tokens false def
  41.  
  42. % Define whether to encrypt the CharStrings on the file.  (CharStrings
  43. % are always encrypted in memory.)  Unencrypted CharStrings load about
  44. % 20% slower, but make the files compress much better for transport.
  45.    /encrypt_CharStrings true def
  46.  
  47. % Define whether the font must provide standard PostScript language
  48. % equivalents for any facilities it uses that are provided in Ghostscript
  49. % but are not part of the standard PostScript language.
  50.    /standard_only true def
  51.  
  52. % Define the value of lenIV to use in writing out the font.
  53. % use_lenIV = 0 produces the smallest output, but this may not be
  54. % compatible with old Adobe interpreters.  use_lenIV = -1 means
  55. % use the value of lenIV from the font.
  56.    /use_lenIV -1 def
  57.  
  58. % Define whether to produce the smallest possible output, relying
  59. % as much as possible on Ghostscript-specific support code.
  60. % Taking full advantage of this requires the following settings:
  61. % binary_CharStrings = true, binary_tokens = true, standard_only = false.
  62.    /smallest_output false def
  63.  
  64. % Define whether to write out all currently known Encodings by name,
  65. % or only StandardEncoding and ISOLatin1Encoding.
  66.    /name_all_Encodings false def
  67.  
  68. % ---------------- Runtime support ---------------- %
  69.  
  70. /.packedfilefilter where
  71.  { pop }
  72.  { (gs_pfile.ps) runlibfile }
  73. ifelse
  74.  
  75. % ------ Output utilities ------ %
  76.  
  77. % By convention, the output file is named psfile.
  78.  
  79. % Define some utilities for writing the output file.
  80.    /wtstring 2000 string def
  81.    /wb {psfile exch write} bind def
  82.    /wnb {/wb load repeat} bind def
  83.    /w1 {psfile exch write} bind def
  84.    /ws {psfile exch writestring} bind def
  85.    /wl {ws (\n) ws} bind def
  86.    /wt {wtstring cvs ws ( ) ws} bind def
  87.    /wd        % Write a dictionary.
  88.     { dup length wo {dict dup begin} wol { we } forall
  89.       {end} wol
  90.     } bind def
  91.    /wld        % Write a large dictionary more efficiently.
  92.            % Ignore the readonly attributes.
  93.     { dup length wo {dict dup begin} wol
  94.       0 exch
  95.        { exch wo wo () wl
  96.      1 add dup 200 eq
  97.       { wo ({def} repeat) wl 0 }
  98.      if
  99.        }
  100.       forall
  101.       dup 0 ne
  102.        { wo ({def} repeat) wl }
  103.        { pop }
  104.       ifelse
  105.       (end) ws
  106.     } bind def
  107.    /we        % Write a dictionary entry.
  108.     { exch wo wo /def cvx wo (\n) ws
  109.     } bind def
  110.    /wcs        % Write a CharString (or Subrs entry)
  111.     { dup type /stringtype eq
  112.        { 4330 exch changelenIV 0 ge
  113.           {    % Add some leading garbage bytes.
  114.         wtstring changelenIV 2 index length getinterval
  115.         .type1decrypt exch pop
  116.         wtstring exch 0 exch length changelenIV add getinterval
  117.       }
  118.       {    % Drop some leading garbage bytes.
  119.         wtstring .type1decrypt exch pop
  120.         changelenIV neg 1 index length 1 index sub getinterval
  121.       }
  122.      ifelse
  123.          binary_tokens encrypt_CharStrings and
  124.       { % Suppress recognizing the readonly status of the string.
  125.         4330 exch dup .type1encrypt exch pop wo
  126.       }
  127.       { encrypt_CharStrings
  128.          { 4330 exch dup .type1encrypt exch pop
  129.          } if
  130.         smallest_output
  131.          { wo
  132.          }
  133.          { readonly dup length wo
  134.            binary_tokens not { ( ) ws } if
  135.            readproc ws wx
  136.          }
  137.         ifelse
  138.       }
  139.      ifelse
  140.        }
  141.        { wo        % PostScript procedure
  142.        }
  143.       ifelse
  144.     } bind def
  145.  
  146. % Construct the inversion of the system name table.
  147.    /SystemNames where
  148.     { pop /snit 256 dict def
  149.       0 1 255
  150.        { dup SystemNames exch get
  151.          dup null ne { exch snit 3 1 roll put } { pop pop } ifelse
  152.        }
  153.       for
  154.     }
  155.     { /snit 1 dict def
  156.     }
  157.    ifelse
  158.  
  159. % Write an object, using binary tokens if requested and possible.
  160.    /woa        % write in ascii
  161.     { psfile exch write==only
  162.     } bind def
  163.  
  164.             % Lookup table for ASCII output.
  165.  
  166.    /intbytes    % int nbytes -> byte*
  167.     { { dup 255 and exch -8 bitshift } repeat pop
  168.     } bind def
  169.    /wotta 10 dict dup begin
  170.       { /booleantype /integertype }
  171.       { { ( ) ws woa } def }
  172.      forall
  173.         % Iterate over arrays so we can print operators.
  174.      /arraytype
  175.       { dup xcheck {(}) ({)} {(]) ([)} ifelse ws exch dup wol exch ws wop
  176.       } bind def
  177.      /dicttype
  178.       { ( ) ws wd } def
  179.      /nametype
  180.       { dup xcheck { ( ) ws } if woa
  181.       } bind def
  182.         % Map back operators to their names,
  183.         % so we can write procedures.
  184.      /nulltype
  185.       { pop ( null) ws
  186.       } bind def
  187.      /operatortype
  188.       { wtstring cvs cvn cvx wo
  189.       } bind def
  190.         % Convert reals to integers if possible.
  191.      /realtype
  192.       { dup cvi 1 index eq { cvi wo } { ( ) ws woa } ifelse
  193.       } bind def
  194.         % == truncates strings longer than 200 characters!
  195.      /stringtype
  196.       { (\() ws dup
  197.      { dup dup 32 lt exch 127 ge or
  198.         { (\\) ws dup -6 bitshift 48 add w1
  199.           dup -3 bitshift 7 and 48 add w1
  200.           7 and 48 add
  201.         }
  202.         { dup dup -2 and 40 eq exch 92 eq or {(\\) ws} if
  203.         }
  204.        ifelse w1
  205.      }
  206.     forall
  207.     (\)) ws wop
  208.       } bind def
  209.      /packedarraytype
  210.       { ([) ws dup { wo } forall
  211.     encodingnames 1 index known
  212.         % This is an encoding, but not one of the standard ones.
  213.         % Use the built-in encoding only if it is available.
  214.      { encodingnames exch get wo
  215.        ({findencoding}stopped{pop) ws
  216.        (}{counttomark 1 add 1 roll cleartomark}ifelse)
  217.      }
  218.      { pop ()
  219.      }
  220.     ifelse
  221.     (/packedarray where{pop counttomark packedarray exch pop}{]readonly}ifelse) ws
  222.     wl
  223.       }
  224.      def
  225.    end def
  226.  
  227.             % Lookup table for binary output.
  228.  
  229.    /wottb 8 dict dup begin
  230.    wotta currentdict copy pop
  231.      /integertype
  232.       { dup dup 127 le exch -128 ge and
  233.          { 136 wb 255 and wb }
  234.      { dup dup 32767 le exch -32768 ge and
  235.         { 134 wb 2 intbytes wb wb }
  236.         { 132 wb 4 intbytes wb wb wb wb }
  237.        ifelse
  238.      }
  239.     ifelse
  240.       } bind def
  241.      /nametype
  242.       { dup snit exch known
  243.          { dup xcheck { 146 } { 145 } ifelse wb
  244.        snit exch get wb
  245.      }
  246.      { wotta /nametype get exec
  247.      }
  248.     ifelse
  249.       } bind def
  250.      /stringtype
  251.       { dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
  252.     ws wop
  253.       } bind def
  254.    end def
  255.  
  256.    /wop        % Write object protection
  257.      { wcheck not { /readonly cvx wo } if
  258.      } bind def
  259.    /wo        % Write an object.
  260.      { dup type binary_tokens { wottb } { wotta } ifelse
  261.        exch get exec
  262.      } bind def
  263.    /wol        % Write a list of objects.
  264.      { { wo } forall
  265.      } bind def
  266.  
  267. % Write a hex string for Subrs or CharStrings.
  268.    /wx        % string ->
  269.     { binary_CharStrings
  270.        { ws
  271.        }
  272.        { % Some systems choke on very long lines, so
  273.      % we break up the hexstring into chunks of 50 characters.
  274.       { dup length 25 le {exit} if
  275.         dup 0 25 getinterval psfile exch writehexstring (\n) ws
  276.         dup length 25 sub 25 exch getinterval
  277.       } loop
  278.      psfile exch writehexstring
  279.        } ifelse
  280.     } bind def
  281.  
  282. % ------ CharString encryption utilities ------ %
  283.  
  284. /enc_dict 20 dict def
  285. 1 dict begin
  286. /bind { } def        % make sure we can print out the procedures
  287. enc_dict begin
  288.  
  289. (type1enc.ps) runlibfile
  290. enc_dict /.type1decrypt undef        % we don't need this
  291.  
  292. end end
  293.  
  294. enc_dict { 1 index where { pop pop pop } { def } ifelse } forall
  295.  
  296. % ------ Other utilities ------ %
  297.  
  298. % Test whether two values are equal (for default dictionary entries).
  299.    /valueeq        % <obj1> <obj2> valueeq <bool>
  300.     { 2 copy eq
  301.        { pop pop true }
  302.        {    % Special hack for comparing FontMatrix values
  303.      dup type /arraytype eq 2 index type /arraytype eq and
  304.       { dup length 2 index length eq
  305.          { true 0 1 3 index length 1 sub
  306.         {    % Stack: arr1 arr2 true index
  307.           3 index 1 index get 3 index 3 -1 roll get eq not
  308.            { pop false exit }
  309.           if
  310.         }
  311.            for 3 1 roll pop pop
  312.          }
  313.          { pop pop false
  314.          }
  315.         ifelse
  316.       }
  317.       { pop pop false
  318.       }
  319.      ifelse
  320.        }
  321.       ifelse
  322.     } bind def
  323.  
  324. % ------ The main program ------ %
  325.  
  326. % Define the dictionary of keys to skip because they are treated specially.
  327. /.fontskipkeys mark
  328.   /CharStrings dup
  329.   /Encoding dup
  330.   /FDepVector dup
  331.   /FID dup
  332.   /FontInfo dup
  333.   /Metrics dup
  334.   /Metrics2 dup
  335.   /Private dup
  336. .dicttomark def
  337. /.minfontskipkeys mark
  338.   .fontskipkeys { } forall
  339.   /FontName dup
  340.   /UniqueID dup
  341. .dicttomark def
  342. /.privateskipkeys mark
  343.   /ND dup
  344.   /NP dup
  345.   /RD dup
  346.   /Subrs dup
  347. .dicttomark def
  348. /.minprivateskipkeys mark
  349.   .privateskipkeys { } forall
  350.   /MinFeature dup
  351.   /Password dup
  352.   /UniqueID dup
  353. .dicttomark def
  354.  
  355. % Define the procedures for the Private dictionary.
  356. % These must be defined without `bind',
  357. % for the sake of the DISKFONTS feature.
  358. 4 dict begin
  359.  /-! {string currentfile exch readhexstring pop} def
  360.  /-| {string currentfile exch readstring pop} def
  361.  /|- {readonly def} def
  362.  /| {readonly put} def
  363. currentdict end /encrypted_procs exch def
  364. 4 dict begin
  365.  /-! {string currentfile exch readhexstring pop
  366.    4330 exch dup .type1encrypt exch pop} def
  367.  /-| {string currentfile exch readstring pop
  368.    4330 exch dup .type1encrypt exch pop} def
  369.  /|- {readonly def} def
  370.  /| {readonly put} def
  371. currentdict end /unencrypted_procs exch def
  372.  
  373. % Construct an inverse dictionary of encodings.
  374. /encodingnames mark
  375.  StandardEncoding /StandardEncoding
  376.  ISOLatin1Encoding /ISOLatin1Encoding
  377.  SymbolEncoding /SymbolEncoding
  378.  DingbatsEncoding /DingbatsEncoding
  379.  /resourceforall where
  380.   { pop (*) { cvn dup findencoding exch } 100 string /Encoding resourceforall }
  381.  if
  382. .dicttomark def
  383.  
  384. % Invert the standard encodings.
  385. .knownEncodings length 256 mul dict begin
  386.   0 .knownEncodings
  387.    {  { currentdict 1 index known { pop } { 1 index def } ifelse
  388.     1 add
  389.       }
  390.      forall
  391.    }
  392.   forall pop
  393. currentdict end /inverseencodings exch def
  394.  
  395. /writefont        % <psfile> writefont - (writes the current font)
  396.  { /psfile exch def
  397.    /Font currentfont def
  398.    /FontInfo Font /FontInfo .knownget not { 0 dict } if def
  399.    /FontType Font /FontType get def
  400.    /hasPrivate Font /Private known def
  401.    /Private hasPrivate { Font /Private get } { 0 dict } ifelse def
  402.    /readproc binary_CharStrings { (-| ) } { (-! ) } ifelse def
  403.    /privateprocs
  404.      encrypt_CharStrings binary_tokens not and
  405.       { encrypted_procs } { unencrypted_procs } ifelse
  406.      def
  407.    /addlenIV false def
  408.    /changelenIV use_lenIV 0 lt
  409.     { 0 }
  410.     { use_lenIV Private /lenIV .knownget not
  411.        { 4 /addlenIV use_lenIV 4 ne def } if sub }
  412.    ifelse def
  413.    /minimize
  414.      smallest_output
  415.      FontType 1 eq and
  416.      Font /UniqueID known and
  417.    def
  418.    (%!FontType) ws FontType wtstring cvs ws (-1.0: ) ws
  419.      currentfont /FontName get wt
  420.      FontInfo /version .knownget not { (001.001) } if wl
  421.    FontInfo /CreationDate .knownget { (%%Creation Date: ) ws wl } if
  422.    FontInfo /VMusage .knownget
  423.     { (%%VMusage: ) ws dup wt wtstring cvs wl }
  424.    if
  425.    (systemdict begin) wl
  426.  
  427. % If we're going to use eexec, create the filters now.
  428.    /realpsfile psfile def
  429.    eexec_encrypt
  430.     { /eexecfilter psfile binary_CharStrings not
  431.        { pop /bxstring 35 string def
  432.       { pop dup length 0 ne
  433.          { realpsfile exch writehexstring realpsfile (\n) writestring }
  434.          { pop }
  435.         ifelse bxstring
  436.       }
  437.      /NullEncode filter dup /hexfilter exch def
  438.        }
  439.       if 55665 /eexecEncode filter def
  440.     }
  441.    if
  442.  
  443. % Turn on binary tokens if relevant.
  444.    binary_tokens { (currentobjectformat 1 setobjectformat) wl } if
  445.  
  446. % If the file has a UniqueID, write out a check against loading it twice.
  447.    minimize
  448.     { Font /FontName get wo
  449.       Font /UniqueID get wo
  450.       Private length addlenIV { 1 add } if wo
  451.       Font length 1 add wo        % +1 for FontFile
  452.       ( .checkexistingfont) wl
  453.     }
  454.     { Font /UniqueID known
  455.        { ({} FontDirectory) ws Font /FontName get dup wo ( known) wl
  456.      ( {) ws wo ( findfont dup /UniqueID known) wl
  457.      (    { dup /UniqueID get) ws Font /UniqueID get wo ( eq exch /FontType get 1 eq and }) wl
  458.      (    { pop false } ifelse) wl
  459.      (    { pop save /restore load } if) wl
  460.      ( } if) wl
  461.        }
  462.       if
  463.     }
  464.    ifelse
  465.  
  466. % If we are writing unencrypted CharStrings for a standard environment,
  467. % write out the encryption procedures.
  468.    privateprocs unencrypted_procs eq standard_only and
  469.     { (systemdict /.type1encrypt known) wl
  470.       ( { save /restore load } { { } } ifelse) wl
  471.       (userdict begin) wl
  472.       enc_dict { we } forall
  473.       (end exec) wl
  474.     }
  475.    if
  476.  
  477. % Write out the creation of the font dictionary and FontInfo.
  478.    minimize not
  479.     { Font length 1 add wo {dict begin} wol        % +1 for FontFile
  480.     }
  481.    if
  482.    (/FontInfo ) ws FontInfo wd {readonly def} wol
  483.  
  484. % Write out the other fixed entries in the font dictionary.
  485.    Font begin
  486.    Font
  487.     { minimize
  488.        { .minfontskipkeys 2 index known
  489.       { pop pop
  490.       }
  491.       { //.compactfontdefault 2 index .knownget
  492.          { 1 index valueeq { pop pop } { we } ifelse }
  493.          { we }
  494.         ifelse
  495.       }
  496.      ifelse
  497.        }
  498.        { .fontskipkeys 2 index known { pop pop } { we } ifelse
  499.        }
  500.       ifelse
  501.     } forall
  502.    /Encoding
  503.    encodingnames Encoding known
  504.    name_all_Encodings
  505.    Encoding StandardEncoding eq or
  506.    Encoding ISOLatin1Encoding eq or and
  507.     { encodingnames Encoding get cvx }
  508.     { Encoding }
  509.    ifelse
  510.    dup /StandardEncoding cvx eq minimize and
  511.     { pop pop }
  512.     { we }
  513.    ifelse
  514.  
  515. % Write the FDepVector, if any.
  516.    Font /FDepVector .knownget
  517.     { {/FDepVector [} wol
  518.        { /FontName get wo {findfont} wol () wl } forall
  519.       {] readonly def} wol
  520.     }
  521.    if
  522.  
  523. % Write out the Metrics, if any.
  524.    Font /Metrics .knownget
  525.     { (/Metrics ) ws wld {readonly def} wol
  526.     }
  527.    if
  528.    Font /Metrics2 .knownget
  529.     { (/Metrics2 ) ws wld {readonly def} wol
  530.     }
  531.    if
  532.  
  533. % Start the eexec-encrypted section, if applicable.
  534.   eexec_encrypt
  535.    { {currentdict currentfile eexec} wol () wl
  536.      /psfile eexecfilter store
  537.      (\000\000\000\000) ws {begin} wol
  538.    }
  539.   if
  540.  
  541. % Create and initialize the Private dictionary, if any.
  542.    hasPrivate
  543. {
  544.    Private
  545.    minimize
  546.     { begin {Private dup begin}
  547.     }
  548.     {  dup length privateprocs length add dict copy begin
  549.        privateprocs { readonly def } forall
  550.        /Private wo
  551.        currentdict length 1 add wo {dict dup begin}
  552.     }
  553.    ifelse wol () wl
  554.    currentdict
  555.     { 1 index minimize { .minprivateskipkeys } { .privateskipkeys } ifelse
  556.       exch known
  557.        { pop pop }
  558.        { 1 index /lenIV eq use_lenIV 0 ge and { pop use_lenIV } if we }
  559.       ifelse
  560.     } forall
  561.    addlenIV { /lenIV use_lenIV we } if
  562. }
  563. if
  564.  
  565. % Write the Subrs entries, if any.
  566.    currentdict /Subrs known
  567.     { (/Subrs[) wl
  568.       Subrs
  569.        { dup null ne
  570.       { wcs minimize not { () wl } if }
  571.       { pop /null cvx wo }
  572.      ifelse
  573.        } forall
  574.       {] dup {readonly pop} forall readonly def} wol () wl
  575.     }
  576.    if
  577.  
  578. % Wrap up the Private dictionary.
  579.    hasPrivate
  580.     { end            % Private
  581.       minimize
  582.        { {end readonly pop} }    % Private
  583.        { {end readonly def} }    % Private in font
  584.       ifelse wol
  585.     }
  586.    if
  587.  
  588. % Write the CharStrings entries.
  589. % Detect identical (eq) entries, which bdftops produces.
  590.    currentdict /CharStrings known
  591. {
  592.    /CharStrings wo CharStrings length wo
  593.    minimize
  594.     { encrypt_CharStrings not wo ( .readCharStrings) wl
  595.       CharStrings length dict
  596.       CharStrings
  597.        { exch inverseencodings 1 index .knownget not { dup } if wo
  598.         % Stack: vdict value key
  599.      3 copy pop .knownget { wo pop pop } { 3 copy put pop wcs } ifelse
  600.        } forall
  601.     }
  602.     { {dict dup Private begin begin} wol () wl
  603.       CharStrings length dict
  604.       CharStrings
  605.        { 2 index 1 index known
  606.       { exch wo 1 index exch get wo {load def} wol () wl
  607.       }
  608.       { 2 index 1 index 3 index put
  609.         exch wo wcs ( |-) wl
  610.       }
  611.      ifelse
  612.        } forall
  613.       {end end} wol
  614.     }
  615.    ifelse
  616.    pop
  617.     { readonly def }    % CharStrings in font
  618.    wol
  619. }
  620. if
  621.  
  622. % Terminate the output.
  623.    end            % Font
  624.    eexec_encrypt
  625.     { {end mark currentfile closefile} wol () wl
  626.       eexecfilter dup flushfile closefile    % psfile is eexecfilter
  627.       binary_CharStrings not { hexfilter dup flushfile closefile } if
  628.       /psfile realpsfile store
  629.       8
  630.        { (0000000000000000000000000000000000000000000000000000000000000000)
  631.          wl
  632.        }
  633.       repeat {cleartomark} wol
  634.     }
  635.    if
  636.     { FontName currentdict end definefont pop
  637.     }
  638.    wol
  639.    Font /UniqueID known { /exec cvx wo } if
  640.    binary_tokens { /setobjectformat cvx wo } if
  641.    ( end) wl        % systemdict
  642.  
  643.  } bind def
  644.  
  645. % ------ Other utilities ------ %
  646.  
  647. % Prune garbage characters and OtherSubrs out of the current font,
  648. % if the relevant dictionaries are writable.
  649. /prunefont
  650.  { currentfont /CharStrings get wcheck
  651.     { currentfont /CharStrings get dup [ exch
  652.        { pop dup (S????00?) .stringmatch not { pop } if
  653.        } forall
  654.       ] { 2 copy undef pop } forall pop
  655.     }
  656.    if
  657.  } bind def
  658.  
  659. end            % wrfont_dict
  660.  
  661. /writefont { wrfont_dict begin writefont end } def
  662.