[comp.lang.postscript] Centering text

ralerche@lindy.Stanford.EDU (Robert A. Lerche) (06/04/91)

"How do I center a string of text around a point?"

Level 1 PostScript has two operators that can extract information about
the metrics of characters: "stringwidth" and "charpath".

The "stringwidth" operator returns the advance width of its string operand.
This is the distance the current point would be moved by a "show" operation
on the same string.  "stringwidth" returns two numbers on the stack,
representing the x and y components of the advance width.  Usually
the y component is zero because most fonts are displayed along a horizontal
line, moving the current point only in the x direction.

Also note that the "stringwidth" operator includes any side bearings
in its result.  It usually does not give an exact measure of the area
of the page that will be touched by its operand.

If all that an application requires is horizontal centering of a long string
of text, the result returned by "stringwidth" is sufficient.  A common
technique is

	x y moveto
	(string) stringwidth pop 2 div neg 0 rmoveto
	(string) show

(This code makes the assumption that the y component of advance width is
irrelevant.)


The "charpath" operator extracts the graphic shapes of its string operand
and appends them to the current path in the graphic state.  These shapes
can then be processed by other PostScript operators.  To get the actual
size of the area touched by a character a simple approach is

	gsave
	newpath
	0 0 moveto
	(X) true charpath flattenpath pathbbox
	grestore

This code places four numbers on the stack, representing the coordinates of
the lower left and upper right corners of the bounding box enclosing the
character "X" rendered with the current point at (0,0).

There are two things to be careful about when using the code shown above:

1.  There are severe limits on the size of the string operand, related
    to the limit on the number of elements in a graphic path.  The PostScript
    Language Reference Manual recommends taking "charpath"s one character
    at a time.

2.  If user space is rotated or skewed with respect to device space, the
    result from "pathbbox" may be larger than expected; "pathbbox" returns
    a rectangle oriented along the user space coordinate axes, which
    fully encloses a (possibly smaller) rectangle oriented along the
    coordinate axes of device space.  If user space is rotated at an integer
    multiple of 90 degrees these two rectangeles will be the same, otherwise
    the rectangle in user space will be larger.

So, to center text vertically one must get the bounding boxes of all
the characters in the string to be displayed, find the minimum and
maximum y coordinate values, and use half the distance between them to
displace the text vertically.

If an application does this repeatedly, it would be wise to store the
bounding boxes in an array indexed by character code, since "charpath"
is a slow operation.

Font metric information is available outside of a PostScript printer in
font metrics files, available from Adobe.  A program generating PostScript
output can obtain metrics from these files rather than extracting the
metrics in the printer.