NAME - Some useful transforms in PostScript


 (/home/wherever/ps/lib/ run
 % to send it to a printer see include_run . . .

 /rect { 4 dict begin   [ /h /w /y /x ] { exch def } forall
   x y moveto  w 0 rlineto  0 h rlineto  0 w sub 0 rlineto  closepath
 end } def    % like rectfill, except it just constructs the path

 /HelveticaBold  310  selectfont

 % the vanishing-point will be 300,400
 % left of the vanishing-point, we start printing text at x0
 /x0 20 def
 x0 375 moveto  (MHXWENZE) true charpath
 [ 300 400 x0 ]  /perspective_xy2uv c_transform fill

 % but right of the VP, we start the text at x0-stringwidth
 /x0   570 def
 /x_start_of_string x0 (MHXWENZE) stringwidth pop sub def
  x_start_of_string 375 moveto (MHXWENZE) true charpath
 % [ x0 theta ]  % at x0, the text is at theta degrees to the viewer
 [ 300 400 x0 20 ]   /perspective_xy2uv c_transform fill

 /y0 20 def
 70  y0  24 5000 rect
 490 y0  24 5000 rect
 0.5 setgray
 [ 300 400 y0 20 ] /perspective_flat_xy2uv c_transform fill

 18 36 575 {   /x exch def
   18 36 808 { /y exch def  x y 20 20 rect } for
 } for   % construct a path
 0.8 setgray
 % [x_amplitud  y_wavelen y_phase  y_amplitud x_wavelen x_phase]
 [9 300 0  6 200 90] /sine_xy2uv c_transform   fill

 18 30 575 {   /x exch def
   18 30 808 { /y exch def  x y 16 16 rect } for
 } for   % construct a path
 % [ x y r magnification ]
 [ 120 700 80 1.8 ]  /softlens_xy2uv c_transform
 [ 120 450 80 1.8 ]  /hardlens_xy2uv c_transform
 % [ x y r angle ]
 [ 350 200 70 60 ]   /twist_xy2uv    c_transform
 % [ x y r range ]
 [ 400 600 70 90 ]   /collapse_xy2uv c_transform  fill


This module implements in PostScript some useful transforms.
It is mostly useful for non-linear transforms, since the linear transforms are more easily done with translate, scale and concat.
It can only transform paths, so to transform text the path must be generated by using charpath, then transfomed, and finally made visible by fill (or stroke).
This means that only text in Type-1 fonts can be transformed.   For example, the custom fonts Bitfont5x7, FatSimple and FatSimpleItalic in are not Type-1 fonts.

The procedures here transform the current path.   Unlike the built-ins translate, scale and concat, they do not transform the coordinate-system and so do not have to be protected between a gsave and grestore.   Anything already stroked or filled onto the page is of course not moved.

For some simple examples, see test_transforms.pdf, a pdf version of the test-file.   (The PostScript source is on github.)

Just as a handy reference: the PostScript matrix as used by concat is the array:
  [ a b c d tx ty ]
where the transformation x,y to x',y' is:
  x' = a.x + c.y + tx
  y' = b.x + d.y + ty


    ctransform   c_transform   collapse_xy2uv   perspective_xy2uv   perspective_flat_xy2uv   sine_xy2uv   softlens_xy2uv   hardlens_xy2uv   twist_xy2uv  

/xy2uv_proc   ctransform

This procedure comes straight from chapter 8 of Mathematical Illustrations: A Manual of Geometry and Postscript by Bill Casselman and makes possible all kinds of non-linear translations of the current path.
It takes one argument, which is a named procedure to transform the coordinates x and y into the resulting u and v

Note that a single long line such as   10 145 moveto 580 145 lineto   remains a long straight line; it's in the nature of pathforall that only the join-points get moved.   So you probably want something like:
10 145 moveto 15 5 580 { 145 lineto } for   which expresses the line in many smaller segments.

[array of params]   /xy2uv_proc   c_transform

c_transform is extended from ctransform to allow the specification of an array of parameters for the _xy2uv routine.

It takes two arguments.   Second-to-top of the stack is an array containing the parameters which will be used by the xy2uv_proc.   Top of the stack is a named procedure to transform the coordinates x and y into the resulting u and v

There now follow various such named procedures, implementing some useful transformations . . .

[x0 y0 radius range]   /collapse_xy2uv   c_transform

collapse_xy2uv implements a "collapse" transform (think Black Hole, or Macular Degeneration) in which everything within a given circle collapses down to the center, and things outside that circle (within a given range of it) stretch inward to fill the gap.

[xvp yvp x0 theta]   /perspective_xy2uv   c_transform

perspective_xy2uv implements a perspective-transformation in which parallel lines converge toward a vanishing-point at xvp,yvp. The lines are assumed to lie in a vertical surface, such as a building-facade, or a wall, or a billboard.
perspective_xy2uv looks at four parameters :   xvp,yvp which are the vanishing-point,
x0 which is the x at which the heights are to scale 1:1,
and theta which is the angle at which the viewer sees the x0 point. So if theta=90 the viewer is face-on to the x=u=x0 point. In practice, theta is typically between 20 and 60 degrees.
theta is currently implemented in a cheap kludge in which the obliqueness is constant all the way to the horizon, whereas in reality the obliqueness becomes more extreme as the vanising-point is approached . . .

If theta is missing, the text is displayed at full width (as if viewed face-on), may be good for legibility but is less realistic, since in reality it would be seen from a more oblique angle.

[xvp yvp y0 theta]   /perspective_flat_xy2uv   c_transform

perspective_flat_xy2uv is like perspective_xy2uv in that parallel lines converge toward a vanishing-point at xvp,yvp, except that the parallel lines are assumed to lie on a horizontal surface, for example the ground.
xvp,yvp specify the vanishing-point.
y0 is the y at which the widths are to scale 1:1, which for surfaces below eye-level will be less than yvp.
theta which is the angle at which the viewer sees the y0 point.

[xampltd ywavlen yphs yampltd xwavlen xphs]   /sine_xy2uv c_transform

sine_xy2uv implements a sine-waviness in the coordinate grid. The vertical lines get a horizontal waviness with a wavelength in the y coordinate, and conversely the horizontal lines get a waviness in the y direction with a wavelength in the x coordinate.
An array of six parameters is needed. In order: x_amplitude, y_wavelength and y_phase for the waviness in the vertical lines, and y_amplitude, x_wavelength and x_phase for the waviness in the horizontal lines.

[x y radius magnification]   /softlens_xy2uv   c_transform

softlens_xy2uv implements a soft-edged magnifying-glass over the coordinate grid. An array of four parameters is needed. In order: x, y, radius and magnification.

[x y radius magnification]   /hardlens_xy2uv   c_transform

hardlens_xy2uv implements a hard-edged magnifying-glass over the coordinate grid. An array of four parameters is needed. In order: x, y, radius and magnification.

[x y radius angle]   /twist_xy2uv   c_transform

twist_xy2uv implements a twist in the coordinate grid. An array of four parameters is needed. In order: x, y, radius and angle.
The degrees-of-twist decay exponentially with the radial distance from the centre.

[stdev_x stdev_y]   /grand_xy2uv   c_transform

grand_xy2uv moves each point by gaussian-random distance, and the standard-deviation in the x and y coordinates is specified separately. So an array of two parameters is needed, namely: stdev_x and stdev_y
If you use this, you will need to run the library.   For example:
  (/home/wherever/ps/lib/ run
  /Times-Roman 110 selectfont
  20 700 moveto ( Gaussian) true charpath
  20 600 moveto (SCDOGJPQ) true charpath
  20 500 moveto (QSCDOGJP) true charpath
  20 400 moveto (PQSCDOGJ) true charpath
  20 300 moveto (JPQSCDOG) true charpath
  20 200 moveto (GJPQSCDO) true charpath
  20 100 moveto (OGJPQSCD) true charpath
  [3 7] /grand_xy2uv c_transform
  gsave 1 0 0 setrgbcolor fill grestore
  0 0 0 setrgbcolor 3 setlinewidth stroke


To install: go to and save the file to your local disc.
Rename it to and move it into some appropriate directory such as ~/ps/lib . . .
Or, first change directory to where you keep your PostScript libraries:
  cd /home/wherever/ps/lib/
(or wherever)   and then either:
  wget -O
  curl -o

Or, get it from github:
    git clone


Peter J Billam


 20170510 added grand_xy2uv
 20160723 perspective and perspective_flat get a [xvp yvp x0 theta] syntax
 20160722 added collapse, perspective_flat, sine, softlens, hardlens, twist
 20160717 first release


Back to P J B Computing or to . . .