home *** CD-ROM | disk | FTP | other *** search
/ swCHIP 1991 January / swCHIP_95-1.bin / utility / gs333ini / gs3.33 / ps2ascii.ps < prev    next >
Text File  |  1995-12-09  |  16KB  |  488 lines

  1. %    Copyright (C) 1991, 1995 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. % Extract the ASCII text from a PostScript file.  Nothing is displayed.
  16. % Instead, ASCII information is written to stdout.  The idea is similar to
  17. % Glenn Reid's `distillery', only a lot more simple-minded, and less robust.
  18.  
  19. % If SIMPLE is defined, just the text is written, with a guess at line
  20. % breaks and word spacing.  If SIMPLE is not defined, lines are written
  21. % to stdout as follows:
  22. %
  23. %    C <r> <g> <b>
  24. %        Indicate the current color. (NOT IMPLEMENTED YET)
  25. %
  26. %    F <height> <width> (<fontname>)
  27. %        Indicate font height and width of a space.
  28. %
  29. %    P
  30. %        Indicate the end of the page.
  31. %    R <x> <y> <width> <height>
  32. %        Display a rectangle. (NOT IMPLEMENTED YET)
  33. %
  34. %    S <x> <y> (<string>) <width>
  35. %        Display a string.
  36. %
  37. % <r>, <g>, and <b> are RGB values expressed as integers between 0 and 1000.
  38. % <width> and <height> are integer dimensions in units of 1/720".
  39. % <x> and <y> are integer coordinates, in units of 1/720", with the origin
  40. %   at the lower left.
  41. % <string> and <fontname> are strings represented with the standard
  42. %   PostScript escape conventions.
  43. % Note that future versions of this program may add other output elements,
  44. %   so programs parsing the output should be prepared to ignore elements
  45. %   that they do not recognize.
  46.  
  47. % Note that this code will only work in all cases if systemdict is writable
  48. % and if `binding' the definitions of operators defined as procedures
  49. % is deferred.  For this reason, it is normally invoked with
  50. %    gs -q -dNODISPLAY -dNOBIND -dWRITESYSTEMDICT ps2ascii.ps
  51.  
  52. % Thanks to J Greely <jgreely@cis.ohio-state.edu> for improvements
  53. % to this code, and to Jerry Whelan <jerryw@abode.ccd.bnl.gov> for
  54. % motivating other improvements.
  55.  
  56. /QUIET true def
  57. systemdict wcheck { systemdict } { userdict } ifelse begin
  58. /.max where { pop } { /.max { 2 copy lt { exch } if pop } bind def } ifelse
  59. /SIMPLE dup where { pop true } { false } ifelse def
  60. /setglobal where
  61.  { pop currentglobal /setglobal load true setglobal }
  62.  { { } }
  63. ifelse
  64.  
  65. % Define a way to store and retrieve integers that survives save/restore.
  66. /.i.string0 (0               ) def
  67. /.i.string .i.string0 length string def
  68. /.iget { cvi } bind def
  69. /.iput { exch //.i.string exch copy cvs pop } bind def
  70. /.inew { //.i.string0 dup length string copy } bind def
  71.  
  72. % Disable the display operators.
  73.  
  74. /eofill { newpath } odef
  75. /erasepage { } odef
  76. /fill { newpath } odef
  77. /stroke { newpath } odef
  78.  
  79. % The image operators must read the input, but do nothing.
  80.  
  81. /colorimage where
  82.  { pop /colorimage { gsave nulldevice //colorimage grestore } odef
  83.  } if
  84. /image { gsave nulldevice //image grestore } odef
  85. /imagemask { gsave nulldevice //imagemask grestore } odef
  86.  
  87. % Redefine the end-of-page operators.
  88.  
  89. /copypage { SIMPLE { (\014) } { (P\n) } ifelse //print } odef
  90. /showpage { copypage erasepage initgraphics } odef
  91.  
  92. % Output the current color if necessary.
  93. /.color.r .inew def
  94.   .color.r -1 .iput        % make sure we write the color at the beginning
  95. /.color.g .inew def
  96. /.color.b .inew def
  97. /.showcolor
  98.  { SIMPLE not
  99.     { currentrgbcolor
  100.       1000 mul round cvi
  101.       3 1 roll 1000 mul round cvi
  102.       exch 1000 mul round cvi
  103.         % Stack: b g r
  104.       dup //.color.r .iget eq
  105.       2 index //.color.g .iget eq and
  106.       3 index //.color.b .iget eq and
  107.        { pop pop pop
  108.        }
  109.        { (C ) //print
  110.      dup //.color.r exch .iput .show==only
  111.          ( ) //print dup //.color.g exch .iput .show==only
  112.          ( ) //print dup //.color.b exch .iput .show==only
  113.      (\n) //print
  114.        }
  115.       ifelse
  116.     }
  117.    if
  118.  } bind def
  119. % Some programs that interpret the output of ps2ascii aren't prepared to
  120. % handle the C command, so ****** WE DISABLE IT ******.
  121. /.showcolor { } def
  122.  
  123. % Redefine `show'.
  124.  
  125. % Set things up so our output will be in tenths of a point, with origin at
  126. % lower left.  This isolates us from the peculiarities of individual devices.
  127.  
  128. /.show.ident.matrix matrix def
  129. /.show.ident
  130. % { //.show.ident.matrix defaultmatrix
  131. %        % Assume the original transformation is well-behaved.
  132. %   0.1 0 2 index dtransform abs exch abs .max /.show.scale exch def
  133. %   0.1 dup 3 -1 roll scale
  134.  { gsave initmatrix
  135.         % Assume the original transformation is well-behaved.
  136.    0.1 0 dtransform abs exch abs .max /.show.scale exch def
  137.    0.1 dup scale .show.ident.matrix currentmatrix
  138.    grestore
  139.  } bind def
  140. /.coord
  141.  { transform .show.ident itransform
  142.    exch round cvi exch round cvi
  143.  } odef
  144. /.dcoord
  145.  {        % Transforming distances is trickier, because
  146.         % the coordinate system might be rotated.
  147.    .show.ident pop
  148.    exch 0 dtransform
  149. %     dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  150. dup mul exch dup mul add sqrt
  151.      .show.scale div round cvi
  152.    exch 0 exch dtransform
  153. %     exch dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  154. dup mul exch dup mul add sqrt
  155.      .show.scale div round cvi
  156.  } odef
  157.  
  158. % Remember the current X, Y, and height.
  159. /.show.x .inew def
  160. /.show.y .inew def
  161. /.show.height .inew def
  162. % Remember the last character of the previous string; if it was a
  163. % hyphen preceded by a letter, we didn't output the hyphen.
  164. /.show.last (\000) def
  165. % Remember the current font.
  166. /.font.name 130 string def
  167. /.font.name.length .inew def
  168. /.font.height .inew def
  169. /.font.width .inew def
  170.  
  171. % We have to redirect stdout somehow....
  172. /.show.stdout { (%stdout) (w) file } bind def
  173.  
  174. % Make sure writing will work even if a program uses =string.
  175. /.show.string =string length string def
  176. /.show.=string =string length string def
  177. /.show==only
  178.  { //=string //.show.=string copy pop
  179.    dup type /stringtype eq
  180.     { dup length //.show.string length le
  181.        { dup rcheck { //.show.string copy } if
  182.        } if
  183.     } if
  184.    .show.stdout exch write==only
  185.    //.show.=string //=string copy pop
  186.  } odef
  187.  
  188. /.showfont    % <string> .showfont <string>
  189.  { gsave
  190.     % Try getting the height and width of the font from the FontBBox.
  191.      currentfont /FontBBox .knownget not { {0 0 0 0} } if
  192.      aload pop exch 4 -1 roll sub 3 1 roll exch sub
  193.      2 copy .max 0 ne
  194.       { currentfont /FontMatrix get dtransform
  195.       }
  196.       {    pop pop
  197.     % Fonts produced by dvips, among other applications, have
  198.     % BuildChar procedures that bomb out when given unexpected
  199.     % characters, and there is no way to determine whether a given
  200.     % character will do this.  So for Type 1 fonts, we measure a
  201.     % typical character ('X'); for others, we punt.
  202.     currentfont /FontType get 1 eq
  203.      { (X) stringwidth pop dup 1.3 mul
  204.      }
  205.      {    % No safe way to get the character size.  Punt.
  206.        0 0
  207.      }
  208.     ifelse
  209.       }
  210.      ifelse .dcoord exch
  211.      currentfont /FontName .knownget not { () } if
  212.      dup type /stringtype ne { //.show.string cvs } if
  213.    grestore
  214.     % Stack: height width fontname
  215.    SIMPLE
  216.     { pop pop //.show.height exch .iput }
  217.     { 2 index //.font.height .iget eq
  218.       2 index //.font.width .iget eq and
  219.       1 index //.font.name 0 //.font.name.length .iget getinterval eq and
  220.        { pop pop pop
  221.        }
  222.        { (F ) //print
  223.      3 -1 roll dup //.font.height exch .iput .show==only ( ) //print
  224.          exch dup //.font.width exch .iput .show==only ( ) //print
  225.      dup length //.font.name.length exch .iput
  226.          //.font.name cvs .show==only (\n) //print
  227.        }
  228.       ifelse
  229.     }
  230.    ifelse
  231.  } odef
  232.  
  233. % Define the letters -- characters which, if they occur followed by a hyphen
  234. % at the end of a line, cause the hyphen and line break to be ignored.
  235. /.letter.chars 100 dict def
  236. mark
  237.   65 1 90 { dup 32 add } for
  238. counttomark { StandardEncoding exch get .letter.chars exch dup put } repeat
  239. pop
  240.  
  241. % Define a set of characters which, if they occur at the start of a line,
  242. % are taken as indicating a paragraph break.
  243. /.break.chars 50 dict def
  244. mark
  245.   /bullet /dagger /daggerdbl /periodcentered /section
  246. counttomark { .break.chars exch dup put } repeat
  247. pop
  248.  
  249. % Define character translation to ASCII.
  250. % We have to do this for the entire character set.
  251. /.char.map 500 dict def
  252. /.chars.def { counttomark 2 idiv { .char.map 3 1 roll put } repeat pop } def
  253.     % Encode the printable ASCII characters.
  254. mark 32 1 126
  255.  { 1 string dup 0 4 -1 roll put
  256.    dup 0 get StandardEncoding exch get exch
  257.  }
  258. for .chars.def
  259.     % Encode accents.
  260. mark
  261.   /acute (') /caron (^) /cedilla (,) /circumflex (^)
  262.   /dieresis (") /grave (`) /ring (*) /tilde (~)
  263. .chars.def
  264.     % Encode the ISO accented characters.
  265. mark 192 1 255
  266.  { ISOLatin1Encoding exch get =string cvs
  267.    dup 0 1 getinterval 1 index dup length 1 sub 1 exch getinterval
  268.    .char.map 2 index known .char.map 2 index known and
  269.     { .char.map 3 -1 roll get .char.map 3 -1 roll get concatstrings
  270.       .char.map 3 1 roll put
  271.     }
  272.     { pop pop pop
  273.     }
  274.    ifelse
  275.  }
  276. for .chars.def
  277.     % Encode the remaining standard and ISO alphabetic characters.
  278. mark
  279.   /AE (AE) /Eth (DH) /OE (OE) /Thorn (Th)
  280.   /ae (ae) /eth (dh)
  281.   /ffi (ffi) /ffl (ffl) /fi (fi) /fl (fl)
  282.   /germandbls (ss) /oe (oe) /thorn (th)
  283. .chars.def
  284.     % Encode the other standard and ISO characters.
  285. mark
  286.   /brokenbar (|) /bullet (*) /copyright ((C)) /currency (#)
  287.   /dagger (#) /daggerdbl (##) /degree (o) /divide (/) /dotaccent (.)
  288.   /dotlessi (i)
  289.   /ellipsis (...) /emdash (--) /endash (-) /exclamdown (!)
  290.   /florin (f) /fraction (/)
  291.   /guillemotleft (<<) /guillemotright (>>)
  292.   /guilsingleft (<) /guilsingright (>) /hungarumlaut ("") /logicalnot (~)
  293.   /macron (_) /minus (-) /mu (u) /multiply (*)
  294.   /ogonek (,) /onehalf (1/2) /onequarter (1/4) /onesuperior (1)
  295.   /ordfeminine (-a) /ordmasculine (-o)
  296.   /paragraph (||) /periodcentered (*) /perthousand (o/oo) /plusminus (+-)
  297.   /questiondown (?) /quotedblbase (") /quotedblleft (") /quotedblright (")
  298.   /quotesinglbase (,) /quotesingle (') /registered ((R))
  299.   /section ($) /sterling (#)
  300.   /threequarters (3/4) /threesuperior (3) /trademark ((TM)) /twosuperior (2)
  301.   /yen (Y)
  302. .chars.def
  303.     % Encode a few common Symbol characters.
  304. mark
  305.   /asteriskmath (*) /copyrightsans ((C)) /copyrightserif ((C))
  306.   /greaterequal (>=) /lessequal (<=) /registersans ((R)) /registerserif ((R))
  307.   /trademarksans ((TM)) /trademarkserif ((TM))
  308. .chars.def
  309.  
  310. % Write out a string.  If it ends in a letter and a hyphen,
  311. % don't write the hyphen, and set .show.last to a hyphen;
  312. % otherwise, set .show.last to the character (or \000 if it was a hyphen).
  313. /.show.write    % <string>
  314.  { dup length 1 ge
  315.     { dup dup length 1 sub get
  316.       dup 45 eq        % hyphen
  317.        { 1 index length 1 gt
  318.           { 1 index dup length 2 sub get }
  319.       { //.show.last 0 get }
  320.      ifelse
  321.      currentfont /Encoding get exch get
  322.      //.letter.chars exch known
  323.       {    % Remove the hyphen
  324.         exch dup length 1 sub 0 exch getinterval exch
  325.       }
  326.       { pop 0
  327.       }
  328.      ifelse
  329.        }
  330.       if
  331.       //.show.last 0 3 -1 roll put
  332.     }
  333.    if
  334.     { dup currentfont /Encoding get exch get
  335.       dup //.char.map exch .knownget
  336.        { .show.stdout exch writestring pop pop
  337.        }
  338.        { currentfont /Encoding dup StandardEncoding eq
  339.      exch ISOLatin1Encoding eq or
  340.       {    % Untranslated character in standard encoding
  341.         pop .show.stdout exch write
  342.       }
  343.       {    % Character in non-standard encoding, substitute
  344.         pop pop .show.stdout (*) writestring
  345.       }
  346.      ifelse
  347.        }
  348.       ifelse
  349.     }
  350.    forall
  351.  } odef
  352. /.showstring1
  353.  { currentpoint .coord
  354.    3 -1 roll dup stringwidth 1 index 0 rmoveto
  355.    .dcoord pop
  356.     % Stack: x y string width
  357.    SIMPLE
  358.     { 2 index //.show.y .iget ne
  359.        {    % Try to figure out whether we have a line break
  360.         % or a paragraph break.
  361.      2 index //.show.y .iget sub abs
  362.      //.show.height .iget 1.3 mul ge
  363.      2 index length 0 gt
  364.       { 2 index 0 get currentfont /Encoding get exch get
  365.         //.break.chars exch known { pop true } if
  366.       }
  367.      if
  368.       { (\n\n)    % Paragraph
  369.       }
  370.       { ( )        % Line
  371.       }
  372.      ifelse //print
  373.      //.show.y 3 index .iput
  374.          //.show.x 4 index .iput
  375.        }
  376.        {    % If the word processor split a hyphenated word within
  377.         % the same line, put out the hyphen now.
  378.      //.show.last 0 get 45 eq { (-) //print } if
  379.        }
  380.       ifelse
  381.       3 index //.show.x .iget 10 add gt
  382.        { ( ) //print
  383.        }
  384.       if
  385.       4 1 roll .show.write pop add //.show.x exch .iput
  386.     }
  387.     { (S ) //print
  388.       4 -1 roll .show==only ( ) //print
  389.       3 -1 roll .show==only ( ) //print
  390.       exch .show==only ( ) //print
  391.       .show==only (\n) //print
  392.     }
  393.    ifelse
  394.  } odef
  395. /.showstring
  396.  { dup () eq { pop } { .showstring1 } ifelse
  397.  } bind def
  398.      
  399. % Redefine all the string display operators.
  400.  
  401. /show
  402.  { .showfont .showcolor .showstring
  403.  } odef
  404.  
  405. % We define all the other operators in terms of .show1.
  406. /.show1.string ( ) def
  407. /.show1 { //.show1.string exch 0 exch put //.show1.string .showstring } odef
  408. /ashow
  409.  { .showfont .showcolor
  410.    { .show1 2 copy rmoveto } forall
  411.    pop pop
  412.  } odef
  413. /awidthshow
  414.  { .showfont .showcolor
  415.     { dup .show1 4 index eq { 4 index 4 index rmoveto } if
  416.       2 copy rmoveto
  417.     }
  418.    forall
  419.    pop pop pop pop pop
  420.  } odef
  421. /widthshow
  422.  { .showfont .showcolor
  423.    //.show1.string 0 4 -1 roll put
  424.     { //.show1.string search not { exit } if
  425.       .showstring .showstring
  426.       2 index 2 index rmoveto
  427.     } loop
  428.    .showstring pop pop
  429.  } odef
  430. /kshow
  431.  { .showfont .showcolor
  432.     { .show1 dup exec } forall pop
  433.  } odef
  434. % We don't really do the right thing with the Level 2 show operators,
  435. % but we do something semi-reasonable.
  436. /xshow where
  437.  { pop /xshow { pop show } bind odef
  438.  } if
  439. /yshow where
  440.  { pop /yshow { pop show } bind odef
  441.  } if
  442. /xyshow where
  443.  { pop /xyshow { pop show } bind odef
  444.  } if
  445. /glyphshow where
  446.  { pop /glyphshow
  447.     { currentfont /Encoding .knownget not { {} } if
  448.       0 1 2 index length 1 sub
  449.        {    % Stack: glyph encoding index
  450.      2 copy get 3 index eq { exch pop exch pop null exit } if
  451.        }
  452.       for null eq { (X) dup 0 4 -1 roll put show } { pop } ifelse
  453.     } bind odef
  454.  } if
  455.  
  456. % Redirect the printing operators.
  457.  
  458. /.stdout (_temp_.out) (w) file def
  459. /.stderr (_temp_.err) (w) file def
  460. /print { //.stdout exch writestring } odef
  461. /=only { //.stdout exch write=only } odef
  462. /==only { //.stdout exch write==only } odef
  463.  
  464. end
  465.  
  466. % Bind the operators we just defined, and all the others if we didn't
  467. % do it before.  Also reenable 'bind' for future files.
  468.  
  469. .bindoperators
  470. NOBIND currentdict systemdict ne and
  471.  { systemdict begin .bindoperators end }
  472. if
  473. NOBIND
  474.  { /bind /.bind load def }
  475. if
  476.  
  477. % Make systemdict read-only if it wasn't already.
  478.  
  479. systemdict wcheck { systemdict readonly pop } if
  480.  
  481. % Restore the current local/global VM mode.
  482.  
  483. exec
  484.