home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / Vyzkuste / gs / gs650w32.exe / gs6.50 / lib / font2pcl.ps < prev    next >
Text File  |  2000-12-05  |  18KB  |  606 lines

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