home *** CD-ROM | disk | FTP | other *** search
/ jppd.dyndns.org / jppd.dyndns.org.tar / jppd.dyndns.org / QUERYPRO / Impressora_PDF / converter.exe / GPLGS / font2pcl.ps < prev    next >
Text File  |  2002-06-03  |  18KB  |  604 lines

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