next up previous
Next: How can I concatenate Up: Programming in PostScript Previous: Why can't I do

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'' usually does not give an exact measure of the area of the page that will be touched by its operand. The letters can either project a little over the boundaries or fall a little within (leaving a touch of whitespace).

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) dup stringwidth pop 2 div neg 0 rmoveto 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) false 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). Leaving the flattenpath out will cause it to be less accurate, but it will take up less memory and be faster.

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 rectangles 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. This still may not do a very good job, since this provides centering based on extrema, not on the optical center of the string (which is more related to a sort of ``center of mass'' of the text).

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 the font vendor. A program generating PostScript output can obtain metrics from these files rather than extracting the metrics in the printer.


next up previous
Next: How can I concatenate Up: Programming in PostScript Previous: Why can't I do
Allen B
2/2/1998