greenber@swatsun (Peter Greenberg) (04/18/87)
Have FUN with your LaserWriter Plus or other PostScript creature!!! I have written a few programs that play with PostScript in interesting ways. I have wrapped these up as shell scripts that take arguments to determine what is printed. The README file will give the necessary details, but before reading it, unpack and type these lines from your shell, just for kicks. You will not sorry. fontnames -- You will get a page out of your PS creature giving names of each font that is knows about printed in the font that it denotes. Boring, but possibly useful. mapfonts Times-Roman ZapfDingbats -- If you don't have these fonts, use the names of ones that you do have. (LaserWriter Plus has them.) ZapfDingbats has no letters, Roman, Greek, or otherwise. It was shown as the line of bizarre symbols when you ran fontnames above. Your PS creature will hand you a page with a few columns. Octal character codes will be matched to characters in each font. Still boring, but a bit more useful. fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats '\244' 0.85 -- Again, change fonts and '\244' to some letter if you do not have the fonts. I don't feel like explaining it. Do it and then show it to your friends. Look up octal character 244 on the sheet from mapfonts to get a clue. scaleshow '\360' Symbol 600 7 -- Most things have the Symbol font. Just do it to see what happens. If you do not have a LaserWriter, you might want to try '\251' instead. I also threw in a bunch of useful and useless PostScript routines in a file called template.ps Peter Greenberg Swarthmore College Swarthmore, PA 19081 ...!seismo!bpa!swatsun!greenber ------------------------SNIP SNIP SNIP------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # README% # fillchar # fontnames # mapfont # scaleshow # template.ps # This archive created: Sat Apr 18 17:27:53 1987 export PATH; PATH=/bin:$PATH if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' README file This posting contains 5 files. template.ps is a file of neat little PostScript procedures that handle centering, flush right, and wrapping of text, and some other stuff. Comments within say what is really going on. The other four are small PostScript applications wrapped up in shell scripts. They take zero or more command line arguments, and print some kind of pretty picture. They currently use lpr as the spooler. If you do not have lpr, then you should go through and change the variable called "spooler" which is set near the top of the program. You should be aware that the shell "wrappings" of these programs are not robust. Error checking beyond number of parameters is not performed. They are basically just nice ways of spooling PostScript programs. If you do not have the Bourne shell, then clip out the shell stuff, and reconstruct some real PostScript program. Note that if a font is not defined on your device, what PostScript does is device dependent. On the LaserWriter, it defaults the font to Courier. To find out which fonts you have, run fontnames first (see below). Also note that where a string is called for, PostScript strings without the parentheses are taken. Therefore, you can use all the backslash escapes understood by PostScript. All the "Try this:" suggestions below assume you are using a LaserWriter Plus. Enter the stuff after the colon on these lines exactly as shown. This is what these things do: fillchar InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel [Type the above all on one line!] Prints ShapeStr in font given by ShapeStrFontName and size Size as an outline, then fills it with gray of level GrayLevel (1 = white, 0 = black), then writes InsideText repeatedly in font given by InsideTextFontName within the outline to fill up Lines lines of text. The size that InsideText is printed in is figured out in PostScript. If ShapeStr is to long, PostScript might think that the path that it defines is too complicated to be a clipping path and it will bomb with a limit check error. Try this: fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats '\244' 0.85 fontnames Prints the name of each font known to PostScript in that font. One font name is printed per line. Try this: fontnames mapfont [font1 [font2]] Maps one font to another. Prints octal character code, character in font1, and character in font2 for each ASCII code between 0 and 255. If only one font is given, the mapping is from Courier to that font, if none are given than it is from Courier to Helvetica. Try this: mapfont Times-Roman ZapfDingbats scaleshow String Font Size LinesInScale Fills a shape given by String in font Font and size Size (that is, the shapes of the characters if they were so pritned) with a grayscale with LinesInScale gradations. Light gray is on top, dark gray on the bottom. PostScript limit check error is possible for large String. Try this: scaleshow '\360' Symbol 600 7 SHAR_EOF fi # end of overwriting check if test -f 'README%' then echo shar: will not over-write existing file "'README%'" else cat << \SHAR_EOF > 'README%' README file This posting contains 5 files. template.ps -- file of neat little PostScript procedures that handle centering, flush right, and wrapping of text, and some other stuff. Comments within say what is really going on. The other four are small PostScript applications wrapped up in shell scripts. They take zero or more command line arguments, and print some kind of pretty picture. They currently use lpr as the spooler. If you do not have lpr, then you should go through and change the variable called "spooler" which is set near the top of the program. You should be aware that the shell "wrappings" of these programs are not robust. Error checking beyond number of parameters is not performed. They are basically just nice ways of spooling PostScript programs. If you do not have the Bourne shell, then clip out the shell stuff, and reconstruct some real PostScript program. Note that if a font is not defined on your device, what PostScript does is device dependent. On the LaserWriter, it defaults the font to Courier. To find out which fonts you have, run fontnames first (see below). Also note that where a string is called for, PostScript strings without the parentheses are taken. Therefore, you can use all the backslash escapes understood by PostScript. All the "Try this:" suggestions below assume you are using a LaserWriter Plus. Enter the stuff after the colon on these lines exactly as shown. This is what these things do: fillchar InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel [Type the above all on one line!] Prints ShapeStr in font given by ShapeStrFontName and size Size as an outline, then fills it with gray of level GrayLevel (1 = white, 0 = black), then writes InsideText repeatedly in font given by InsideTextFontName within the outline to fill up Lines lines of text. The size that InsideText is printed in is figured out in PostScript. If ShapeStr is to long, PostScript might think that the path that it defines is too complicated to be a clipping path and it will bomb with a limit check error. Try this: fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats '\244' 0.85 fontnames Prints the name of each font known to PostScript in that font. One font name is printed per line. Try this: fontnames mapfont [font1 [font2]] Maps one font to another. Prints octal character code, character in font1, and character in font2 for each ASCII code between 0 and 255. If only one font is given, the mapping is from Courier to that font, if none are given than it is from Courier to Helvetica. Try this: mapfont Times-Roman ZapfDingbats scaleshow String Font Size LinesInScale Fills a shape given by String in font Font and size Size (that is, the shapes of the characters if they were so pritned) with a grayscale with LinesInScale gradations. Light gray is on top, dark gray on the bottom. PostScript limit check error is possible for large String. Try this: scaleshow '\360' Symbol 600 7 SHAR_EOF fi # end of overwriting check if test -f 'fillchar' then echo shar: will not over-write existing file "'fillchar'" else cat << \SHAR_EOF > 'fillchar' #! /bin/sh # This is a PostScript program wrapped as a shell script. # copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this # work freely so long as this message and the copyright message are retained. # comments/bug fixes to: # Peter Greenberg # Swarthmore College # Swarthmore, PA 19081 # (215) 328-8610 # UUCP: ...!seismo!bpa!swatsun!greenber # ARPA: swatsun!greenber@seismo.CSS.GOV # CHANGE THESE LINES TO USE ANTOHER SPOOLER spooler=/usr/ucb/lpr spoolopts=-PPostScript # Except for number of arguments (7), no checking done in shell. Specifically, # arguments 3 and 4 must be integers, 7 must be real beween 0 and 1. If these # conditions are not met, PostScript errors will result. emit_header() { cat <<End-Of-Header %! /InsideTextFontName /$1 def /InsideText ($2) def /Lines $3 def /Size $4 def /ShapeStrFontName /$5 def /ShapeStr ($6) def /GrayLevel $7 def End-Of-Header } emit_main_stuff() { cat <<End-Of-Main-Stuff % This program prints some string repeatedly within the path defined by some % other string. /FillWithText { % /grayness exch def % background color /c exch def % string defining clipping path /cfont exch def % font of string defining clipping path /size exch def % size of outline string shape /lines exch def % number of lines within shape /str exch def % string to be repeated within shape /sfont exch def % font of str gsave size srand % we will need random numbers later cfont findfont size scalefont setfont c true charpath % set up clipping path gsave stroke grestore % stroke and fill with background color gsave grayness setgray fill grestore pathbbox % get bounding box /ury exch def /urx exch def /lly exch def % strings should start left of box str stringwidth pop sub /llx exch def /lineht ury lly sub lines div def /cury ury lineht sub def clip % do the clipping sfont findfont lineht scalefont setfont % nested loop to print text in box { llx rand str stringwidth pop cvi mod add cury moveto { str show ( ) stringwidth pop 2 div 0 rmoveto currentpoint pop urx ge {exit} if } loop /cury cury lineht sub def cury lly le {exit} if } loop grestore } def 40 40 moveto InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel FillWithText showpage End-Of-Main-Stuff } case $# in 7) ;; *) echo usage: ; echo $0 InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel ; exit 1 ;; esac (emit_header $@ ; emit_main_stuff) | $spooler $spoolopts exit 0 SHAR_EOF chmod +x 'fillchar' fi # end of overwriting check if test -f 'fontnames' then echo shar: will not over-write existing file "'fontnames'" else cat << \SHAR_EOF > 'fontnames' #! /bin/sh # PostScript program wrapped up in a Bourne Shellscript. # copyright 1987 by Peter Greenberg. # This stuff can be used, copied modified, and incorporated into other works # so long as this message and the copyright message are retained. # comments/bug fixes to: # Peter Greenberg # Swarthmore College # Swarthmore, PA 19081 # (215) 328-8610 # UUCP: ...!seismo!bpa!swatsun!greenber # ARPA: swatsun!greenber@seismo.CSS.GOV spooler=/usr/ucb/lpr spoolopts=-PPostScript emit_main_stuff() { cat <<End-Of-Main-Stuff %! % Just a little hack to show the name of each font printed in that font. % Of course, non-alphabetic fonts will look strange. Will print the name % of each font that PostScript knows about, one to a line. % This program takes a while to run on an LW+. /Font %fontname scale { /scale exch def findfont scale scalefont setfont } def /Size 15 def /Lineheight Size 3 add def /Leftmargin 30 def /Topmargin 770 def /Showinfont % string fontname { Leftmargin currentpoint exch pop Lineheight sub moveto Size Font show } def Leftmargin Topmargin moveto FontDirectory { pop dup 256 string cvs exch Showinfont } forall showpage End-Of-Main-Stuff } emit_main_stuff | $spooler $spoolopts exit 0 SHAR_EOF chmod +x 'fontnames' fi # end of overwriting check if test -f 'mapfont' then echo shar: will not over-write existing file "'mapfont'" else cat << \SHAR_EOF > 'mapfont' #! /bin/sh # This is a PostScript program wrapped as a shell script. # copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this # work freely so long as this message and the copyright message are retained. # comments/bug fixes to: # Peter Greenberg # Swarthmore College # Swarthmore, PA 19081 # (215) 328-8610 # UUCP: ...!seismo!bpa!swatsun!greenber # ARPA: swatsun!greenber@seismo.CSS.GOV # USAGE: # mapfont [mapfrom [mapto]] # defaults: mapfrom=Courier ; mapto=Helvetica # CHANGE THESE LINES TO USE ANTOHER SPOOLER spooler=/usr/ucb/lpr spoolopts=-PPostScript emit_header() { cat <<End-Of-Header %! /Font1 /$1 def /Font2 /$2 def End-Of-Header } emit_main_stuff() { cat <<End-Of-Main-Stuff % This program maps one PostScript font to another. For each character % code in a specific range, this program will print (to the actual page) % the character code in octal, the character in Font1, then the character % in Font2. The reason for this is to show which characters are associated % with which ASCII codes in each font. It is especially useful to see what % non-alphabetical fonts like Symbol and ZapfDingbats have to offer. % The output is in neat columns, determined by taking into account the % left and right margins and top and bottom margins and the pitch of the % characters. Presently these are set to produce a nice looking 8.5 x 11 inch % page but this can be fiddled with. % Unfortunately, this program takes about 3 minutes to execute on an LW+. /ArrayToStr { /Array exch def /Length Array length def /Str Length string def 0 1 Length 1 sub { Str exch dup Array exch get put } for Str } bind def /IntToChar %char is a one character string { /Int exch def /Str 1 string def Str 0 Int put Str } def /FontSet { findfont Size scalefont setfont } bind def /IntToOctString { %integer. Only handles 3-digit octal (0..511) /DecInt exch def /OctStr 3 string def OctStr 0 DecInt 64 idiv 48 add put /DecInt DecInt 64 mod def OctStr 1 DecInt 8 idiv 48 add put /DecInt DecInt 8 mod def OctStr 2 DecInt 48 add put OctStr } bind def /inch { 72 mul } def /Top 9.5 inch def /Bottom 0.5 inch def /Left 0.5 inch def /Right 7 inch def /Size 12 def /Lineheight Size 5 add def /FirstChar 0 def /LastChar 255 def /SpaceStr (: ) def /CharsPerCol Top Bottom sub Lineheight div cvi def /ColPerPage LastChar FirstChar sub CharsPerCol div cvi def /ColWidth Right Left sub ColPerPage div cvi def Left Top 0.5 inch add moveto Font1 FontSet (Mapping from ) show Font1 80 string cvs show ( to ) show Font2 80 string cvs show /PresentCol Left def /PresentRow Top def FirstChar 1 LastChar { /ThisChar exch def PresentCol PresentRow moveto Font1 FontSet ThisChar dup IntToOctString show ( ) show IntToChar dup show SpaceStr show Font2 FontSet show /PresentRow PresentRow Lineheight sub def PresentRow Bottom lt { /PresentRow Top def /PresentCol PresentCol ColWidth add def } if } bind for showpage End-Of-Main-Stuff } case $# in 0) FONT1=Courier ; FONT2=Helvetica ;; 1) FONT1=Courier ; FONT2=$1 ;; *) FONT1=$1 ; FONT2=$2 ;; esac (emit_header $FONT1 $FONT2 ; emit_main_stuff) | $spooler $spoolopts exit 0 SHAR_EOF chmod +x 'mapfont' fi # end of overwriting check if test -f 'scaleshow' then echo shar: will not over-write existing file "'scaleshow'" else cat << \SHAR_EOF > 'scaleshow' #! /bin/sh # This is a PostScript program wrapped as a shell script. # copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this # work freely so long as this message and the copyright message are retained. # comments/bug fixes to: # Peter Greenberg # Swarthmore College # Swarthmore, PA 19081 # (215) 328-8610 # UUCP: ...!seismo!bpa!swatsun!greenber # ARPA: swatsun!greenber@seismo.CSS.GOV # Usage: scaleshow ShapeString ShapeFont Size Lines # The program will bomb out with an appropriate error message if ther are not # exactly four arguments. Otherwise no checking is done. Size must be a # real and Lines and integer. If they are not, a PostScript error will result. # CHANGE THESE LINES TO USE ANTOHER SPOOLER spooler=/usr/ucb/lpr spoolopts=-PPostScript emit_header() { cat <<End-Of-Header %! /String ($1) def /ShapeFont /$2 def /Size $3 def /Lines $4 def End-Of-Header } emit_main_stuff() { cat <<End-Of-Main-Stuff /SetFont { findfont Size scalefont setfont } def /CenterShow { /Str exch def /Ycoord currentpoint exch pop def Right Left sub Str stringwidth pop sub 2 div Left add Ycoord moveto Str show } def /CenterShowPlace { %string returns proper x-coord for center show /Str exch def Right Left sub Str stringwidth pop sub 2 div Left add } def /DrawBox { % boxllx boxlly boxurx boxury /boxury exch def /boxurx exch def /boxlly exch def /boxllx exch def boxllx boxlly moveto boxllx boxury lineto boxurx boxury lineto boxurx boxlly lineto closepath boxurx boxury moveto } def /HorrizontalScaleShow { % numscales string gsave true charpath closepath flattenpath clip pathbbox /ury exch def /urx exch def /lly exch def /llx exch def newpath 1 exch div /Grade exch def /Height ury lly sub def /Incr Grade Height mul def /Oldury lly def 0 Grade 1 { setgray llx Oldury urx Oldury Incr add dup /Oldury exch def DrawBox fill } for grestore } def /inch { 72 mul } def /Right 7 inch def /Left 1 inch def /Top 9.5 inch def /Bottom 0.5 inch def 0 Top Bottom sub 2 div Bottom add moveto ShapeFont SetFont Lines String dup CenterShowPlace 3 inch moveto HorrizontalScaleShow showpage End-Of-Main-Stuff } case $# in 4) ;; *) echo Usage: ; echo $0 ShapeString ShapeFont Size Lines; exit 1 ;; esac (emit_header $@ ; emit_main_stuff) | $spooler $spoolopts exit 0 SHAR_EOF chmod +x 'scaleshow' fi # end of overwriting check if test -f 'template.ps' then echo shar: will not over-write existing file "'template.ps'" else cat << \SHAR_EOF > 'template.ps' %! % TEMPLATE: This does nothing yet. It is a bunch of useful routines that you % may want to incorporate into your PostScript programs. They probably work. % copyright 1987 by Peter Greenberg. You can copy, use, and redistribute this % work so long as the copyright message and this message are retained. /ArrayToStr % array -> string % Takes array of integers and makes a string containing the integers ASCII % characters { /Array exch def /Length Array length def /Str Length string def 0 1 Length 1 sub { Str exch dup Array exch get put } for Str } def /IntToChar % string -> int % Returns character code of first character in string { /Int exch def /Str 1 string def Str 0 Int put Str } def /SetFont % -> % sets currentfont to Font in size Size, which are preset variables. { findfont Size scalefont setfont } def /CenterShow { % string -> % Shows string in middle of page. Y coordinate is not changed. Assumes % definition of Left and Right. /Str exch def /Ycoord currentpoint exch pop def Right Left sub Str stringwidth pop sub 2 div Left add Ycoord moveto Str show } def /FlushRightShow { % string -> % Shows string flush to right hand side of the page. % Y coordinate is not changed. Assumes definition of Left and Right. /Str exch def currentpoint /Ycoord exch def pop Right Str stringwidth pop sub Ycoord moveto Str show } def /MirrorShow % string -> % Like ordinary show, but string is shown in mirror image. { gsave dup /Str exch def stringwidth /Ydisp exch def /Xdisp exch def currentpoint /Y exch def /X exch def X Xdisp add Y Ydisp add translate 0 0 moveto [ -1 0 0 1 0 0 ] concat Str show grestore Xdisp Ydisp rmoveto } def /ConcatStr % string1 string2 -> newstring % Concatenates string1 and string2, returns newstring of combined length. { /Str2 exch def /Str1 exch def /NewStr Str1 length Str2 length add string def NewStr Str1 length Str2 putinterval NewStr 0 Str1 putinterval NewStr } def /NextLine { % -> % Goes to nextline as given by preset Lineheight. Left currentpoint exch pop Lineheight sub dup Bottom lt { pop copypage erasepage Top } if moveto } def % The following procedures all help in wrapping text. See comment on % last procedure. /SP 32 def /WhitespaceSearch { /Str exch def /StrLen Str length def /i 0 def { i StrLen lt { Str i get 32 gt { /i i 1 add def } { exit } ifelse } { exit } ifelse } loop i StrLen lt { /j i def { j StrLen lt { Str j get 32 le { /j j 1 add def } { exit } ifelse } { exit } ifelse } loop j StrLen lt { Str j StrLen j sub getinterval % Put Post on Stack } { () % put an empty string on the stack } ifelse Str i j i sub getinterval % Put Whitespace on Stack Str 0 i getinterval % Put Pre on stack true } { Str false } ifelse } def /WrapShow % string returns true if newline inserted after word { /Str exch def Str stringwidth pop dup /StrW exch def Right Left sub gt { NextLine Str show %just get out NextLine true } { StrW currentpoint pop add dup /Xcoord exch def WrapZone gt % Xcoord would extend past Wrapzone { Xcoord Right le { Str show NextLine true } % word ends in WrapZone { NextLine Str show false } % word extends past Rt. Margin ifelse } { Str show false } ifelse } ifelse } def /Tabulate { currentpoint exch Tab div ceiling Tab mul Left add exch moveto } def /ShowWhitespace % bool string (whitespace) { % a true will be on the stack if a newline had been inserted before % whitespace /WhiteSp exch def /NewLineBefore exch def WhiteSp 0 get dup dup 32 eq NewLineBefore not and { ( ) show } if 9 eq { Tabulate } if 10 eq NewLineBefore not and { NextLine } if WhiteSp 1 WhiteSp length 1 sub getinterval { dup dup 32 eq { ( ) show } if 9 eq { Tabulate } if 10 eq { NextLine } if } forall } def /WrapText % string (perhaps very long) -> % Shows the string from current point. Wraps text according to preset % Lineheight, Left, Right, Top, Bottom. Puts in page breaks, line breaks, etc. % Does not justify text. Takes newlines literally and prints them, so this % is not quite like a ?roff fill routine, and it may be a bit flaky, but it is % cool nonetheless. { /Str exch def Str WhitespaceSearch % loop until all words are eaten { /TextWord exch def /WhiteSpace exch def /Rest exch def TextWord WrapShow % returns true if newline inserted after word WhiteSpace ShowWhitespace Rest WrapText } { WrapShow %no spaces so this is the last word } ifelse } def /inch { 72 mul } def /Top 10.5 inch def /Bottom 0.5 inch def /Left 1 inch def /Right 8 inch def /WrapZone 7 inch def /Size 10 def /Lineheight Size 5 add def /Font1 /Courier def /Font2 /ZapfDingbats def % all symbols, no real letters /Font3 /AvantGarde-Book def /LineChr (-) def % boxes in ZapfDingbats /Tab 1 inch def % PUT PROGRAM HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SHAR_EOF fi # end of overwriting check # End of shell archive exit 0 -- Peter Greenberg, Swarthmore College, Swarthmore, PA 19081 AT&T:(215) 328-8384 or 8610 UUCP: ...{{seismo | inhp4}!bpa | {sun | rutgers}!liberty}!swatsun!greenber ARPA: swatsun!greenber@bpa.BELL-ATL.COM