- 1. Fonts and Text
- 1.1. Overview
- 1.2. Font Basics
- 1.3. Basic Text Rendering
- 1.4. Advanced Text Operators
- 1.5. Text Metrics
- 1.6. Font Transformations
- 1.7. Text as Paths
- 1.8. Text Effects
- 1.9. Multi-line Text
- 1.10. Text Layout Patterns
- 1.11. Font Management
- 1.12. Practical Examples
- 1.13. Best Practices
- 1.14. Common Pitfalls
- 1.15. Performance Tips
- 1.16. See Also
1. Fonts and Text
Typography and text rendering in PostScript provide sophisticated control over font selection, text layout, and character positioning. Mastering these capabilities is essential for professional document production.
1.1. Overview
PostScript text capabilities include:
-
Font management - Loading, scaling, and caching fonts
-
Text rendering - Basic and advanced text display
-
Character positioning - Precise character placement
-
Text metrics - Measuring text dimensions
-
Font transformations - Scaling, rotating, and skewing fonts
-
Custom text effects - Outlines, shadows, and patterns
PostScript uses vector fonts that scale to any size without quality loss.
1.2. Font Basics
1.2.1. Font Selection
The standard font workflow:
% 1. Find font by name
/Times-Roman findfont
% 2. Scale to desired size
12 scalefont
% 3. Make it current
setfont
% Or in one line:
/Times-Roman findfont 12 scalefont setfont
1.2.2. Standard Fonts
PostScript Level 1 guaranteed fonts:
% Serif fonts
/Times-Roman findfont 12 scalefont setfont
/Times-Bold findfont 12 scalefont setfont
/Times-Italic findfont 12 scalefont setfont
/Times-BoldItalic findfont 12 scalefont setfont
% Sans-serif fonts
/Helvetica findfont 12 scalefont setfont
/Helvetica-Bold findfont 12 scalefont setfont
/Helvetica-Oblique findfont 12 scalefont setfont
/Helvetica-BoldOblique findfont 12 scalefont setfont
% Monospaced fonts
/Courier findfont 12 scalefont setfont
/Courier-Bold findfont 12 scalefont setfont
/Courier-Oblique findfont 12 scalefont setfont
/Courier-BoldOblique findfont 12 scalefont setfont
% Symbol font
/Symbol findfont 12 scalefont setfont
1.3. Basic Text Rendering
1.3.1. The show Operator
Display text at current point:
% Set up
/Helvetica findfont 24 scalefont setfont
100 100 moveto
% Show text
(Hello, World!) show
Multiple text segments:
/Times-Roman findfont 14 scalefont setfont
100 100 moveto
(This is ) show
/Times-Bold findfont 14 scalefont setfont
(bold ) show
/Times-Roman findfont 14 scalefont setfont
(text.) show
1.3.2. Text Positioning
Text updates the current point:
100 100 moveto
(Line 1) show
% Current point is now at end of "Line 1"
% Move down for next line
0 -20 rmoveto
(Line 2) show
Common line spacing:
/fontSize 12 def
/leading fontSize 1.2 mul def % 120% of font size
/Times-Roman findfont fontSize scalefont setfont
100 500 moveto
(Line 1) show
0 leading neg rmoveto
(Line 2) show
0 leading neg rmoveto
(Line 3) show
1.3.3. Text Alignment
Left-aligned (default):
100 100 moveto
(Left aligned) show
Right-aligned:
/text (Right aligned) def
/Times-Roman findfont 12 scalefont setfont
% Measure text width
text stringwidth pop
% Move left by text width
neg 0 rmoveto
% Show text
text show
Center-aligned:
/text (Centered) def
/Times-Roman findfont 12 scalefont setfont
% Measure and divide by 2
text stringwidth pop 2 div
% Move left by half width
neg 0 rmoveto
% Show text
text show
Alignment helper:
/alignText { % x y text alignment -> -
% alignment: 0=left, 1=center, 2=right
4 dict begin
/align exch def
/text exch def
/y exch def
/x exch def
text stringwidth pop
align 1 eq {
2 div neg 0
} {
align 2 eq {
neg 0
} {
pop 0 0
} ifelse
} ifelse
x add y moveto
text show
end
} def
% Usage
100 100 (Left) 0 alignText
200 100 (Center) 1 alignText
300 100 (Right) 2 alignText
1.4. Advanced Text Operators
1.4.1. The ashow Operator
Add space after each character:
% ashow: ax ay string ashow
100 100 moveto
5 0 (Spaced Text) ashow
% Adds 5 points horizontal space after each character
1.4.2. The widthshow Operator
Add space after specific character:
% widthshow: cx cy char string widthshow
100 100 moveto
10 0 32 (Add space after spaces) widthshow
% Adds 10 points after each space (ASCII 32)
1.4.3. The awidthshow Operator
Combines ashow and widthshow:
% awidthshow: cx cy char ax ay string awidthshow
100 100 moveto
20 0 32 2 0 (Spacing example) awidthshow
% 2 points after each char, 20 points after spaces
1.4.4. The kshow Operator
Custom kerning with procedure:
% kshow: string procedure kshow
% Procedure called between each character pair
/Times-Roman findfont 24 scalefont setfont
100 100 moveto
(WAVE) {
% Add custom spacing based on characters
pop % Current character code
2 0 rmoveto % Add 2 points between chars
} kshow
Advanced kerning:
% Custom kerning pairs
/kerningPairs <<
(AV) -2
(VA) -2
(To) -1
(Wo) -1
>> def
/kernedShow { % string -> -
{
% Get character
1 string dup 0 4 -1 roll put
% Show it
dup show
% Check for kerning pair
% (implementation simplified)
} kshow
} def
(WAVE) kernedShow
1.5. Text Metrics
1.5.1. The stringwidth Operator
Get text dimensions:
% stringwidth: string -> width height
/Times-Roman findfont 12 scalefont setfont
(Sample Text) stringwidth
% Returns: width height
% Common usage - get width only
(Sample Text) stringwidth pop pop % Discard both
(Sample Text) stringwidth exch pop % Keep height
(Sample Text) stringwidth pop % Keep width
Measuring for centering:
/centerText { % x y text -> -
3 dict begin
/text exch def
/y exch def
/x exch def
text stringwidth pop 2 div
x exch sub y moveto
text show
end
} def
300 400 (Centered Text) centerText
1.6. Font Transformations
1.6.1. The scalefont Operator
Scale font to size:
% scalefont: font scale -> scaledfont
/Times-Roman findfont
12 scalefont setfont
% Different sizes
/Times-Roman findfont 8 scalefont setfont % Small
/Times-Roman findfont 12 scalefont setfont % Normal
/Times-Roman findfont 24 scalefont setfont % Large
/Times-Roman findfont 72 scalefont setfont % Huge
1.6.2. The makefont Operator
Apply arbitrary transformation matrix:
% makefont: font matrix -> transformedfont
% Condensed font (50% width)
/Times-Roman findfont
[6 0 0 12 0 0] makefont setfont
100 100 moveto
(Condensed) show
% Expanded font (200% width)
/Times-Roman findfont
[24 0 0 12 0 0] makefont setfont
100 80 moveto
(Expanded) show
% Italic (slanted)
/Times-Roman findfont
[12 0 6 12 0 0] makefont setfont
100 60 moveto
(Slanted) show
% Rotated
/Times-Roman findfont
[0 12 -12 0 0 0] makefont setfont
100 40 moveto
(Rotated) show
Combined transformations:
% Create fancy font transformation
/Times-Bold findfont
[20 0 4 24 0 0] makefont % Wide and slanted
setfont
100 100 moveto
(Fancy!) show
1.7. Text as Paths
1.7.1. The charpath Operator
Convert text to path outline:
% charpath: string boolean charpath
% boolean: true=stroke outline, false=fill outline
/Helvetica-Bold findfont 72 scalefont setfont
newpath
100 200 moveto
(TEXT) true charpath % Create stroke outline
2 setlinewidth
stroke
Outlined text:
/outlineText { % text -> -
gsave
% Fill
1 1 1 setrgbcolor
newpath
100 200 moveto
dup false charpath
fill
grestore
% Outline
0 0 0 setrgbcolor
newpath
100 200 moveto
true charpath
2 setlinewidth
stroke
} def
(OUTLINED) outlineText
Text with gradient (simulated):
/Helvetica-Bold findfont 72 scalefont setfont
newpath
100 200 moveto
(GRADIENT) false charpath
% Clip to text
clip
newpath
% Draw gradient through text
0 1 100 {
/i exch def
i 100 div dup 0 setrgbcolor
i 100 200 1 72 rectfill
} for
1.8. Text Effects
1.8.1. Drop Shadow
/shadowText { % x y text -> -
3 dict begin
/text exch def
/y exch def
/x exch def
% Shadow
gsave
0.7 setgray
x 3 add y 3 sub moveto
text show
grestore
% Text
0 setgray
x y moveto
text show
end
} def
100 100 (Shadow Text) shadowText
1.8.2. Outline Text
/outlineText { % x y text outlineWidth -> -
4 dict begin
/width exch def
/text exch def
/y exch def
/x exch def
/Helvetica-Bold findfont 48 scalefont setfont
% Outline
1 1 1 setrgbcolor
width setlinewidth
newpath
x y moveto
text true charpath
stroke
% Fill
0 0 0 setrgbcolor
x y moveto
text show
end
} def
100 100 (OUTLINE) 3 outlineText
1.8.3. 3D Text Effect
/text3D { % x y text depth -> -
4 dict begin
/depth exch def
/text exch def
/y exch def
/x exch def
/Helvetica-Bold findfont 72 scalefont setfont
% Depth layers
depth -1 1 {
/d exch def
d depth div 0.3 add setgray
x d add y d sub moveto
text show
} for
% Front
1 1 0 setrgbcolor
x y moveto
text show
end
} def
100 200 (3D!) 5 text3D
1.8.4. Patterned Text
/patternText { % x y text -> -
3 dict begin
/text exch def
/y exch def
/x exch def
/Helvetica-Bold findfont 72 scalefont setfont
% Create clipping path from text
gsave
newpath
x y moveto
text false charpath
clip
newpath
% Draw pattern
0 5 100 {
/i exch def
i 10 mod 10 div setgray
x i add y 1 72 rectfill
} for
grestore
end
} def
100 200 (PATTERN) patternText
1.9. Multi-line Text
1.9.1. Basic Multi-line
/multiLine { % x y lineHeight textArray -> -
4 dict begin
/lines exch def
/leading exch def
/y exch def
/x exch def
lines {
x y moveto
show
/y y leading sub def
} forall
end
} def
% Usage
100 500 15 [
(Line 1)
(Line 2)
(Line 3)
] multiLine
1.9.2. Text Box with Word Wrap
/textBox { % x y width text -> -
4 dict begin
/text exch def
/boxWidth exch def
/startY exch def
/startX exch def
/currentX startX def
/currentY startY def
/fontSize 12 def
/leading fontSize 1.2 mul def
/Helvetica findfont fontSize scalefont setfont
% Split text into words
text ( ) {
search {
% Found space
dup stringwidth pop
currentX add boxWidth startX add gt {
% Word doesn't fit, new line
/currentX startX def
/currentY currentY leading sub def
} if
currentX currentY moveto
dup show
stringwidth pop currentX add
/currentX exch def
% Add space width
( ) stringwidth pop currentX add
/currentX exch def
} {
% Last word
currentX currentY moveto
show
exit
} ifelse
} loop
end
} def
% Usage
50 500 200 (This is a long text that will automatically wrap to fit within the specified width.) textBox
1.10. Text Layout Patterns
1.10.1. Justified Text
/justifyLine { % x y width text -> -
4 dict begin
/text exch def
/lineWidth exch def
/y exch def
/x exch def
% Count spaces
/spaces 0 def
0 1 text length 1 sub {
text exch get 32 eq {
/spaces spaces 1 add def
} if
} for
% Calculate extra space per gap
spaces 0 gt {
text stringwidth pop
lineWidth exch sub
spaces div
% Show with extra spacing
x y moveto
0 32 text widthshow
} {
% No spaces, just show
x y moveto
text show
} ifelse
end
} def
% Usage
50 100 500 (This line will be justified across the width.) justifyLine
1.10.2. Vertical Text
/verticalText { % x y text -> -
3 dict begin
/text exch def
/y exch def
/x exch def
/Helvetica findfont 12 scalefont setfont
/charHeight 14 def
0 1 text length 1 sub {
/i exch def
x y i charHeight mul sub moveto
text i 1 getinterval show
} for
end
} def
100 500 (VERTICAL) verticalText
1.10.3. Circular Text
/circularText { % centerX centerY radius text -> -
4 dict begin
/text exch def
/r exch def
/cy exch def
/cx exch def
/Helvetica findfont 12 scalefont setfont
/angleStep 360 text length div def
0 1 text length 1 sub {
/i exch def
/angle i angleStep mul 90 add def
gsave
cx cy translate
angle rotate
0 r moveto
text i 1 getinterval show
grestore
} for
end
} def
200 200 100 (CIRCULAR TEXT!) circularText
1.11. Font Management
1.11.1. Defining Custom Fonts
% Define a font alias
/MyFont /Times-Roman findfont 12 scalefont def
% Use it
MyFont setfont
100 100 moveto
(Using custom font) show
1.11.2. Font Cache
% Cache scaled fonts for performance
/fontCache 10 dict def
/getCachedFont { % fontName size -> font
2 dict begin
/size exch def
/name exch def
/key name =string cvs (-) exch concatstrings
size =string cvs concatstrings def
fontCache key known {
fontCache key get
} {
name findfont size scalefont
dup fontCache key 3 -1 roll put
} ifelse
end
} def
% Usage
/Times-Roman 12 getCachedFont setfont
/Helvetica 14 getCachedFont setfont
1.12. Practical Examples
1.12.1. Example 1: Title Page
/titlePage {
% Title
/Helvetica-Bold findfont 36 scalefont setfont
306 600 moveto
(Document Title) dup stringwidth pop 2 div neg 0 rmoveto
show
% Subtitle
/Helvetica findfont 18 scalefont setfont
306 560 moveto
(A Comprehensive Guide) dup stringwidth pop 2 div neg 0 rmoveto
show
% Author
/Times-Italic findfont 14 scalefont setfont
306 400 moveto
(By Author Name) dup stringwidth pop 2 div neg 0 rmoveto
show
% Date
/Times-Roman findfont 12 scalefont setfont
306 370 moveto
(January 2024) dup stringwidth pop 2 div neg 0 rmoveto
show
} def
titlePage
1.12.2. Example 2: Business Card
/businessCard {
% Border
0.5 setlinewidth
50 50 252 144 rectstroke
% Name
/Helvetica-Bold findfont 16 scalefont setfont
60 160 moveto
(John Doe) show
% Title
/Helvetica findfont 10 scalefont setfont
60 145 moveto
(Senior Developer) show
% Contact info
/Courier findfont 8 scalefont setfont
60 120 moveto (Email: john@example.com) show
60 110 moveto (Phone: +1-555-0123) show
60 100 moveto (Web: www.example.com) show
} def
businessCard
1.12.3. Example 3: Invoice Header
/invoiceHeader {
% Company name
/Helvetica-Bold findfont 24 scalefont setfont
50 750 moveto
(ACME Corporation) show
% Address
/Helvetica findfont 10 scalefont setfont
50 735 moveto (123 Business St) show
50 725 moveto (City, State 12345) show
% Invoice title
/Helvetica-Bold findfont 18 scalefont setfont
450 750 moveto (INVOICE) show
% Invoice details
/Helvetica findfont 10 scalefont setfont
450 730 moveto (Invoice #: 12345) show
450 720 moveto (Date: 2024-01-15) show
450 710 moveto (Due: 2024-02-15) show
} def
invoiceHeader
1.12.4. Example 4: Code Listing
/codeListing { % lines -> -
1 dict begin
/lines exch def
/y 700 def
/lineHeight 12 def
% Background
0.95 setgray
50 y lineHeight lines length mul add 500 lineHeight lines length mul sub rectfill
% Line numbers and code
/Courier findfont 9 scalefont setfont
0 1 lines length 1 sub {
/i exch def
% Line number
0.5 setgray
55 y moveto
i 1 add =string cvs show
% Code
0 setgray
90 y moveto
lines i get show
/y y lineHeight sub def
} for
end
} def
% Usage
[
(function hello() {)
( console.log("Hello");)
(})
] codeListing
1.13. Best Practices
1.13.1. Cache Fonts
% Good: define once, use many times
/bodyFont /Times-Roman findfont 12 scalefont def
/headingFont /Helvetica-Bold findfont 18 scalefont def
bodyFont setfont
(Body text) show
headingFont setfont
(Heading) show
1.13.2. Use Appropriate Fonts
% Serif for body text (easier to read)
/Times-Roman findfont 11 scalefont setfont
% Sans-serif for headings
/Helvetica-Bold findfont 18 scalefont setfont
% Monospace for code
/Courier findfont 9 scalefont setfont
1.13.3. Consistent Leading
% Define leading as multiple of font size
/fontSize 12 def
/leading fontSize 1.2 mul def % 120% = good readability
% Or
/leading fontSize 1.5 mul def % 150% = loose, airy
1.13.4. Check Text Bounds
/showInBounds { % x y width text -> -
4 dict begin
/text exch def
/maxWidth exch def
/y exch def
/x exch def
text stringwidth pop maxWidth gt {
% Text too wide, scale down
/Times-Roman findfont
maxWidth text stringwidth pop div 12 mul
scalefont setfont
} if
x y moveto text show
end
} def
1.14. Common Pitfalls
1.14.1. Forgetting Current Point
% Wrong: no current point
(Text) show % ERROR: nocurrentpoint
% Correct: set position first
100 100 moveto
(Text) show
1.15. Performance Tips
1.15.1. Minimize Font Changes
% Good: batch by font
/Times-Roman findfont 12 scalefont setfont
100 100 moveto (Line 1) show
100 85 moveto (Line 2) show
100 70 moveto (Line 3) show
% Less efficient: font changes
/Times-Roman findfont 12 scalefont setfont
100 100 moveto (Line 1) show
/Helvetica findfont 12 scalefont setfont
100 85 moveto (Line 2) show
/Times-Roman findfont 12 scalefont setfont
100 70 moveto (Line 3) show
1.16. See Also
-
Font & Text Commands - Complete command reference
-
show - Display text
-
findfont - Find font
-
scalefont - Scale font
-
setfont - Set current font
-
stringwidth - Measure text
-
charpath - Text to path
-
Color Spaces - Text colors
-
Graphics State - Text rendering state