From: jgm@cs.brown.edu (Jonathan Monsarrat)
Subject: PostScript -> ASCII  *and*  ASCII -> PostScript  programs
Organization: Brown University Department of Computer Science
Date: Thu, 1 Oct 1992 16:57:05 GMT

Somebody want to stick revised parts of this in the FAQ?

-Jon Monsarrat                     Two roads diverged in a wood, and I -
 Brown University                      I took the one marked "Free Food"
                                   And that has made all difference.
---------------------------------
In general, when you say
  "I want to convert PostScript to ASCII"

what you really mean is

  "I want to convert MacWrite (which makes PostScript output) to ASCII"

or
  "I want to convert somebody's TeX document (which I have in
   PostScript)  to ASCII"

Unfortunately, programs like these (if they're smart) do a lot of
fancy stuff like kerning, which means that where they would normally
execute the postscript command for

    "print water buffalo"

instead they execute the postscript command for

    "print wat"      (move a little to get the spacing *just* right)
    "print er"       (move a little to get the spacing *just* right)
    "print buff"     (move a little to get the spacing *just* right)
    "print alo"      (move a little to get the spacing *just* right)

So if I write a program to look through a PostScript file for strings,
like this:

--------------------------------------------------------

#! /usr/local/bin/perl -P
########################################################
# ps2ascii: look through a PostScript file for ASCII strings
#
# Usage:
#     ps2ascii <inputfile.ps>
#
# Somebody wanna enhance this to do "\)" properly?
########################################################

$out = "";
while(<>)
{
  $line = $_;
  while($line =~/\((.*)\)(.*)/) {
       $line = $2;
       if(length($out)+length($1) > 76) {
         print "$out\n";
         $out="";
       }
       $out=$out." ".$1;
  }
}
print "$out\n";


--------------------------------------------------------

It can't tell where the words really end. Here my program
would see 4 strings

"wat" "er" "buff" "alo"

And it doesn't see any difference between the spacing between "buff"
and "alo" (not a word break) and the spacing between "er" and "buff"
(a real word break).

The problem is that PostScript for text formatting is usually produced
machine generated by a text formatter. A PostScript generator like "dvips"
might have a special command like "boop" that differentiates between a
real world break and a fake one. But every text formatter that
generates PostScript has their own name for the "boop" command.

So you really want a "PostScript -> ASCII converter for dvips output".

---------------------------------------------------------

The only general solution I can see would be to redefine the show
operator to print out the currentpoint for every letter being printed,
like this

%!
%% Prepend this to your PostScript program and
%% run it through an on-line interpreter (not a printer!)
%% Then run it through a program that places everything nicely
%% onto an ASCII page given the ascii value and (x y) coordinates.
%% (this program is not included) Documentation?? Read the code! :)
/show{
     dup length 1 sub 0 1 3 -1 roll
     {
       currentpoint = =
       1 index exch
       1 getinterval
       dup show {} forall =
     } for pop
} bind def
/showpage { (New Page!\n) print showpage } bind def

and then make up an ASCII page based on this by sticking ASCII
characters where they go in a two-dimensional array. That would
convert PostScript to ASCII "formatted".

Somebody want to write this? I haven't got time.

---------------------------------------------------------

But even that wouldn't solve the problem, because special bitmap fonts
and and standard fonts like Symbol don't always print a "P" when you
say the letter "P". Sometimes they print the greek Pi symbol or a
chess piece or a ZapfDingBat.

---------------------------------------------------------

If anyone is interested, here is an interesting program written by
Professor John Hughes here at Brown University that formats ASCII
in PostScript without a machine generator of any kind.

Sometime later I'm going to incorporate this into LameTeX so you can
write documents in simple LaTeX without ever running a program! You
would just append your simple .tex document to the end of a PostScript
program. Wish me luck.

(plug: LameTeX formats LaTeX with fancy sideways criss-cross graphics.
Try it at wilma.cs.brown.edu (128.148.31.66) as "pub/lametex.tar.Z")

-----------------------------------------------------------
%!
%%%
%%% Plan:
%%% Start with an empty string.
%%% For each character in the input stream, 
%%%    check to see if it's a carriage return.
%%%    if so, show the current string and reset it to empty
%%%    if not, add it to the current string.

/Courier findfont 10 scalefont setfont  %% Choose a fixed width font
/lineheight 
currentfont /FontBBox get dup     	%% bbox bbox
0 2 getinterval				%% bbox {xm ym}
exch					%% {xm ym} bbox
2 2 getinterval				%% {xm ym} {xM yM}
aload pop				%% {xm ym} xM yM
3 2 roll 				%% xM yM {xm ym}
aload pop
currentfont /FontMatrix get		%% xM yM xm ym MAT
transform				%% xM yM xm' ym'
4 2 roll
currentfont /FontMatrix get		%% xm' ym' xM yM MAT
transform				%% xm' ym' xM' yM'
exch pop 				%% xm' ym' yM'
sub					%% xm' ym'-yM'
exch pop				%% dy
neg def 

lineheight pstack pop

/str 500 string def			%% Room to store a long string...
/empty 500 string def			%% An empty string to work with
/stringindex 0 def			%% How far we've filled the string
/inch {72 mul } def			%% A useful tool...
/pageheight 11 inch def
/topmargin 1 inch def
/botmargin 1 inch def
/leftmargin 1 inch def
/linesperpage pageheight topmargin sub botmargin sub lineheight div cvi def
/linenumber 1 def			%% the line we're about to write on

/newline { 		%% move to a new line; flush page if necessary
   linenumber linesperpage gt {/linenumber 1 def showpage } if
   leftmargin pageheight topmargin sub linenumber lineheight mul sub moveto
   /linenumber linenumber 1 add def
} def

/cleanup {		%% print out the last bit of whatever you had there...
   str show showpage
} def

/startstring {		%% empty the string and reset its counter.
   str 0 empty putinterval
   /stringindex 0 def
} def

/showstring {		%% print the string on a new line and flush it
   newline
   str show 
   startstring
} def

pstack 

/addtostring {		%% put another character in the string, if there's room
   dup 500 gt {pop}{str exch stringindex exch put
   /stringindex stringindex 1 add def} ifelse
} def

%
% Main program: get characters and deal with them
%
{
   currentfile read {}{cleanup exit} ifelse
   dup 10 eq                   %% if it's a carriage return...
      {pop showstring}         %% write out this line of text and start over
      {dup 0 eq 	       %% if it's an end-of-file mark...
       {exit}	               %% stop!
       {addtostring}           %% otherwise, add the character to current string
       ifelse}
      ifelse                   %% Sample data follows.
} loop


This text should print out
You can put any text here you want to.
It's effectively "verbatim" mode.
Handles page breaks and margins.
Documentation?? Read the code! :)