home *** CD-ROM | disk | FTP | other *** search
/ Internet Magazine 2002 February / INTERNET88.ISO / pc / software / windows / bits / pdf995 / data1.cab / Program_Executable_Files / res / font2pcl.ps < prev    next >
Encoding:
Text File  |  2001-12-08  |  18.0 KB  |  607 lines

  1. %    Copyright (C) 1993, 1994, 1995, 1997 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of GNU Ghostscript.
  3. % GNU Ghostscript is distributed in the hope that it will be useful, but
  4. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  5. % to anyone for the consequences of using it or for whether it serves any
  6. % particular purpose or works at all, unless he says so in writing.  Refer
  7. % to the GNU General Public License for full details.
  8. % Everyone is granted permission to copy, modify and redistribute GNU
  9. % Ghostscript, but only under the conditions described in the GNU General
  10. % Public License.  A copy of this license is supposed to have been given
  11. % to you along with GNU Ghostscript so you can know your rights and
  12. % responsibilities.  It should be in a file named COPYING.  Among other
  13. % things, the copyright notice and this notice must be preserved on all
  14. % copies.
  15.  
  16. % $RCSfile: font2pcl.ps,v $ $Revision: 1.2.2.1 $
  17. % font2pcl.ps
  18. % Write out a font as a PCL bitmap font.
  19.  
  20. /pcldict 60 dict def
  21.  
  22. % Write out the current font as a PCL bitmap font.
  23. % The current transformation matrix defines the font size and orientation.
  24.  
  25. /WriteResolution? false def    % true=use "resolution bound font" format,
  26.                 % false=use older format
  27.  
  28. /LJ4 false def            % true=use LJ4 Typeface code
  29.                 % false=use LJIIP/IID/IIIx Typeface code
  30.  
  31. pcldict begin        % internal procedures
  32.  
  33. /findstring    % <string> <substring> findstring <bool>
  34.  { search { pop pop pop true } { pop false } ifelse
  35.  } def
  36.  
  37.     % Determine which set of keywords is present in a string.
  38.     % The last keyword set must be empty.
  39.  
  40. /keysearch    % <string> <array of arrays of keywords> keysearch <index>
  41.  { 0 1 2 index length 1 sub
  42.     { 2 copy get true exch
  43.        {    % Stack: <string> <a.a.k.> <index> <bool> <keyword>
  44.          4 index exch findstring and
  45.        }
  46.       forall
  47.        { 0 exch getinterval exit
  48.        }
  49.       if pop
  50.     }
  51.    for
  52.    exch pop length    % invalid index if missing
  53.  } def
  54.  
  55.     % Determine the device height of a string in quarter-dots.
  56.  
  57. /charheight        % <string> charheight <int>
  58.  { gsave newpath 0 0 moveto false charpath
  59.    pathbbox exch pop exch sub exch pop 0 exch grestore
  60.    dtransform add abs 4 mul cvi
  61.  } def
  62.  
  63.     % Compute an integer version of the transformed FontBBox.
  64.  
  65. /inflate        % <num> inflate <num>
  66.  { dup 0 gt { ceiling } { floor } ifelse
  67.  } def
  68. /ixbbox            % - ixbbox <llx> <lly> <urx> <ury>
  69.  { /FontBBox load aload pop        % might be executable or literal
  70.    4 2 roll transform exch truncate cvi exch truncate cvi
  71.    4 2 roll transform exch inflate cvi exch inflate cvi
  72.  } def
  73.  
  74.     % Determine the original font of a possibly transformed font.
  75.     % Since some badly behaved PostScript files construct transformed
  76.     % fonts "by hand", we can't just rely on the OrigFont pointers.
  77.     % Instead, if a font with the given name exists, and if its
  78.     % entries for FontType and UniqueID match those of the font we
  79.     % obtain by following the OrigFont chain, we use that font.
  80.  
  81. /origfont
  82.  {  { dup /OrigFont known not { exit } if /OrigFont get } loop
  83.    FontDirectory 1 index /FontName get .knownget
  84.     {        % Stack: origfont namedfont
  85.       1 index /FontType get 1 index /FontType get eq
  86.        { 1 index /UniqueID .knownget
  87.       { 1 index /UniqueID .knownget
  88.          { eq { exch } if }
  89.          { pop }
  90.             ifelse
  91.       }
  92.      if
  93.        }
  94.       if pop
  95.     }
  96.    if
  97.  } def
  98.  
  99.  
  100.     % Determine the bounding box of the current device's image.
  101.     % Free variables: row, zerow.
  102.  
  103. /devbbox        % <rw> <rh> devbbox <ymin> <ymax1> <xmin> <xmax1>
  104.  {        % Find top and bottom whitespace.
  105.    dup
  106.     { dup 0 eq { exit } if 1 sub
  107.       dup currentdevice exch row copyscanlines
  108.       zerow ne { 1 add exit } if
  109.     }
  110.    loop        % ymax1
  111.    0
  112.     { 2 copy eq { exit } if
  113.       dup currentdevice exch row copyscanlines
  114.       zerow ne { exit } if
  115.       1 add
  116.     }
  117.    loop        % ymin
  118.    exch
  119.         % Find left and right whitespace.
  120.    3 index 0
  121.         % Stack: rw rh ymin ymax1 xmin xmax1
  122.    3 index 1 4 index 1 sub
  123.     { currentdevice exch row copyscanlines .findzeros
  124.       exch 4 1 roll max 3 1 roll min exch
  125.     }
  126.    for        % xmin xmax1
  127.         % Special check: xmin > xmax1 if height = 0
  128.    2 copy gt { exch pop dup } if
  129.    6 -2 roll pop pop
  130.  
  131.  } def
  132.  
  133.     % Write values on outfile.
  134.  
  135.  /w1 { 255 and outfile exch write } def
  136.  /w2 { dup -8 bitshift w1 w1 } def
  137.  /wbyte            % <byte> <label> wbyte
  138.   { VDEBUG { print ( =byte= ) print dup == flush } { pop } ifelse w1
  139.   } def
  140.  /wword            % <word16> <label> wword
  141.   { VDEBUG { print ( =word= ) print dup == flush } { pop } ifelse w2
  142.   } def
  143.  /wdword        % <word32> <label> wdword
  144.   { VDEBUG { print ( =dword= ) print dup == flush } { pop } ifelse
  145.     dup -16 bitshift w2 w2
  146.   } def
  147.  
  148. /style.posture.keys
  149.  [ { (Italic) } { (Oblique) }
  150.    { }
  151.  ] def
  152. /style.posture.values <010100> def
  153.  
  154. /style.appearance.width.keys
  155.  [ { (Ultra) (Compressed) }
  156.    { (Extra) (Compressed) }
  157.    { (Extra) (Condensed) }
  158.    { (Extra) (Extended) }
  159.    { (Extra) (Expanded) }
  160.    { (Compressed) }
  161.    { (Condensed) }
  162.    { (Extended) }
  163.    { (Expanded) }
  164.    { }
  165.  ] def
  166. /style.appearance.width.values <04030207070201060600> def
  167.  
  168. /width.type.keys
  169.  [ { (Ultra) (Compressed) }
  170.    { (Extra) (Compressed) }
  171.    { (Extra) (Condensed) }
  172.    { (Extra) (Expanded) }
  173.    { (Compressed) }
  174.    { (Condensed) }
  175.    { (Expanded) }
  176.    { }
  177.  ] def
  178. /width.type.values <fbfcfd03fdfe0200> def
  179.  
  180. /stroke.weight.keys
  181.  [ { (Ultra) (Thin) }
  182.    { (Ultra) (Black) }
  183.    { (Extra) (Thin) }
  184.    { (Extra) (Light) }
  185.    { (Extra) (Bold) }
  186.    { (Extra) (Black) }
  187.    { (Demi) (Light) }
  188.    { (Demi) (Bold) }
  189.    { (Semi) (Light) }
  190.    { (Semi) (Bold) }
  191.    { (Thin) }
  192.    { (Light) }
  193.    { (Bold) }
  194.    { (Black) }
  195.    { }
  196.  ] def
  197. /stroke.weight.values <f907fafc0406fe02ff01fbfd030500> def
  198.  
  199. /vendor.keys
  200.  [ { (Agfa) }
  201.    { (Bitstream) }
  202.    { (Linotype) }
  203.    { (Monotype) }
  204.    { (Adobe) }
  205.    { }
  206.  ] def
  207. /vendor.default.index 4 def        % might as well be Adobe
  208. /old.vendor.values <020406080a00> def
  209. /new.vendor.values <010203040500> def
  210. /vendor.initials (CBLMA\000) def
  211.  
  212. currentdict readonly end pop        % pcldict
  213.  
  214.  
  215. % Convert and write a PCL font for the current font and transformation.
  216.  
  217. % Write the font header.  We split this off only to avoid overflowing
  218. % the limit on the maximum size of a procedure.
  219. % Free variables: outfile uury u0y rw rh orientation uh ully
  220. /writefontheader
  221.  { outfile (\033\)s) writestring
  222.    outfile 64 WriteResolution? { 4 add } if
  223.      Copyright length add write==only
  224.    outfile (W) writestring
  225.    WriteResolution? { 20 68 } { 0 64 } ifelse
  226.      (Font Descriptor Size) wword
  227.      (Header Format) wbyte
  228.    1 (Font Type) wbyte
  229.    FullName style.posture.keys keysearch style.posture.values exch get
  230.    FullName style.appearance.width.keys keysearch
  231.      style.appearance.width.values exch get 4 mul add
  232.    PaintType 2 eq { 32 add } if
  233.      /style exch def
  234.    style -8 bitshift (Style MSB) wbyte
  235.    0 (Reserved) wbyte
  236.    /baseline uury 1 sub u0y sub def
  237.      baseline (Baseline Position) wword
  238.    rw (Cell Width) wword
  239.    rh (Cell Height) wword
  240.    orientation (Orientation) wbyte
  241.    FontInfo /isFixedPitch .knownget not { false } if
  242.     { 0 } { 1 } ifelse (Spacing) wbyte
  243.     % Use loop/exit to fake a multiple-exit block.
  244.     { Encoding StandardEncoding eq { 10 (J) exit } if
  245.       Encoding ISOLatin1Encoding eq { 11 (J) exit } if
  246.       Encoding SymbolEncoding eq { 19 (M) exit } if
  247.       Encoding DingbatsEncoding eq { 10 (L) exit } if
  248. %      (Warning: unknown Encoding, using ISOLatin1.\n) print flush
  249.       11 (J) exit
  250.     }
  251.    loop
  252.    0 get 64 sub exch 32 mul add (Symbol Set) wword
  253.    ( ) stringwidth pop 0 dtransform add abs 4 mul
  254.      /pitch exch def
  255.    pitch cvi (Pitch) wword
  256.    uh 4 mul (Height) wword            % Height
  257.    (x) charheight (x-Height) wword
  258.    FullName width.type.keys keysearch
  259.      width.type.values exch get (Width Type) wbyte
  260.    style 255 and (Style LSB) wbyte
  261.    FullName stroke.weight.keys keysearch
  262.      stroke.weight.values exch get (Stroke Weight) wbyte
  263.    FullName vendor.keys keysearch
  264.      dup vendor.initials exch get 0 eq
  265.       {        % No vendor in FullName, try Notice
  266.         pop Copyright vendor.keys keysearch
  267.     dup vendor.initials exch get 0 eq { pop vendor.default.index } if
  268.       }
  269.      if
  270.      /vendor.index exch def
  271.    0 (Typeface LSB) wbyte        % punt
  272.    0 (Typeface MSB) wbyte        % punt
  273.    0 (Serif Style) wbyte        % punt
  274.    2 (Quality) wbyte
  275.    0 (Placement) wbyte
  276.    gsave FontMatrix concat rot neg rotate
  277.    /ulwidth
  278.      FontInfo /UnderlineThickness .knownget
  279.       { 0 exch dtransform exch pop abs }
  280.       { resolution 100 div }
  281.      ifelse def
  282.    FontInfo /UnderlinePosition .knownget
  283.     { 0 exch transform exch pop negY ulwidth 2 div add }
  284.     { ully ulwidth add }
  285.    ifelse u0y sub
  286.    round cvi 1 max 255 min (Underline Position) wbyte
  287.    ulwidth round cvi 1 max 255 min (Underline Thickness) wbyte
  288.    grestore
  289.    uh 1.2 mul 4 mul cvi (Text Height) wword
  290.    (average lowercase character) dup stringwidth
  291.      pop 0 dtransform add abs
  292.      exch length div 4 mul cvi (Text Width) wword
  293.    0
  294.     { dup Encoding exch get /.notdef ne { exit } if
  295.       1 add
  296.     }
  297.    loop (First Code) wword
  298.    255
  299.     { dup Encoding exch get /.notdef ne { exit } if
  300.       1 sub
  301.     }
  302.    loop (Last Code) wword
  303.    pitch dup cvi sub 256 mul cvi (Pitch Extended) wbyte
  304.    0 (Height Extended) wbyte
  305.    0 (Cap Height) wword            % (default)
  306.    currentfont /UniqueID known { UniqueID } { 0 } ifelse
  307.      16#c1000000 add (Font Number (Adobe UniqueID)) wdword
  308.    FontName length 16 max string
  309.      dup FontName exch cvs pop
  310.      outfile exch 0 16 getinterval writestring    % Font Name
  311.    WriteResolution?
  312.     { resolution dup (X Resolution) wword (Y Resolution) wword
  313.     }
  314.    if
  315.    outfile Copyright writestring    % Copyright
  316.  } def
  317.  
  318. /writePCL        % <fontfile> <resolution> writePCL -
  319.  {
  320.    save
  321.    currentfont begin
  322.    pcldict begin
  323.    80 dict begin        % allow for recursion
  324.      /saved exch def
  325.      /resolution exch def
  326.      /outfile exch def
  327.    matrix currentmatrix dup 4 0 put dup 5 0 put setmatrix
  328.  
  329.     % Supply some default values so we don't have to check later.
  330.  
  331.    currentfont /FontInfo known not { /FontInfo 1 dict def } if
  332.    currentfont /FontName known not { /FontName () def } if
  333.    /Copyright   FontInfo /Notice .knownget not { () } if   def
  334.    /FullName
  335.      FontInfo /FullName .knownget not
  336.       { FontName dup length string cvs }
  337.      if def
  338.  
  339.     % Determine the original font, and its relationship to this one.
  340.  
  341.    /OrigFont currentfont origfont def
  342.    /OrigMatrix OrigFont /FontMatrix get def
  343.    /OrigMatrixInverse OrigMatrix matrix invertmatrix def
  344.    /ScaleMatrix matrix currentfont OrigFont ne
  345.     { FontMatrix exch OrigMatrixInverse exch concatmatrix
  346.     } if
  347.    def
  348.    /CurrentScaleMatrix
  349.      matrix currentmatrix
  350.      matrix defaultmatrix
  351.      dup 0 get 1 index 3 get mul 0 lt
  352.      1 index dup 1 get exch 2 get mul 0 gt or
  353.        /flipY exch def
  354.      dup invertmatrix
  355.      dup concatmatrix
  356.    def
  357.    /negY flipY { {neg} } { {} } ifelse def
  358.  
  359.     % Print debugging information.
  360.  
  361.    /CDEBUG where { pop } { /CDEBUG false def } ifelse
  362.    /VDEBUG where { pop } { /VDEBUG false def } ifelse
  363.    CDEBUG { /VDEBUG true def } if
  364.    DEBUG
  365.     { (currentmatrix: ) print matrix currentmatrix ==
  366.       (defaultmatrix: ) print matrix defaultmatrix ==
  367.       (flipY: ) print flipY ==
  368.       (scaling matrix: ) print CurrentScaleMatrix ==
  369.       (FontMatrix: ) print FontMatrix ==
  370.       (FontBBox: ) print /FontBBox load ==
  371.       currentfont OrigFont ne
  372.        { OrigFont /FontName .knownget { (orig FontName: ) print == } if
  373.          (orig FontMatrix: ) print OrigMatrix ==
  374.        } if
  375.       currentfont /ScaleMatrix .knownget { (ScaleMatrix: ) print == } if
  376.       gsave
  377.     FontMatrix concat
  378.     (combined matrix: ) print matrix currentmatrix ==
  379.       grestore
  380.       flush
  381.     } if
  382.  
  383.     % Determine the orientation.
  384.  
  385.    ScaleMatrix matrix currentmatrix dup concatmatrix
  386.    0 1 3
  387.     { 1 index 1 get 0 eq 2 index 2 get 0 eq and 2 index 0 get 0 gt and
  388.        { exit } if
  389.       pop -90 matrix rotate exch dup concatmatrix
  390.     }
  391.    for
  392.    dup type /integertype ne
  393.     { (Only rotations by multiples of 90 degrees are supported:\n) print
  394.       == flush
  395.       saved end end end restore stop
  396.     }
  397.    if
  398.    /orientation exch def
  399.    /rot orientation 90 mul def
  400.    DEBUG { (orientation: ) print orientation == flush } if
  401.  
  402.    dup dup 0 get exch 3 get negY sub abs 0.5 ge
  403.     { (Only identical scaling in X and Y is supported:\n) print
  404.       exch flipY 3 array astore ==
  405.       currentdevice .devicename ==
  406.       matrix defaultmatrix == flush
  407.       saved end end end restore stop
  408.     }
  409.    if pop
  410.  
  411.     % Determine the font metrics, in the PCL character coordinate system,
  412.     % which has +Y going towards the top of the page.
  413.  
  414.    gsave
  415.    FontMatrix concat
  416.      0 0 transform
  417.      negY round cvi /r0y exch def
  418.      round cvi /r0x exch def
  419.    ixbbox
  420.      negY /rury exch def  /rurx exch def
  421.      negY /rlly exch def  /rllx exch def
  422.      /rminx rllx rurx min def
  423.      /rminy rlly negY rury negY min def
  424.      /rw rurx rllx sub abs def
  425.      /rh rury rlly sub abs def
  426.    gsave rot neg rotate
  427.      0 0 transform
  428.      negY round cvi /u0y exch def
  429.      round cvi /u0x exch def
  430.    ixbbox
  431.      negY /uury exch def   /uurx exch def
  432.      negY /ully exch def   /ullx exch def
  433.      /uw uurx ullx sub def
  434.      /uh uury ully sub def
  435.    grestore
  436.    DEBUG 
  437.     { (rmatrix: ) print matrix currentmatrix ==
  438.       (rFontBBox: ) print [rllx rlly rurx rury] ==
  439.       (uFontBBox: ) print [ullx ully uurx uury] ==
  440.       flush
  441.     } if
  442.    grestore
  443.  
  444.     % Disable the character cache, to avoid excessive allocation
  445.     % and memory sandbars.
  446.  
  447.    mark cachestatus   /upper exch def
  448.    cleartomark 0 setcachelimit
  449.    
  450.     % Write the font header.
  451.  
  452.    writefontheader
  453.  
  454.     % Establish an image device for rasterizing characters.
  455.  
  456.    matrix currentmatrix
  457.      dup 4 rminx neg put
  458.      dup 5 rminy neg put
  459.     % Round the width up to a multiple of 8
  460.     % so we don't get garbage bits in the last byte of each row.
  461.    rw 7 add -8 and rh <ff 00> makeimagedevice
  462.      /cdevice exch def
  463.    nulldevice            % prevent page device switching
  464.    cdevice setdevice
  465.  
  466.     % Rasterize each character in turn.
  467.  
  468.    /raster   rw 7 add 8 idiv   def
  469.    /row   raster string   def
  470.    /zerow   row length string   def
  471.    0 1 Encoding length 1 sub
  472.     { /cindex exch def
  473.       Encoding cindex get /.notdef ne
  474.        { VDEBUG { Encoding cindex get == flush } if
  475.          erasepage initgraphics
  476.      0 0 moveto currentpoint transform add
  477.      ( ) dup 0 cindex put show
  478.      currentpoint transform add exch sub round cvi
  479.        /cwidth exch abs def
  480.      rw rh devbbox
  481.      VDEBUG
  482.       { (image bbox: ) print 4 copy 4 2 roll 4 array astore == flush
  483.       } if
  484.         % Save the device bounding box.
  485.         % Note that this is in current device coordinates,
  486.         % not PCL (right-handed) coordinates.
  487.      /bqx exch def  /bpx exch def  /bqy exch def  /bpy exch def
  488.         % Re-render with the character justified to (0,0).
  489.         % This may be either the lower left or the upper left corner.
  490.      bpx neg bpy neg idtransform moveto
  491.      erasepage
  492.      VDEBUG { (show point: ) print [ currentpoint transform ] == flush } if
  493.      ( ) dup 0 cindex put show
  494.         % Find the bounding box.  Note that xmin and ymin are now 0,
  495.         % xmax1 = xw, and ymax1 = yh.
  496.      rw rh devbbox
  497.        /xw exch def
  498.         % xmin or ymin can be non-zero only if the character is blank.
  499.        xw 0 eq
  500.         { pop }
  501.         { dup 0 ne { (Non-zero xmin! ) print = } { pop } ifelse }
  502.        ifelse
  503.        /yh exch def
  504.        yh 0 eq
  505.         { pop }
  506.         { dup 0 ne { (Non-zero ymin! ) print = } { pop } ifelse }
  507.        ifelse
  508.  
  509.      /xbw xw 7 add 8 idiv def
  510.      /xright raster 8 mul xw sub def
  511.         % Write the Character Code command.
  512.      outfile (\033*c) writestring
  513.      outfile cindex write==only
  514.      outfile (E) writestring
  515.          % Write the Character Definition command.
  516.      outfile (\033\(s) writestring
  517.      yh xbw mul 16 add
  518.      outfile exch write=only
  519.         % Record the character position for the .PCM file.
  520.      /cfpos outfile fileposition 1 add def
  521.      outfile (W\004\000\016\001) writestring
  522.      orientation (Orientation) wbyte 0 (Reserved) wbyte
  523.      rminx bpx add r0x sub (Left Offset) wword
  524.      flipY { rminy bpy add neg } { rminy bqy add } ifelse r0y sub
  525.        (Top Offset) wword
  526.      xw (Character Width) wword
  527.      yh (Character Height) wword
  528.      cwidth orientation 2 ge { neg } if 4 mul (Delta X) wword
  529.         % Write the character data.
  530.      flipY { 0 1 yh 1 sub } { yh 1 sub -1 0 } ifelse
  531.       { cdevice exch row copyscanlines
  532.         0 xbw getinterval
  533.         CDEBUG
  534.          { dup
  535.             { 8
  536.            { dup 128 ge { (+) } { (.) } ifelse print
  537.              127 and 1 bitshift
  538.            }
  539.           repeat pop
  540.             }
  541.            forall (\n) print
  542.          }
  543.         if
  544.         outfile exch writestring
  545.       }
  546.      for
  547.        }
  548.        { /bpx 0 def   /bpy 0 def   /bqx 0 def   /bqy 0 def
  549.      /cwidth 0 def
  550.      /cfpos 0 def
  551.        }
  552.       ifelse
  553.  
  554.     }
  555.    for
  556.  
  557.     % Wrap up.
  558.  
  559.    upper setcachelimit
  560.    outfile closefile
  561.  
  562.    nulldevice            % prevent page device switching
  563.    saved end end end restore
  564.  
  565.  } def
  566.  
  567. % Provide definitions for testing with older or non-custom interpreters.
  568.  
  569. /.findzeros where { pop (%END) .skipeof } if
  570. /.findzeros
  571.  { userdict begin   /zs exch def   /zl zs length def
  572.    0 { dup zl ge { exit } if dup zs exch get 0 ne { exit } if 1 add } loop
  573.    zl { dup 0 eq { exit } if dup 1 sub zs exch get 0 ne { exit } if 1 sub } loop
  574.    exch 3 bitshift exch 3 bitshift
  575.    2 copy lt
  576.     { exch zs 1 index -3 bitshift get
  577.        { dup 16#80 and 0 ne { exit } if exch 1 add exch 1 bitshift } loop pop
  578.       exch zs 1 index -3 bitshift 1 sub get
  579.        { dup 1 and 0 ne { exit } if exch 1 sub exch -1 bitshift } loop pop
  580.     }
  581.    if end
  582.  } bind def
  583. %END
  584.  
  585. /write=only where { pop (%END) .skipeof } if
  586. /w=s 128 string def
  587. /write=only
  588.  { w=s cvs writestring
  589.  } bind def
  590. %END
  591.  
  592. %**************** Test
  593. /PCLTEST where {
  594.   pop
  595.   /DEBUG true def
  596.   /CDEBUG true def
  597.   /VDEBUG true def
  598.   /Times-Roman findfont 10 scalefont setfont
  599.   (t.pcf) (w) file
  600.   300 72 div dup scale
  601.   300 writePCL
  602.   flush quit
  603. } if
  604.