A content stream is the program that draws a page, a form, a pattern, a Type 3 glyph
or an annotation’s appearance. It is a stream of operands and operators in postfix
order: the operands first, then the operator that uses them, as in
72 720 m. Operands are PDF objects: numbers, strings, names, arrays and
dictionaries, but never references. Operators are bare words. PDF 1.5 to 2.0 have 73
operators, every one of which was already in PDF 1.3: these versions added none.
An example
q
1 0 0 RG 2 w
72 700 m 540 700 l S
Q
BT
/F1 24 Tf
72 712 Td
(Hello, world) Tj
ET
q 200 0 0 100 72 500 cm /Im1 Do Q
Coordinates are in user space, by default 1/72 inch with the origin at the bottom
left of the page. F1 and Im1 are names in the page’s
resources.
q and Q save and restore the graphics state, so the red
colour and the image’s scaling do not leak into what follows.
How operators may be used
Operators can only appear in certain places. Outside any object, at page level, a
stream may change the graphics state, start a path, start a text object, paint a
shading, draw an XObject or an inline image, or mark content. Once a path is begun with
m or re, only path construction operators may follow until a
painting operator (or n) ends it; a clipping operator
W or W* may come just before the painting operator. Text
showing and positioning operators may appear only between BT and
ET, and text objects do not nest. q and Q must
balance within a stream, and should not appear inside a text object. Readers are
usually lenient where writers break these rules.
An unknown operator is an error, unless it falls between BX and
EX.
All the operators
In the tables “Since” is the version that added the operator. The operand names follow ISO 32000.
General graphics state
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| lineWidth | w | 1.0 | Set the line width, in user space units; 0 means the thinnest line the device can draw |
| lineCap | J | 1.0 | Set the line cap: 0 butt, 1 round, 2 projecting square |
| lineJoin | j | 1.0 | Set the line join: 0 mitre, 1 round, 2 bevel |
| miterLimit | M | 1.0 | Set the mitre limit, default 10: above it a mitre join becomes a bevel |
| dashArray dashPhase | d | 1.0 | Set the dash pattern: [3 2] 0 d is 3 on, 2 off; [] 0 d is solid |
| intent | ri | 1.1 | Set the rendering intent: AbsoluteColorimetric, RelativeColorimetric, Saturation or Perceptual |
| flatness | i | 1.0 | Set the flatness tolerance, 0 to 100, in device pixels; 0 is the device default |
| dictName | gs | 1.2 | Set the parameters in the named graphics state parameter dictionary of the ExtGState resources |
Special graphics state
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | q | 1.0 | Save the whole graphics state on a stack |
| – | Q | 1.0 | Restore the last saved graphics state |
| a b c d e f | cm | 1.0 | Multiply the current transformation matrix by [a b c d e f]: 1 0 0 1 tx ty cm moves, sx 0 0 sy 0 0 cm scales |
Path construction
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| x y | m | 1.0 | Begin a new subpath at (x, y) |
| x y | l | 1.0 | Add a straight line to (x, y) |
| x1 y1 x2 y2 x3 y3 | c | 1.0 | Add a cubic Bézier curve to (x3, y3) with control points (x1, y1) and (x2, y2) |
| x2 y2 x3 y3 | v | 1.0 | Add a curve whose first control point is the current point |
| x1 y1 x3 y3 | y | 1.0 | Add a curve whose second control point is the end point |
| – | h | 1.0 | Close the subpath with a straight line back to its start |
| x y width height | re | 1.0 | Add a rectangle as a complete closed subpath |
Path painting
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | S | 1.0 | Stroke the path |
| – | s | 1.0 | Close and stroke the path, as h S |
| – | f | 1.0 | Fill the path, nonzero winding number rule; open subpaths are closed |
| – | F | 1.0 | The same as f, kept for old files; should not be written |
| – | f* | 1.0 | Fill the path, even-odd rule |
| – | B | 1.0 | Fill, nonzero rule, then stroke |
| – | B* | 1.0 | Fill, even-odd rule, then stroke |
| – | b | 1.0 | Close, fill with the nonzero rule, and stroke |
| – | b* | 1.0 | Close, fill with the even-odd rule, and stroke |
| – | n | 1.0 | End the path without painting it, usually after a clip |
Clipping
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | W | 1.0 | Intersect the clipping path with the current path, nonzero rule, once the path is painted |
| – | W* | 1.0 | The same with the even-odd rule |
The clip takes effect after the painting operator that follows, so
0 0 100 100 re W n clips to a square without drawing it. A clip can only
shrink; Q is the only way to widen it again.
Text objects
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | BT | 1.0 | Begin a text object: set the text matrix and the text line matrix to the identity |
| – | ET | 1.0 | End the text object, and apply any clip collected by the text rendering modes 4 to 7 |
Text state
These may also be used outside a text object; the values belong to the graphics
state, and q and Q save and restore them.
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| charSpace | Tc | 1.0 | Character spacing, added after every glyph, in unscaled text space units; default 0 |
| wordSpace | Tw | 1.0 | Word spacing, added after each single-byte code 32; default 0. It does not apply to multi-byte codes |
| scale | Tz | 1.0 | Horizontal scaling, in per cent; default 100 |
| leading | TL | 1.0 | Leading, the distance between lines for T*, ' and "; default 0 |
| font size | Tf | 1.0 | Set the font, a name in the Font resources, and its size. There is no default font: text before Tf is an error |
| render | Tr | 1.0 | Text rendering mode, below; default 0 |
| rise | Ts | 1.0 | Text rise, a baseline shift for superscripts and subscripts; default 0 |
Text rendering modes
| Mode | Glyphs are |
|---|---|
| 0 | filled |
| 1 | stroked |
| 2 | filled, then stroked |
| 3 | neither filled nor stroked: invisible, as in the text layer over a scanned page |
| 4 | filled, and added to the clip |
| 5 | stroked, and added to the clip |
| 6 | filled, stroked, and added to the clip |
| 7 | only added to the clip |
Text positioning
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| tx ty | Td | 1.0 | Move to the start of the next line, offset by (tx, ty) from the start of the current one |
| tx ty | TD | 1.0 | The same, and set the leading to −ty: as −ty TL tx ty Td |
| a b c d e f | Tm | 1.0 | Set the text matrix and the text line matrix. It replaces them; it does not multiply |
| – | T* | 1.0 | Move to the start of the next line, using the leading: as 0 −leading Td |
Text showing
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| string | Tj | 1.0 | Show the string: its bytes are character codes in the current font’s encoding |
| array | TJ | 1.0 | Show strings with adjustments: each number in the array moves the next glyph back by that many thousandths of a text space unit, so [(A) 120 (V)] TJ kerns “AV” closer |
| string | ' | 1.0 | Move to the next line and show the string: as T* string Tj |
| aw ac string | " | 1.0 | Set word spacing to aw and character spacing to ac, move to the next line and show the string |
After each glyph the text matrix moves by the glyph’s width from the font, scaled by the font size and horizontal scaling, plus the character and word spacing. The bytes of a string are character codes, not text: for a Type 0 font a code may be several bytes, as its CMap says. Getting text out of a PDF means mapping the codes back to Unicode through the font’s ToUnicode CMap or encoding.
Type 3 fonts
Only as the first operator in a glyph procedure of a Type 3 font:
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| wx wy | d0 | 1.0 | Set the glyph’s width; the glyph may set its own colour |
| wx wy llx lly urx ury | d1 | 1.0 | Set the width and the bounding box; the glyph is a shape painted in the current colour, and colour operators in it are ignored |
Colour
Upper case sets the stroking colour, lower case the non-stroking (fill) colour.
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| name | CS | 1.1 | Set the stroking colour space: a device space name, Pattern, or a name in the ColorSpace resources; the colour becomes the space’s initial colour |
| name | cs | 1.1 | Set the non-stroking colour space |
| c1 … cn | SC | 1.1 | Set the stroking colour in the current space, for device, CIE-based and Indexed spaces |
| c1 … cn [name] | SCN | 1.2 | The same, and also for Pattern, Separation, DeviceN and ICCBased spaces; with a pattern, the last operand is the pattern’s name |
| c1 … cn | sc | 1.1 | Set the non-stroking colour |
| c1 … cn [name] | scn | 1.2 | Set the non-stroking colour, for every kind of space |
| gray | G | 1.0 | Set the stroking space to DeviceGray and the grey level, 0 black to 1 white |
| gray | g | 1.0 | The same for non-stroking |
| r g b | RG | 1.0 | Set the stroking space to DeviceRGB and the colour |
| r g b | rg | 1.0 | The same for non-stroking |
| c m y k | K | 1.0 | Set the stroking space to DeviceCMYK and the colour |
| c m y k | k | 1.0 | The same for non-stroking |
Shading
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| name | sh | 1.3 | Paint the named shading from the Shading resources over the whole current clip |
Inline images
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | BI | 1.0 | Begin an inline image: key and value pairs follow |
| – | ID | 1.0 | Begin the image data: one white-space byte, then the data |
| – | EI | 1.0 | End the inline image |
The keys and their short forms are on
Images.
Finding EI is the hardest part of parsing a content stream: the data
has no length unless the writer gives one (PDF 2.0 adds an optional
L, Length, key), and may itself contain the bytes
EI.
XObjects
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| name | Do | 1.0 | Draw the named XObject from the XObject resources: an image, painted into the unit square of the current matrix, or a form, run as its own content stream |
Marked content
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| tag | MP | 1.2 | A marked-content point |
| tag properties | DP | 1.2 | A marked-content point with a property list: a dictionary, or the name of one in the Properties resources |
| tag | BMC | 1.2 | Begin a marked-content sequence |
| tag properties | BDC | 1.2 | Begin a marked-content sequence with a property list |
| – | EMC | 1.2 | End the sequence |
Sequences nest and must balance within the stream. Three uses matter most:
- Tagged PDF:
/P <</MCID 3>> BDC … EMCties the content to a structure element by its MCID. - Optional content:
/OC /oc1 BDC … EMC, whereoc1is a name in thePropertiesresources for an optional content group or membership dictionary. The content is drawn only if the group is on. - Artifacts:
/Artifact BMC … EMCmarks page furniture such as headers and page numbers that is not part of the text.
A property list may also carry ActualText, Alt and
Lang for the content it marks.
Compatibility
| Operands | Operator | Since | Meaning |
|---|---|---|---|
| – | BX | 1.1 | Begin a compatibility section: unknown operators until the matching EX are ignored, with their operands |
| – | EX | 1.1 | End the compatibility section |
Sections nest. They were meant for operators of later versions; since none has been added after PDF 1.3, they are now rarely seen.
The operators in alphabetical order
All 73, as the tables above give them: b B
b* B* BDC BI BMC
BT BX c cm CS
cs d d0 d1 Do
DP EI EMC ET EX
f F f* G g
gs h i ID j
J K k l m
M MP n q Q
re RG rg ri s
S SC sc SCN scn
sh T* Tc Td TD
Tf Tj TJ TL Tm
Tr Ts Tw Tz v
w W W* y '
".
Sixteen came after PDF 1.0: BX, EX, CS,
cs, SC, sc and ri in 1.1;
BDC, BMC, EMC, MP,
DP, gs, SCN and scn in 1.2; and
sh in 1.3. Everything new in PDF 1.4 to 2.0, such as transparency and
optional content, works through graphics state dictionaries, resources and marked
content, not new operators.