Skip to content

API reference / Common / Engine types / TextDrawing

Interface: TextDrawing ​

A drawing embedded in a span (docx w:drawing, or the legacy w:pict) — an image, shape, chart, diagram or group placed in the text flow.

The text model's embedding point for the shape sub-tree, the span-level twin of TextTable: one atomic slot in the parent story, its content edited in the node's own space. A DrawingML a:txBody has no such run — this is docx-only, honored by the wordprocessing host and ignored by the rest (the superset-union rule).

Inline and floating are one element ​

w:drawing holds exactly one child, wp:inline or wp:anchor, and that choice is the inline-vs-floating distinction — so it is one level down here too, in placement, rather than two span variants. CT_Anchor is CT_Inline plus its positioning: everything above placement is carried identically by both, and the fields that differ are exactly what [TextFloatingPlacement] holds. Keeping them one variant is also what makes Word's "In Line with Text" ↔ "Square" a placement swap, leaving the node — and any story inside it — where it is, rather than a delete and re-insert that the CRDT would see as a new object.

A floating drawing is still anchored at this span: wp:positionV's paragraph and line origins, and wp:positionH's character, are all stated against where the span sits, and deleting the anchoring text deletes the drawing with it. Only its advance differs — a floating drawing contributes none, and the frame lifts it out of the line as an exclusion.

Identity is its own, not its content's ​

id is the drawing's, and the shape tree it holds carries its own ids underneath. The wrapper is what the text model owns — it has its own extents, placement, locks and clearances, and it outlives any one payload — so borrowing the root node's id for it would tie the drawing's identity to a field of its content, which a payload swap rewrites.

Size lives here, not only on the node ​

extents is wp:extent, and it is stored rather than derived from the node's own a:ext: the two disagree in real documents (Word's rounding drift across a resize), and wp:extent — grown by effect_extent — is the one that reserves the line box.

Properties ​

PropertyDescription
id
string
Stable model id.
properties?
TextCharacterProperties
w:rPr — the drawing span's own character properties. Load-bearing, unlike a pptx atom's: w:position raises or lowers an inline drawing off the baseline, w:vanish hides it with the hidden text around it, and w:noProof rides here on nearly every drawing Word writes.
extents
ShapeExtents
wp:extent — the size of the drawing itself, without its effects.
effectExtent?
TextDrawingEffectExtent
wp:effectExtent — how far the drawing's shadow, reflection or glow reaches past extents on each edge, which the text keeps clear of as it does the drawing. Not derivable: we do not compute effect spread, so it is carried as written.
distance?
TextDrawingWrapDistance
distT / distB / distL / distR — how far text keeps clear of the drawing, on every edge. The only clearance in the model. The file also lets each wrap element restate these, overriding the drawing's for that wrap; the importer folds the override in here so an editor has one value to read and one to write, rather than two that can disagree.
locks?
ShapeGraphicFrameLocks
wp:cNvGraphicFramePr/a:graphicFrameLocks — the edits the drawing refuses.
legacy?
boolean
The drawing was written as a VML w:pict rather than a w:drawing, and is to be written back as one. A bool and not a variant of its own: after import a w:pict is a drawing — its v:shape lowers to the same node and its style / w10:wrap to the same placement, field for field — so the encoding is the only thing left to remember. It still has to be remembered: a header watermark is a VML shape of type #_x0000_t136, and re-emitting it as DrawingML is what stops Word's Remove Watermark from recognizing it. The VML declarations themselves stay in the format layer.
placement?
TextDrawingPlacement
wp:inline vs wp:anchor — how the drawing meets the text.
tree
ShapeTree
a:graphic/a:graphicData — the drawing itself, as a shape tree. a:graphicData holds one payload element and every payload is one node — pic:pic a picture, wps:wsp a shape, and the container ones a group (wpg:wgp is ShapeGroup field for field, wpc:wpc likewise) — so the tree's root is that payload, and it is conventionally not a group the way a slide's root is. A [ShapeTree] and not the bare [ShapeNode] it wraps, because a drawing's interior has its own pin / mark / update lifecycle: an editor types in a wps:txbx text box and picks a child of a group, and what carries the marks that reach them — mark_shape_*, text_frame_mut, the update pass — is ComposedShapeTree, whose pin and update take a &ShapeTree. So the run holds a ComposedShapeTree and this holds its model; both sides moved together. wp:docPr rides the root node's ShapeNonVisualProperties, which already names that mapping.