home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / inne / gs300ini / wrfont.ps < prev    next >
Encoding:
Text File  |  1994-08-02  |  15.6 KB  |  542 lines

  1. %    Copyright (C) 1991, 1993, 1994 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. % wrfont.ps
  16. % Write out a Type 1 font in readable, reloadable form.
  17. % Note that this does NOT work on protected fonts, such as Adobe fonts
  18. % (unless you have loaded unprot.ps first, in which case you may be
  19. % violating the Adobe license).
  20.  
  21. /wrfont_dict 100 dict def
  22. wrfont_dict begin
  23.  
  24. % ------ Options ------ %
  25.  
  26. % Define whether to write out the CharStrings in binary or in hex.
  27. % Binary takes less space on the file, but isn't guaranteed portable.
  28.    /binary_CharStrings false def
  29.  
  30. % Define whether to use binary token encodings when possible.
  31. % Binary tokens are smaller and load faster, but are a Level 2 feature.
  32.    /binary_tokens false def
  33.  
  34. % Define whether to encrypt the CharStrings on the file.  (CharStrings
  35. % are always encrypted in memory.)  Unencrypted CharStrings load about
  36. % 20% slower, but make the files compress much better for transport.
  37.    /encrypt_CharStrings true def
  38.  
  39. % Define whether the font must provide standard PostScript language
  40. % equivalents for any facilities it uses that are provided in Ghostscript
  41. % but are not part of the standard PostScript language.
  42.    /standard_only true def
  43.  
  44. % Define the value of lenIV to use in writing out the font.
  45. % use_lenIV = 0 produces the smallest output, but this may not be
  46. % compatible with old Adobe interpreters.  use_lenIV = -1 means
  47. % use the value of lenIV from the font.
  48.    /use_lenIV -1 def
  49.  
  50. % Define whether to produce the smallest possible output, relying
  51. % as much as possible on Ghostscript-specific support code.
  52. % Taking full advantage of this requires the following settings:
  53. % binary_CharStrings = true, binary_tokens = true, standard_only = false.
  54.    /smallest_output false def
  55.  
  56. % ---------------- Runtime support ---------------- %
  57.  
  58. currentdict end
  59.  
  60. % If smallest_output was selected when the font was written,
  61. % the following code must be available when the font is being loaded.
  62.  
  63. /.check_existing_font    % <fontname> <uid> .check_existing_font {}
  64.             % <fontname> <uid> .check_existing_font restore -save-
  65.  { {} 3 1 roll
  66.    exch FontDirectory exch .knownget
  67.     { dup /UniqueID .knownget
  68.        { 2 index eq exch /FontType get 1 eq and }
  69.        { pop false }
  70.       ifelse exch pop
  71.        { pop save /restore load }
  72.       if
  73.     }
  74.     { pop
  75.     }
  76.    ifelse
  77.  } bind def
  78.  
  79. /.knownEncodings [
  80.    ISOLatin1Encoding
  81.    StandardEncoding
  82.    SymbolEncoding
  83. ] readonly def
  84.  
  85. /.read_CharStrings    % <count> <encrypt> .read_CharStrings <dict>
  86.  { exch dup dict dup 3 -1 roll
  87.     { currentfile token pop dup type /integertype eq
  88.        { dup -8 bitshift .knownEncodings exch get exch 255 and get } if
  89.       currentfile token pop dup type /nametype eq
  90.        { 2 index exch get
  91.        }
  92.        {    % Stack: encrypt dict dict key value
  93.      4 index { 4330 exch dup .type1encrypt exch pop } if
  94.      readonly
  95.        }
  96.       ifelse put dup
  97.     }
  98.    repeat pop exch pop
  99.  } bind def
  100.  
  101. begin
  102.  
  103. % ------ Output utilities ------ %
  104.  
  105. % By convention, the output file is named psfile.
  106.  
  107. % Define some utilities for writing the output file.
  108.    /wtstring 800 string def
  109.    /wb {psfile exch write} bind def
  110.    /wnb {/wb load repeat} bind def
  111.    /w1 {psfile exch write} bind def
  112.    /ws {psfile exch writestring} bind def
  113.    /wl {ws (\n) ws} bind def
  114.    /wt {wtstring cvs ws ( ) ws} bind def
  115.    /wd        % Write a dictionary.
  116.     { dup length wt (dict dup begin) wl { we } forall
  117.       (end) ws
  118.     } bind def
  119.    /wld        % Write a large dictionary more efficiently.
  120.            % Ignore the readonly attributes.
  121.     { dup length wt (dict dup begin) wl
  122.       0 exch
  123.        { exch wo wo () wl
  124.      1 add dup 200 eq
  125.       { wo ({def} repeat) wl 0 }
  126.      if
  127.        }
  128.       forall
  129.       dup 0 ne
  130.        { wo ({def} repeat) wl }
  131.        { pop }
  132.       ifelse
  133.       (end) ws
  134.     } bind def
  135.    /we        % Write a dictionary entry.
  136.     { exch wo wo /def cvx wo (\n) ws
  137.     } bind def
  138.    /wcs        % Write a CharString (or Subrs entry)
  139.     { dup type /stringtype eq
  140.        { 4330 exch changelenIV 0 ge
  141.           {    % Add some leading garbage bytes.
  142.         wtstring changelenIV 2 index length getinterval
  143.         .type1decrypt exch pop
  144.         wtstring exch 0 exch length changelenIV add getinterval
  145.       }
  146.       {    % Drop some leading garbage bytes.
  147.         wtstring .type1decrypt exch pop
  148.         changelenIV neg 1 index length 1 index sub getinterval
  149.       }
  150.      ifelse
  151.          binary_tokens encrypt_CharStrings and
  152.       { % Suppress recognizing the readonly status of the string.
  153.         4330 exch dup .type1encrypt exch pop wo
  154.       }
  155.       { encrypt_CharStrings
  156.          { 4330 exch dup .type1encrypt exch pop
  157.          } if
  158.         smallest_output
  159.          { wo
  160.          }
  161.          { readonly dup length wo
  162.            binary_tokens not { ( ) ws } if
  163.            readproc ws wx
  164.          }
  165.         ifelse
  166.       }
  167.      ifelse
  168.        }
  169.        { wo        % PostScript procedure
  170.        }
  171.       ifelse
  172.     } bind def
  173.  
  174. % Construct the inversion of the system name table.
  175.    /SystemNames where
  176.     { pop /snit 256 dict def
  177.       0 1 255
  178.        { dup SystemNames exch get
  179.          dup null ne { exch snit 3 1 roll put } { pop pop } ifelse
  180.        }
  181.       for
  182.     }
  183.     { /snit 1 dict def
  184.     }
  185.    ifelse
  186.  
  187. % Write an object, using binary tokens if requested and possible.
  188.    /woa        % write in ascii
  189.     { psfile exch write==only
  190.     } bind def
  191.  
  192.             % Lookup table for ASCII output.
  193.  
  194.    /intbytes    % int nbytes -> byte*
  195.     { { dup 255 and exch -8 bitshift } repeat pop
  196.     } bind def
  197.    /wotta 10 dict dup begin
  198.       { /booleantype /integertype /nulltype }
  199.       { { ( ) ws woa } def }
  200.      forall
  201.         % Iterate over arrays so we can print operators.
  202.      /arraytype
  203.       { dup xcheck {(}) ({)} {(]) ([)} ifelse ws exch dup wol exch ws wop
  204.       } bind def
  205.      /dicttype
  206.       { ( ) ws wd } def
  207.      /nametype
  208.       { dup xcheck { ( ) ws } if woa
  209.       } bind def
  210.         % Map back operators to their names,
  211.         % so we can write procedures.
  212.      /operatortype
  213.       { wtstring cvs cvn cvx wo
  214.       } bind def
  215.         % Convert reals to integers if possible.
  216.      /realtype
  217.       { dup cvi 1 index eq { cvi wo } { ( ) ws woa } ifelse
  218.       } bind def
  219.         % == truncates strings longer than 200 characters!
  220.      /stringtype
  221.       { (\() ws dup
  222.      { dup dup 32 lt exch 127 ge or
  223.         { (\\) ws dup -6 bitshift 48 add w1
  224.           dup -3 bitshift 7 and 48 add w1
  225.           7 and 48 add
  226.         }
  227.         { dup dup -2 and 40 eq exch 92 eq or {(\\) ws} if
  228.         }
  229.        ifelse w1
  230.      }
  231.     forall
  232.     (\)) ws wop
  233.       } bind def
  234.      /packedarraytype
  235.       { ([) ws dup { wo } forall
  236.     encodingnames 1 index known
  237.         % This is an encoding, but not one of the standard ones.
  238.         % Use the built-in encoding only if it is available.
  239.      { encodingnames exch get wo
  240.        ({findencoding}stopped{pop) ws
  241.        (}{counttomark 1 add 1 roll cleartomark}ifelse)
  242.      }
  243.      { pop ()
  244.      }
  245.     ifelse
  246.     (/packedarray where{pop counttomark packedarray exch pop}{]readonly}ifelse) ws
  247.     wl
  248.       }
  249.      def
  250.    end def
  251.  
  252.             % Lookup table for binary output.
  253.  
  254.    /wottb 8 dict dup begin
  255.    wotta currentdict copy pop
  256.      /integertype
  257.       { dup dup 127 le exch -128 ge and
  258.          { 136 wb 255 and wb }
  259.      { dup dup 32767 le exch -32768 ge and
  260.         { 134 wb 2 intbytes wb wb }
  261.         { 132 wb 4 intbytes wb wb wb wb }
  262.        ifelse
  263.      }
  264.     ifelse
  265.       } bind def
  266.      /nametype
  267.       { dup snit exch known
  268.          { dup xcheck { 146 } { 145 } ifelse wb
  269.        snit exch get wb
  270.      }
  271.      { wotta /nametype get exec
  272.      }
  273.     ifelse
  274.       } bind def
  275.      /stringtype
  276.       { dup dup length dup 255 le { 142 2 } { 2 intbytes 143 3 } ifelse wnb
  277.     ws wop
  278.       } bind def
  279.    end def
  280.  
  281.    /wop        % Write object protection
  282.      { wcheck not { /readonly cvx wo } if
  283.      } bind def
  284.    /wo        % Write an object.
  285.      { dup type binary_tokens { wottb } { wotta } ifelse
  286.        exch get exec
  287.      } bind def
  288.    /wol        % Write a list of objects.
  289.      { { wo } forall
  290.      } bind def
  291.  
  292. % Write a hex string for Subrs or CharStrings.
  293.    /wx        % string ->
  294.     { binary_CharStrings
  295.        { ws
  296.        }
  297.        { % Some systems choke on very long lines, so
  298.      % we break up the hexstring into chunks of 50 characters.
  299.       { dup length 25 le {exit} if
  300.         dup 0 25 getinterval psfile exch writehexstring (\n) ws
  301.         dup length 25 sub 25 exch getinterval
  302.       } loop
  303.      psfile exch writehexstring
  304.        } ifelse
  305.     } bind def
  306.  
  307. % ------ CharString encryption utilities ------ %
  308.  
  309. /enc_dict 20 dict def
  310. 1 dict begin
  311. /bind { } def        % make sure we can print out the procedures
  312. enc_dict begin
  313.  
  314. (type1enc.ps) run
  315. enc_dict /.type1decrypt undef        % we don't need this
  316.  
  317. end end
  318.  
  319. enc_dict { 1 index where { pop pop pop } { def } ifelse } forall
  320.  
  321. % ------ The main program ------ %
  322.  
  323. % Define the dictionary of actions for special entries in the dictionaries.
  324. % We lump the font and the Private dictionary together, because
  325. % the set of keys doesn't overlap.
  326. [/CharStrings /Encoding /FID /FontInfo /Metrics /Private /Subrs]
  327. dup length dict begin
  328.  { null cvx def } forall
  329. currentdict end /specialkeys exch def
  330.  
  331. % Define the procedures for the Private dictionary.
  332. % These must be defined without `bind',
  333. % for the sake of the DISKFONTS feature.
  334. 4 dict begin
  335.  /-! {string currentfile exch readhexstring pop} def
  336.  /-| {string currentfile exch readstring pop} def
  337.  /|- {readonly def} def
  338.  /| {readonly put} def
  339. currentdict end /encrypted_procs exch def
  340. 4 dict begin
  341.  /-! {string currentfile exch readhexstring pop
  342.    4330 exch dup .type1encrypt exch pop} def
  343.  /-| {string currentfile exch readstring pop
  344.    4330 exch dup .type1encrypt exch pop} def
  345.  /|- {readonly def} def
  346.  /| {readonly put} def
  347. currentdict end /unencrypted_procs exch def
  348.  
  349. % Construct an inverse dictionary of encodings.
  350. 4 dict begin
  351.  StandardEncoding /StandardEncoding def
  352.  ISOLatin1Encoding /ISOLatin1Encoding def
  353.  SymbolEncoding /SymbolEncoding def
  354.  DingbatsEncoding /DingbatsEncoding def
  355. currentdict end /encodingnames exch def
  356.  
  357. % Invert the standard encodings.
  358. .knownEncodings length 256 mul dict begin
  359.   0 .knownEncodings
  360.    {  { currentdict 1 index known { pop } { 1 index def } ifelse
  361.     1 add
  362.       }
  363.      forall
  364.    }
  365.   forall pop
  366. currentdict end /inverseencodings exch def
  367.  
  368. /writefont        % <psfile> writefont - (writes the current font)
  369.  { /psfile exch def
  370.    /Font currentfont def
  371.    /readproc binary_CharStrings { (-| ) } { (-! ) } ifelse def
  372.    /privateprocs
  373.      encrypt_CharStrings binary_tokens not and
  374.       { encrypted_procs } { unencrypted_procs } ifelse
  375.      def
  376.    /changelenIV use_lenIV 0 lt
  377.     { 0 }
  378.     { use_lenIV Font /Private get /lenIV .knownget not { 4 } if sub }
  379.    ifelse def
  380.    (%!FontType1-1.0: ) ws currentfont /FontName get wt (000.000) wl
  381.    (systemdict begin) wl
  382.  
  383. % Turn on binary tokens if relevant.
  384.    binary_tokens { (currentobjectformat 1 setobjectformat) wl } if
  385.  
  386. % If the file has a UniqueID, write out a check against loading it twice.
  387.    Font /UniqueID known
  388.     { smallest_output
  389.        { Font /FontName get wo
  390.      Font /UniqueID get wo
  391.      ( .check_existing_font) wl
  392.        }
  393.        { ({} FontDirectory) ws Font /FontName get dup wo ( known) wl
  394.      ( {) ws wo ( findfont dup /UniqueID known) wl
  395.      (    { dup /UniqueID get) ws Font /UniqueID get wo ( eq exch /FontType get 1 eq and }) wl
  396.      (    { pop false } ifelse) wl
  397.      (    { pop save /restore load } if) wl
  398.      ( } if) wl
  399.        }
  400.       ifelse
  401.     }
  402.    if
  403.  
  404. % If we are writing unencrypted CharStrings for a standard environment,
  405. % write out the encryption procedures.
  406.    privateprocs unencrypted_procs eq standard_only and
  407.     { (systemdict /.type1encrypt known) wl
  408.       ( { save /restore load } { { } } ifelse) wl
  409.       (userdict begin) wl
  410.       enc_dict { we } forall
  411.       (end exec) wl
  412.     }
  413.    if
  414.  
  415. % Write out the creation of the font dictionary and FontInfo.
  416.    Font length 1 add wt (dict begin) wl        % +1 for FontFile
  417.    Font begin
  418.    (/FontInfo ) ws FontInfo wd ( readonly def) wl
  419.  
  420. % Write out the other fixed entries in the font dictionary.
  421.    Font
  422.     { 1 index specialkeys exch known
  423.        { pop pop } { we } ifelse
  424.     } forall
  425.    /Encoding
  426.    encodingnames Encoding known
  427.    Encoding StandardEncoding eq
  428.    Encoding ISOLatin1Encoding eq or and
  429.     { encodingnames Encoding get cvx }
  430.     { Encoding }
  431.    ifelse we
  432.  
  433. % Write out the Metrics, if any.
  434.    Font /Metrics known
  435.     { (/Metrics ) ws Metrics wld ( readonly def) wl
  436.     }
  437.    if
  438.  
  439. % Close the font dictionary.
  440.    (currentdict end) wl
  441.  
  442. % The rest of the file could be in eexec form, but we don't see any point
  443. % in doing this, because we aren't attempting to conceal it from anyone.
  444.  
  445. % Create and initialize the Private dictionary.
  446.    Private
  447.    smallest_output
  448.     { begin
  449.     }
  450.     {  dup length privateprocs length add dict copy begin
  451.        privateprocs { readonly def } forall
  452.     }
  453.    ifelse
  454.    {dup /Private} wol currentdict length 1 add wo {dict dup begin} wol () wl
  455.    currentdict
  456.     { 1 index specialkeys exch known
  457.        { pop pop }
  458.        { 1 index /lenIV eq use_lenIV 0 ge and { pop use_lenIV } if we }
  459.       ifelse
  460.     } forall
  461.  
  462. % Write the Subrs entries, if any.
  463.    currentdict /Subrs known
  464.     { (/Subrs[) wl
  465.       Subrs
  466.        { dup null ne
  467.       { wcs }
  468.       { pop /null cvx wo }
  469.      ifelse
  470.        } forall
  471.       {] dup {readonly pop} forall readonly def} wol () wl
  472.     }
  473.    if
  474.  
  475. % Write the CharStrings entries.
  476. % Detect identical (eq) entries, which bdftops produces.
  477.    {2 index /CharStrings} wol
  478.    CharStrings length wo
  479.    smallest_output
  480.     { encrypt_CharStrings not wo ( .read_CharStrings) wl
  481.       CharStrings length dict
  482.       CharStrings
  483.        { exch inverseencodings 1 index .knownget not { dup } if wo
  484.         % Stack: vdict value key
  485.      3 copy pop .knownget { wo pop pop } { 3 copy put pop wcs } ifelse
  486.        } forall
  487.     }
  488.     { {dict dup begin} wol () wl
  489.       CharStrings length dict
  490.       CharStrings
  491.        { 2 index 1 index known
  492.       { exch wo 1 index exch get wo ( load def) wl
  493.       }
  494.       { 2 index 1 index 3 index put
  495.         exch wo wcs ( |-) wl
  496.       }
  497.      ifelse
  498.        } forall
  499.       {end} wol
  500.     }
  501.    ifelse
  502.    pop
  503.  
  504. % Wrap up the private part of the font.
  505.    end            % Private
  506.    end            % Font
  507.     { end        % Private
  508.       readonly put    % CharStrings in font
  509.       readonly put    % Private in font
  510.  
  511. % Terminate the output.
  512.       dup /FontName get exch definefont pop
  513.     }
  514.    wol
  515.    Font /UniqueID known { /exec cvx wo } if
  516.    binary_tokens { /setobjectformat cvx wo } if
  517.    /end cvx wo        % systemdict
  518.    () wl
  519.  
  520.  } bind def
  521.  
  522. % ------ Other utilities ------ %
  523.  
  524. % Prune garbage characters and OtherSubrs out of the current font,
  525. % if the relevant dictionaries are writable.
  526. /prunefont
  527.  { currentfont /CharStrings get wcheck
  528.     { currentfont /CharStrings get dup [ exch
  529.        { pop dup (S????00?) .stringmatch not { pop } if
  530.        } forall
  531.       ] { 2 copy undef pop } forall pop
  532.     }
  533.    if
  534.  } bind def
  535.  
  536. end            % wrfont_dict
  537.  
  538. /writefont { wrfont_dict begin writefont end } def
  539.