- 1. Graphics State
- 1.1. Overview
- 1.2. The Graphics State Stack
- 1.3. Color Parameters
- 1.4. Line Attributes
- 1.5. Clipping
- 1.6. Font State
- 1.7. Transformation Matrix
- 1.8. Graphics State Objects (Level 2)
- 1.9. Practical Graphics State Patterns
- 1.10. Common Graphics State Tasks
- 1.11. Best Practices
- 1.12. Debugging Graphics State
- 1.13. Common Pitfalls
- 1.14. See Also
1. Graphics State
The graphics state contains all parameters that affect the appearance of rendered graphics. Managing the graphics state effectively is essential for consistent and predictable output.
1.1. Overview
The graphics state is a collection of parameters that control how graphics are rendered:
-
Current path - The path being constructed
-
Current position - The position within the path
-
Color - Current color for fill and stroke operations
-
Line attributes - Width, cap style, join style, dash pattern
-
Transformation matrix - Coordinate system transformations
-
Clipping path - Region where graphics can appear
-
Font - Current font and size
These parameters persist until explicitly changed or the graphics state is restored.
1.2. The Graphics State Stack
1.2.1. Saving State with gsave
The gsave operator pushes the current graphics state onto the stack:
% Set some graphics parameters
1 0 0 setrgbcolor % Red
2 setlinewidth % 2-point line
% Save current state
gsave
% Modify state
0 1 0 setrgbcolor % Green
5 setlinewidth % 5-point line
% Draw something
0 0 100 100 rectfill
% State is still modified here
1.2.2. Restoring State with grestore
The grestore operator pops the graphics state from the stack:
gsave
% Set temporary state
0 1 0 setrgbcolor
5 setlinewidth
% Draw
0 0 100 100 rectfill
grestore
% Color and line width are restored to pre-gsave values
% Back to red and 2-point lines
0 0 moveto
200 0 lineto
stroke
1.2.3. Nested State Management
Graphics state operations can be nested:
% Initial state: black, 1-point line
gsave % Level 1
1 0 0 setrgbcolor % Red
gsave % Level 2
0 1 0 setrgbcolor % Green
3 setlinewidth
% Draw green with thick line
grestore % Back to level 1: red, 1-point
% Draw red with 1-point line
grestore % Back to initial: black, 1-point
1.3. Color Parameters
1.3.1. Gray Color
Set grayscale values (0 = black, 1 = white):
% Set gray for fill and stroke
0 setgray % Black
0.5 setgray % 50% gray
1 setgray % White
% Query current gray
currentgray % Returns current gray value (0-1)
1.3.2. RGB Color
Set red-green-blue color components (each 0-1):
% RGB: red green blue
1 0 0 setrgbcolor % Pure red
0 1 0 setrgbcolor % Pure green
0 0 1 setrgbcolor % Pure blue
0.5 0.5 0.5 setrgbcolor % Gray
1 1 0 setrgbcolor % Yellow
0 1 1 setrgbcolor % Cyan
% Query current RGB
currentrgbcolor % Returns: r g b
Creating custom colors:
% Define color constants
/Navy { 0 0 0.5 setrgbcolor } def
/Orange { 1 0.647 0 setrgbcolor } def
/Purple { 0.502 0 0.502 setrgbcolor } def
% Use them
Navy
0 0 100 100 rectfill
Orange
200 0 100 100 rectfill
1.3.3. CMYK Color
Set cyan-magenta-yellow-black components (each 0-1):
% CMYK: cyan magenta yellow black
0 0 0 1 setcmykcolor % Pure black
1 0 0 0 setcmykcolor % Pure cyan
0 1 0 0 setcmykcolor % Pure magenta
0 0 1 0 setcmykcolor % Pure yellow
% Query current CMYK
currentcmykcolor % Returns: c m y k
1.3.4. HSB Color
Set hue-saturation-brightness (hue: 0-360, saturation and brightness: 0-1):
% HSB: hue saturation brightness
0 1 1 sethsbcolor % Pure red
120 1 1 sethsbcolor % Pure green
240 1 1 sethsbcolor % Pure blue
60 1 1 sethsbcolor % Yellow
% Pastel colors (low saturation)
0 0.3 1 sethsbcolor % Pastel red
% Query current HSB
currenthsbcolor % Returns: h s b
1.4. Line Attributes
1.4.1. Line Width
Set the width of stroked lines (in user space units):
% Set line width
0.5 setlinewidth % Thin line
1 setlinewidth % Default
5 setlinewidth % Thick line
10 setlinewidth % Very thick line
% Query current line width
currentlinewidth % Returns current width
% Example
newpath
1 setlinewidth
0 100 moveto 100 100 lineto stroke
5 setlinewidth
0 110 moveto 100 110 lineto stroke
10 setlinewidth
0 120 moveto 100 120 lineto stroke
1.4.2. Line Cap Style
Controls the shape of line endpoints:
% Line cap styles:
% 0 = butt cap (default) - square end at endpoint
% 1 = round cap - semicircular end
% 2 = projecting square cap - extends beyond endpoint
0 setlinecap % Butt cap
1 setlinecap % Round cap
2 setlinecap % Square cap
% Query current line cap
currentlinecap % Returns 0, 1, or 2
Visual comparison:
10 setlinewidth
% Butt cap
0 setlinecap
0 100 moveto 100 100 lineto stroke
% Round cap
1 setlinecap
0 120 moveto 100 120 lineto stroke
% Square cap
2 setlinecap
0 140 moveto 100 140 lineto stroke
1.4.3. Line Join Style
Controls how line segments connect:
% Line join styles:
% 0 = miter join (default) - pointed join
% 1 = round join - circular join
% 2 = bevel join - beveled join
0 setlinejoin % Miter join
1 setlinejoin % Round join
2 setlinejoin % Bevel join
% Query current line join
currentlinejoin % Returns 0, 1, or 2
Visual comparison with angles:
10 setlinewidth
% Miter join
0 setlinejoin
newpath
0 100 moveto
50 150 lineto
100 100 lineto
stroke
% Round join
1 setlinejoin
newpath
0 120 moveto
50 170 lineto
100 120 lineto
stroke
% Bevel join
2 setlinejoin
newpath
0 140 moveto
50 190 lineto
100 140 lineto
stroke
1.4.4. Miter Limit
Controls when miter joins are beveled (only applies to miter joins):
% Miter limit (default is 10)
% Ratio of miter length to line width
% Smaller values bevel sharper angles
10 setmiterlimit % Default
4 setmiterlimit % More aggressive beveling
1 setmiterlimit % Very aggressive
% Query current miter limit
currentmiterlimit % Returns current limit
Practical example:
20 setlinewidth
0 setlinejoin % Miter join
% Sharp angle with high miter limit
10 setmiterlimit
newpath
0 100 moveto
50 150 lineto
100 100 lineto
stroke
% Same angle with low miter limit (will bevel)
1 setmiterlimit
newpath
0 200 moveto
50 250 lineto
100 200 lineto
stroke
1.4.5. Dash Pattern
Creates dashed or dotted lines:
% setdash: array offset setdash
% array = [on off on off ...]
% offset = starting offset into pattern
% Solid line (default)
[] 0 setdash
% Simple dash pattern
[5 3] 0 setdash % 5 on, 3 off
0 100 moveto 200 100 lineto stroke
% Dash-dot pattern
[10 5 2 5] 0 setdash
0 110 moveto 200 110 lineto stroke
% Dotted line
[1 3] 0 setdash
0 120 moveto 200 120 lineto stroke
% Query current dash
currentdash % Returns: array offset
Pattern with offset:
[10 5] 0 setdash
0 100 moveto 200 100 lineto stroke
% Same pattern, different offset
[10 5] 5 setdash
0 110 moveto 200 110 lineto stroke
1.5. Clipping
1.5.1. Setting the Clipping Path
The clipping path restricts where graphics can appear:
% Create a clipping path
gsave
newpath
100 100 100 0 360 arc
clip % Set as clipping path
newpath % Start new path (don't stroke clip path)
% Only visible inside circle
0 0 200 200 rectfill
grestore
1.5.2. Even-Odd Clipping
Alternative clipping rule:
gsave
% Create complex path with holes
newpath
50 50 150 0 360 arc
100 100 50 0 360 arc
eoclip % Even-odd clip
newpath
% Fill shows holes
0 0 300 300 rectfill
grestore
1.6. Font State
1.7. Transformation Matrix
1.8. Graphics State Objects (Level 2)
1.8.1. Creating a Graphics State Object
Save parameters in a reusable object:
% Create gstate object
gstate % Creates empty gstate
currentgstate % Fills with current state
% Store for later use
/myState currentgstate def
1.8.2. Using Graphics State Objects
% Save current state
/savedState currentgstate def
% Modify state
1 0 0 setrgbcolor
5 setlinewidth
45 rotate
% Restore from saved state
savedState setgstate
% Back to state when we saved it
Practical example - switching between two states:
% Define two different states
/redThick gstate def
redThick currentgstate pop
redThick /PaintType 1 0 0 setrgbcolor
redThick /LineWidth 5 setlinewidth
/blueThin gstate def
blueThin currentgstate pop
blueThin /PaintType 0 0 1 setrgbcolor
blueThin /LineWidth 1 setlinewidth
% Use them
redThick setgstate
0 100 moveto 200 100 lineto stroke
blueThin setgstate
0 110 moveto 200 110 lineto stroke
redThick setgstate
0 120 moveto 200 120 lineto stroke
1.9. Practical Graphics State Patterns
1.9.1. Pattern 1: Temporary Style Changes
% Draw with temporary style
/withStyle { % ... procedure ... -> -
gsave
% Set style
1 0 0 setrgbcolor
3 setlinewidth
[5 3] 0 setdash
% Execute procedure
exec
grestore
} def
% Usage
{
0 0 moveto
100 100 lineto
stroke
} withStyle
1.9.2. Pattern 2: Style Inheritance
% Base style
/baseStyle {
/Helvetica findfont 12 scalefont setfont
0 setgray
1 setlinewidth
} def
% Heading style (inherits from base)
/headingStyle {
baseStyle
/Helvetica-Bold findfont 18 scalefont setfont
} def
% Use them
baseStyle
100 100 moveto (Body text) show
headingStyle
100 120 moveto (Heading) show
1.9.3. Pattern 3: State Snapshot
% Take snapshot of current state
/snapshot {
20 dict begin
/savedGray currentgray def
/savedLineWidth currentlinewidth def
/savedLineCap currentlinecap def
/savedLineJoin currentlinejoin def
/savedDash currentdash def
/savedFont currentfont def
% ... other parameters
currentdict end
} def
% Restore snapshot
/restore {
begin
savedGray setgray
savedLineWidth setlinewidth
savedLineCap setlinecap
savedLineJoin setlinejoin
savedDash aload pop setdash
savedFont setfont
end
} def
1.10. Common Graphics State Tasks
1.10.1. Drawing with Multiple Styles
% Draw border and fill with different styles
gsave
% Fill
0.9 0.9 1 setrgbcolor
100 100 200 150 rectfill
grestore
gsave
% Border
0 0 0.5 setrgbcolor
2 setlinewidth
100 100 200 150 rectstroke
grestore
1.10.2. Creating Gradients (Manual)
% Horizontal gradient (simplified)
/gradient { % y1 y2 -> -
10 {
dup 10 div setgray
100 2 index 200 1 rectfill
1 add
} repeat
pop pop
} def
100 200 gradient
1.10.3. Style-based Drawing Functions
% Draw rectangle with specified style
/styledRect { % x y w h style -> -
5 dict begin
/style exch def
/h exch def
/w exch def
/y exch def
/x exch def
gsave
style exec
x y w h rectfill
grestore
end
} def
% Define styles
/redStyle { 1 0 0 setrgbcolor } def
/blueStyle { 0 0 1 setrgbcolor } def
% Use them
100 100 50 50 redStyle styledRect
200 100 50 50 blueStyle styledRect
1.11. Best Practices
1.11.1. Always Balance gsave/grestore
% Good: balanced
gsave
% ...
grestore
% Bad: unbalanced
gsave
% ... missing grestore
gsave
% ... too many gsave
1.11.2. Use Meaningful State Boundaries
% Good: logical grouping
gsave
% Set up for drawing shape
1 0 0 setrgbcolor
2 setlinewidth
% Draw shape
100 100 50 0 360 arc
stroke
grestore
% Bad: arbitrary boundaries
gsave
1 0 0 setrgbcolor
grestore
gsave
2 setlinewidth
100 100 50 0 360 arc
grestore
1.12. Debugging Graphics State
1.12.1. Print Current State
/printState {
(=== Graphics State ===) print
(Gray: ) print currentgray =
(RGB: ) print currentrgbcolor pop pop =
(Line Width: ) print currentlinewidth =
(Line Cap: ) print currentlinecap =
(Line Join: ) print currentlinejoin =
(Dash: ) print currentdash pop =
(Font: ) print currentfont /FontName get =
} def
% Usage
printState
1.13. Common Pitfalls
1.13.1. Modifying State Without Saving
% Wrong: permanent change
1 0 0 setrgbcolor
% Everything after this is red!
% Correct: temporary change
gsave
1 0 0 setrgbcolor
% Draw red things
grestore
% Color restored
1.14. See Also
-
Coordinate Systems - Transformation matrix details
-
Painting - Using graphics state for rendering
-
Graphics State Commands - Complete command reference
-
gsave - Save graphics state
-
grestore - Restore graphics state
-
setlinewidth - Set line width
-
setrgbcolor - Set RGB color