pathtextdict begin /movetoproc
{ /newy exch def /newx exch def
‘‘movetoproc’’ is executed when a moveto component has been encountered in the pathforall operation.
/firstx newx def /firsty newy def /ovr 0 def
newx newy transform
Remember the ‘‘first point’’ in the path so that when we get a closepath component we can properly handle the text.
/cpy exch def /cpx exch def } def
Explicitly keep track of the current position in device space.
/linetoproc ‘‘linetoproc’’ is executed when a lineto component has been encountered in the pathforall operation.
{ /oldx newx def /oldy newy def Update the old point.
/newy exch def /newx exch def Get the new point.
/dx newx oldx sub def /dy newy oldy sub def
/dist dx dup mul dy dup mul add sqrt def Compute the distance between the old and new point.
dist 0 ne Don’t do anything if the line segment has zero length.
{ /dsx dx dist div ovr mul def /dsy dy dist div ovr mul def
‘‘dsx’’ and ‘‘dsy’’ are used to update the current position to be just beyond the width of the previous character.
oldx dsx add oldy dsy add transform
/cpy exch def /cpx exch def Update the current position.
/pathdist pathdist dist add def Increment the distance we have traveled along the path.
{ setdist pathdist le Keep setting characters along this path segment until we have exhausted its length.
{ charcount str length lt {setchar} {exit} ifelse }
As long as there are still characters left in the string, set them.
{ /ovr setdist pathdist sub def exit }
ifelse } loop
Keep track of how much we have overshot the path segment by setting the previous character. This enables us to position the origin of the following characters properly on the path.
} if } def
/curvetoproc
{ (ERROR: No curveto’s after flattenpath!) print } def
‘‘curvetoproc’’ is executed when a curveto component has been encountered in the pathforall operation. It prints an error message since there shouldn’t be any
curveto’s in a path after the flattenpath operator has
been executed.
/closepathproc
{ firstx firsty linetoproc firstx firsty movetoproc } def
‘‘closepathproc’’ is executed when a closepath component has been encountered in the pathforall operation. It simulates the action of the operator
closepath by executing ‘‘linetoproc’’ with the
coordinates of the most recent moveto and then executing ‘‘movetoproc’’ to the same point.
175
Program 11 / Placing Text Along an Arbitrary Path
(continued)
/setchar
{ /char str charcount 1 getinterval def
‘‘setchar’’ sets the next character in the string along the path and then updates the amount of path we have exhausted.
/charcount charcount 1 add def Increment the character count.
/charwidth char stringwidth pop def Find the width of the character.
gsave
cpx cpy itransform translate Translate to the current position in user space.
dy dx atan rotate Rotate the x-axis to coincide with the current segment.
0 0 moveto char show currentpoint transform /cpy exch def /cpx exch def grestore
Update the current position before restoring to the untransformed state.
/setdist setdist charwidth add def } def
Increment the distance we have covered by setting characters.
end The completes the definitions required by ‘‘pathtext.’’
Below is an example of using ‘‘pathtext.’’
/Helvetica findfont 16 scalefont setfont Set up the font we wish to use.
newpath
200 500 70 0 270 arc
200 110 add 500 70 270 180 arc
Define the path that ‘‘pathtext’’ will use.
(If my film makes one more person feel\ miserable I’ll feel I’ve done my job.\
-- WOODY ALLEN) 55 pathtext Print the string along the path at an offset of 55 points.
newpath Draw an outline shape suggestive of a movie camera.
150 310 moveto 360 310 lineto Draw the box part.
360 400 lineto 150 400 lineto closepath
360 347 moveto 410 330 lineto Draw the lens part.
410 380 lineto 360 363 lineto 2 setlinewidth stroke
EXERCISE FOR THE READER: This algorithm places characters along the path according to the origin of each character. Rewrite the algorithm so that the characters are placed according to the center of their width. This will yield better results around sharp curves and when larger point sizes are used.
A Simple Line Breaking Algorithm
In every period there have been better or worse types employed in better or worse ways. The better types employed in better ways have been used by the educated printer acquainted with standards and history, directed by taste and a sense of the fitness of things, and facing the industrial conditions and the needs of his time. Such men have made of printing an art. The poorer types and methods have been employed by printers ignorant of standards and caring alone for commercial success. To these, printing has been simply a trade. The typography of a nation has been good or bad as one or other of these classes had the supremacy. And to-day any intelligent printer can educate his taste, so to choose types for his work and so to use them, that he will help printing to be an art rather than a trade. –Daniel Berkeley Updike.
Drawing a Pie Chart
January Pie Sales Blueberry Cherry Apple Boston Cream Other Vanilla Cream
Filling an Area with a Pattern
Basket weave, no rotation in user space Fish scale, 90 degree rotation in user space
Making a Poster
50%
SA
% OF
AL
OFF
LE
NOTE: This is not the actual output page produced by the following POSTSCRIPT program. The rectangles are scaled down versions of the 8 1/2" by 11" pages generated by the program.