Skip to content

shape

shape

Custom element classes for shape-related elements like <w:inline>.

CT_Anchor

Bases: BaseOxmlElement

<wp:anchor> element, container for a "floating" shape.

Where wp:inline puts a picture in the text flow like a character, wp:anchor detaches it: the picture is positioned against the page, the margin, the column or the paragraph, and text wraps around it.

The schema type is an xsd:sequence and Word refuses to open a document whose children are out of order, so the successors bookkeeping below matters more than usual. The wrap element is one of an xsd:choice — exactly one must be present — which is why it is reached through wrap_type rather than as five separate declared children.

wrap_type property writable

wrap_type: WD_WRAP_TYPE

Member of WdWrapType describing how text wraps around this shape.

new_pic_anchor classmethod

new_pic_anchor(
    shape_id: int,
    rId: str,
    filename: str,
    cx: Length,
    cy: Length,
    pos_x: Length,
    pos_y: Length,
    description: str | None = None,
    title: str | None = None,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Anchor

Create a wp:anchor element containing a pic:pic element.

The shape is positioned pos_x right of and pos_y below the column and paragraph it is anchored to, which is where Word puts a picture converted from inline to floating, and text wraps around its bounding rectangle.

Source code in src/docx/oxml/shape.py
@classmethod
def new_pic_anchor(
    cls,
    shape_id: int,
    rId: str,
    filename: str,
    cx: Length,
    cy: Length,
    pos_x: Length,
    pos_y: Length,
    description: str | None = None,
    title: str | None = None,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Anchor:
    """Create a `wp:anchor` element containing a `pic:pic` element.

    The shape is positioned `pos_x` right of and `pos_y` below the column and
    paragraph it is anchored to, which is where Word puts a picture converted from
    inline to floating, and text wraps around its bounding rectangle.
    """
    pic_id = 0  # -- as with an inline picture, Word does not appear to use this --
    pic = CT_Picture.new(pic_id, filename, rId, cx, cy, svg_rId=svg_rId, transform=transform)
    anchor = cast(CT_Anchor, parse_xml(cls._anchor_xml()))
    anchor.extent.cx = cx
    anchor.extent.cy = cy
    anchor.positionH.offset = pos_x
    anchor.positionV.offset = pos_y
    anchor.docPr.id = shape_id
    anchor.docPr.name = "Picture %d" % shape_id
    if description is not None:
        anchor.docPr.descr = description
    if title is not None:
        anchor.docPr.title = title
    anchor.graphic.graphicData.uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
    anchor.graphic.graphicData._insert_pic(pic)  # pyright: ignore[reportPrivateUsage]
    return anchor

_CT_PosBase

Bases: BaseOxmlElement

Common behavior of wp:positionH and wp:positionV.

Both hold an xsd:choice of wp:align or wp:posOffset — a named alignment such as "center", or an absolute distance in EMU. Setting one removes the other, since the schema allows only one to be present and Word ignores a document that has both.

align property writable

align

The named alignment of this position, or None when an offset is used.

offset property writable

offset: Length | None

The absolute offset of this position, or None when an alignment is used.

CT_PosH

Bases: _CT_PosBase

<wp:positionH> element, the horizontal position of a floating shape.

CT_PosV

Bases: _CT_PosBase

<wp:positionV> element, the vertical position of a floating shape.

CT_Blip

Bases: BaseOxmlElement

<a:blip> element, specifies image source and adjustments such as alpha and tint.

svgBlip property

svgBlip: CT_SvgBlip | None

The asvg:svgBlip extension of this blip, or None when there is none.

Reached by xpath rather than a declared child, because a:ext is already registered as the extent element of a:xfrm and lxml dispatches on tag name alone; the same tag means two different things in DrawingML.

CT_SvgBlip

Bases: BaseOxmlElement

<asvg:svgBlip> element, the SVG source of a picture.

A Word 2016 extension. It accompanies rather than replaces the raster blip: a consumer that does not understand the extension renders the raster one instead.

CT_BlipFillProperties

Bases: BaseOxmlElement

<pic:blipFill> element, specifies picture properties.

CT_GraphicalObject

Bases: BaseOxmlElement

<a:graphic> element, container for a DrawingML object.

CT_GraphicalObjectData

Bases: BaseOxmlElement

<a:graphicData> element, container for the XML of a DrawingML object.

CT_Inline

Bases: BaseOxmlElement

<wp:inline> element, container for an inline shape.

new classmethod

new(
    cx: Length, cy: Length, shape_id: int, pic: CT_Picture
) -> CT_Inline

Return a new <wp:inline> element populated with the values passed as parameters.

Source code in src/docx/oxml/shape.py
@classmethod
def new(cls, cx: Length, cy: Length, shape_id: int, pic: CT_Picture) -> CT_Inline:
    """Return a new ``<wp:inline>`` element populated with the values passed as
    parameters."""
    inline = cast(CT_Inline, parse_xml(cls._inline_xml()))
    inline.extent.cx = cx
    inline.extent.cy = cy
    inline.docPr.id = shape_id
    inline.docPr.name = "Picture %d" % shape_id
    inline.graphic.graphicData.uri = "http://schemas.openxmlformats.org/drawingml/2006/picture"
    inline.graphic.graphicData._insert_pic(pic)
    return inline

new_pic_inline classmethod

new_pic_inline(
    shape_id: int,
    rId: str,
    filename: str,
    cx: Length,
    cy: Length,
    description: str | None = None,
    title: str | None = None,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Inline

Create wp:inline element containing a pic:pic element.

The contents of the pic:pic element is taken from the argument values. description and title are the alternative text of the picture and are omitted when None. svg_rId, when given, identifies the SVG source of the picture, making rId its raster fallback. transform is the rotation and flip expressing the source image's EXIF orientation.

cx and cy are the display dimensions, so they become the wp:extent and the layout reserves the space the rotated picture actually occupies.

Source code in src/docx/oxml/shape.py
@classmethod
def new_pic_inline(
    cls,
    shape_id: int,
    rId: str,
    filename: str,
    cx: Length,
    cy: Length,
    description: str | None = None,
    title: str | None = None,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Inline:
    """Create `wp:inline` element containing a `pic:pic` element.

    The contents of the `pic:pic` element is taken from the argument values.
    `description` and `title` are the alternative text of the picture and are
    omitted when |None|. `svg_rId`, when given, identifies the SVG source of the
    picture, making `rId` its raster fallback. `transform` is the rotation and flip
    expressing the source image's EXIF orientation.

    `cx` and `cy` are the *display* dimensions, so they become the `wp:extent` and
    the layout reserves the space the rotated picture actually occupies.
    """
    pic_id = 0  # Word doesn't seem to use this, but does not omit it
    pic = CT_Picture.new(pic_id, filename, rId, cx, cy, svg_rId=svg_rId, transform=transform)
    inline = cls.new(cx, cy, shape_id, pic)
    if description is not None:
        inline.docPr.descr = description
    if title is not None:
        inline.docPr.title = title
    return inline

CT_NonVisualDrawingProps

Bases: BaseOxmlElement

Used for <wp:docPr> element, and perhaps others.

Specifies the id and name of a DrawingML drawing, and its alternative text.

CT_NonVisualPictureProperties

Bases: BaseOxmlElement

<pic:cNvPicPr> element, specifies picture locking and resize behaviors.

CT_Picture

Bases: BaseOxmlElement

<pic:pic> element, a DrawingML picture.

new classmethod

new(
    pic_id: int,
    filename: str,
    rId: str,
    cx: Length,
    cy: Length,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Picture

A new minimum viable <pic:pic> (picture) element.

cx and cy are the display dimensions. transform is the (rotation, flip_h) pair expressing the source image's EXIF orientation, in the units a:xfrm/@rot uses; it is omitted when it is the no-op (0, False).

rId identifies the image the raster blip refers to. When svg_rId is given the picture also carries an asvg:svgBlip extension referring to that SVG, and rId is the raster fallback shown by anything that does not understand the extension.

Source code in src/docx/oxml/shape.py
@classmethod
def new(
    cls,
    pic_id: int,
    filename: str,
    rId: str,
    cx: Length,
    cy: Length,
    svg_rId: str | None = None,
    transform: tuple[int, bool] = (0, False),
) -> CT_Picture:
    """A new minimum viable `<pic:pic>` (picture) element.

    `cx` and `cy` are the *display* dimensions. `transform` is the
    `(rotation, flip_h)` pair expressing the source image's EXIF orientation, in the
    units `a:xfrm/@rot` uses; it is omitted when it is the no-op `(0, False)`.

    `rId` identifies the image the raster blip refers to. When `svg_rId` is given
    the picture also carries an `asvg:svgBlip` extension referring to that SVG, and
    `rId` is the raster fallback shown by anything that does not understand the
    extension.
    """
    pic = parse_xml(cls._pic_xml_svg() if svg_rId else cls._pic_xml())
    pic.nvPicPr.cNvPr.id = pic_id
    pic.nvPicPr.cNvPr.name = filename
    pic.blipFill.blip.embed = rId
    if svg_rId:
        svgBlip = pic.blipFill.blip.svgBlip
        assert svgBlip is not None
        svgBlip.embed = svg_rId
    rotation, flip_h = transform
    if rotation in (90 * 60000, 270 * 60000):
        # -- `a:ext` is the box the shape occupies *before* rotation, which for a
        # -- quarter turn is the display box with its sides exchanged. The
        # -- containing `wp:extent` stays the display box, so the layout reserves
        # -- the right space. --
        pic.spPr.cx, pic.spPr.cy = Emu(cy), Emu(cx)
    else:
        pic.spPr.cx = cx
        pic.spPr.cy = cy
    pic.spPr.apply_transform(rotation, flip_h)
    return pic

CT_PictureNonVisual

Bases: BaseOxmlElement

<pic:nvPicPr> element, non-visual picture properties.

CT_Point2D

Bases: BaseOxmlElement

Used for <a:off> element, and perhaps others.

Specifies an x, y coordinate (point).

CT_PositiveSize2D

Bases: BaseOxmlElement

Used for <wp:extent> element, and perhaps others later.

Specifies the size of a DrawingML drawing.

CT_PresetGeometry2D

Bases: BaseOxmlElement

<a:prstGeom> element, specifies an preset autoshape geometry, such as rect.

CT_RelativeRect

Bases: BaseOxmlElement

<a:fillRect> element, specifying picture should fill containing rectangle shape.

CT_ShapeProperties

Bases: BaseOxmlElement

<pic:spPr> element, specifies size and shape of picture container.

cx property writable

cx

Shape width as an instance of Emu, or None if not present.

cy property writable

cy

Shape height as an instance of Emu, or None if not present.

apply_transform

apply_transform(rotation: int, flip_h: bool) -> None

Rotate this shape by rotation, in 60000ths of a degree, and mirror it.

Both are omitted when they would be the no-op values, so an ordinary picture carries no rotation markup at all.

Source code in src/docx/oxml/shape.py
def apply_transform(self, rotation: int, flip_h: bool) -> None:
    """Rotate this shape by `rotation`, in 60000ths of a degree, and mirror it.

    Both are omitted when they would be the no-op values, so an ordinary picture
    carries no rotation markup at all.
    """
    if rotation == 0 and not flip_h:
        return
    xfrm = self.get_or_add_xfrm()
    if rotation:
        xfrm.rot = rotation
    if flip_h:
        xfrm.flipH = True

CT_StretchInfoProperties

Bases: BaseOxmlElement

<a:stretch> element, specifies how picture should fill its containing shape.

CT_Transform2D

Bases: BaseOxmlElement

<a:xfrm> element, specifies size and shape of picture container.

@rot is the rotation applied about the shape's centre, in 60000ths of a degree — 5400000 is a quarter turn clockwise. @flipH and @flipV mirror the shape. This is where an image's EXIF orientation lands: rotating the pixels themselves would mean a decode/encode dependency this library does not have, would lose quality, and would break the sha1 deduplication that keeps one copy of an image used twice.