1. stringwidth
Calculate text width and displacement.
1.3. Description
stringwidth calculates the change in the current point that would occur if string were given as the operand to show with the current font. wx and wy are computed by adding together the width vectors of all the individual characters in string and converting the result to user space.
They form a distance vector in x and y describing the width of the entire string in user space. To obtain the character widths, stringwidth may execute the descriptions of one or more of the characters in the current font and may cause the results to be placed in the font cache.
However, stringwidth prevents the graphics operators that are executed from painting anything into the current page.
Note that the "width" of a string is defined as movement of the current point. It has nothing to do with the dimensions of the character outlines (see charpath) and pathbbox.
1.5. Returns
wx (number)
: X component of the total width vector in user space
wy (number)
: Y component of the total width vector in user space
1.6. Examples
1.6.1. Basic Width Measurement
/Helvetica findfont 12 scalefont setfont
(Hello, World!) stringwidth
% Returns wx and wy
pop % Usually only wx is needed
1.6.2. Centering Text
/centerText { % string centerText -
dup stringwidth pop % Get width (wx)
2 div neg % Calculate offset
0 rmoveto % Move left by half width
show % Show centered
} def
300 400 moveto
(Centered Text) centerText
1.6.3. Right-Aligned Text
/rightShow { % string x y rightShow -
moveto
dup stringwidth pop neg 0 rmoveto
show
} def
(Right aligned) 500 700 rightShow
1.6.4. Calculating Text Bounding Box
% Note: stringwidth gives displacement, not bounding box!
% For actual bbox, use charpath + pathbbox
/textBBox { % string textBBox llx lly urx ury
gsave
newpath
0 0 moveto
true charpath % Get character outlines
pathbbox % Get bounding box
grestore
} def
(Text) textBBox % Returns actual visual bounds
1.7. Errors
invalidaccess : Font or string has restricted access
invalidfont : Current font is not valid
rangecheck : Character code exceeds encoding bounds
stackunderflow : No operand on stack
typecheck : Operand is not a string
1.8. Width Vector Calculation
For a string "ABC":
stringwidth("ABC") = width(A) + width(B) + width(C)
Where each character width is a 2D vector:
width(c) = (wx(c), wy(c))
The total is the vector sum in user space.
1.9. Coordinate System
The width is returned in user space, not character space:
/Helvetica findfont 12 scalefont setfont
(ABC) stringwidth % Returns user space width
% After CTM change, same string has different width
2 2 scale
(ABC) stringwidth % Returns 2× larger values
1.10. Common Patterns
1.10.1. Multi-Line Text Width
/maxLineWidth { % array-of-strings maxLineWidth width
0 % Initialize max width
exch {
stringwidth pop % Get width of each line
2 copy lt { exch } if pop
} forall
} def
[(Line 1)
(Longer line 2)
(Short)] maxLineWidth
% Returns width of widest line
1.10.2. Truncating Text to Fit
/truncateToFit { % string maxWidth truncateToFit substring
1 index stringwidth pop % Check if fits
1 index le {
% Fits as-is
pop
} {
% Too wide: truncate
0 1 2 index length 1 sub {
2 index 0 1 index getinterval
dup stringwidth pop
3 index lt { exit } if
pop
} for
% Add ellipsis
(...) concatstrings
exch pop
} ifelse
} def
(Very long text that needs truncation) 200 truncateToFit
1.11. Width vs. Bounding Box
| Measurement | Purpose |
|---|---|
stringwidth |
Current point displacement (typographic width) |
charpath + pathbbox |
Visual bounding box (ink bounds) |
Example difference:
% Typographic width (includes sidebearings)
(Text) stringwidth pop % e.g., 120 units
% Visual width (actual ink)
gsave
newpath 0 0 moveto
(Text) true charpath
pathbbox
grestore
pop exch pop sub % e.g., 115 units (tighter)
1.12. Performance Considerations
-
Fast operation (similar cost to
show) -
May trigger character caching
-
Does not paint (no output overhead)
-
Can be called repeatedly without side effects
-
Useful for layout calculations before rendering