Shapes - In General

Each visual element in a PowerPoint presentation is a shape. A shape appears on the “canvas” of a slide, which includes the various types of master. Within a slide, shapes appear in a shape tree, corresponding to an <p:spTree> element.

The following table summarizes the six shape types:

shape type

element

auto shape

<p:sp>

group shape

<p:grpSp>

graphicFrame

<p:graphicFrame>

connector

<p:cxnSp>

picture

<p:pic>

content part

<p:contentPart>

Some of these shape types have important sub-types. For example, a placeholder, a text box, and a preset geometry shape such as a circle, are all defined with an <p:sp> element.

<p:sp> shape elements

The <p:sp> element is used for three types of shape: placeholder, text box, and geometric shapes. A geometric shape with preset geometry is referred to as an auto shape. Placeholder shapes are documented on the Placeholders page. Auto shapes are documented on the Auto Shape page.

Geometric shapes are the familiar shapes that may be placed on a slide such as a rectangle or an ellipse. In the PowerPoint UI they are simply called shapes. There are two types of geometric shapes, preset geometry shapes and custom geometry shapes.

Shape.shape_id and Shape.name

Shape.shape_id is read-only and is assigned by python-pptx when necessary.

Proposed protocol:

>>> shape.shape_id
42
>>> shape.name
u'Picture 5'
>>> shape.name = 'T501 - Foo; B. Baz; 2014'
>>> shape.name
u'T501 - Foo; B. Baz; 2014'

Shape.rotation

Read/write float degrees of clockwise rotation. Negative values can be used for counter-clockwise rotation.

XML Semantics

ST_Angle is an integer value, 60,000 to each degree. PowerPoint appears to only ever use positive values. Oddly, the UI uses positive values for counter-clockwise rotation while the XML uses positive increase for clockwise rotation.

PowerPoint behavior

It appears graphic frame shapes can’t be rotated. AutoShape, group, connector, and picture all rotate fine.

Proposed protocol:

>>> shape.rotation
0.0
>>> shape.rotation = 45.2
>>> shape.rotation
45.2

Math:

def rot_from_angle(value):
    """
    Return positive integer rotation in 60,000ths of a degree
    corresponding to *value* expressed as a float number of degrees.
    """
    DEGREE_INCREMENTS = 60000
    THREE_SIXTY = 360 * DEGREE_INCREMENTS
    # modulo normalizes negative and >360 degree values
    return int(round(value * DEGREE_INCREMENTS)) % THREE_SIXTY

Specimen XML

Geometric shape (rounded rectangle):

<p:sp>
  <p:nvSpPr>
    <p:cNvPr id="3" name="Rounded Rectangle 2"/>
    <p:cNvSpPr/>
    <p:nvPr/>
  </p:nvSpPr>
  <p:spPr>
    <a:xfrm>
      <a:off x="760096" y="562720"/>
      <a:ext cx="2520824" cy="914400"/>
    </a:xfrm>
    <a:prstGeom prst="roundRect">
      <a:avLst>
        <a:gd name="adj" fmla="val 30346"/>
      </a:avLst>
    </a:prstGeom>
  </p:spPr>
  <p:style>
    <a:lnRef idx="1">
      <a:schemeClr val="accent1"/>
    </a:lnRef>
    <a:fillRef idx="3">
      <a:schemeClr val="accent1"/>
    </a:fillRef>
    <a:effectRef idx="2">
      <a:schemeClr val="accent1"/>
    </a:effectRef>
    <a:fontRef idx="minor">
      <a:schemeClr val="lt1"/>
    </a:fontRef>
  </p:style>
  <p:txBody>
    <a:bodyPr rtlCol="0" anchor="ctr"/>
    <a:lstStyle/>
    <a:p>
      <a:pPr algn="ctr"/>
      <a:r>
        <a:rPr lang="en-US" dirty="0" smtClean="0"/>
        <a:t>This is text inside a rounded rectangle</a:t>
      </a:r>
      <a:endParaRPr lang="en-US" dirty="0"/>
    </a:p>
  </p:txBody>
</p:sp>

Default textbox shape as inserted by PowerPoint:

<p:sp>
  <p:nvSpPr>
    <p:cNvPr id="2" name="TextBox 1"/>
    <p:cNvSpPr txBox="1"/>
    <p:nvPr/>
  </p:nvSpPr>
  <p:spPr>
    <a:xfrm>
      <a:off x="1997289" y="2529664"/>
      <a:ext cx="2390398" cy="369332"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
      <a:avLst/>
    </a:prstGeom>
    <a:noFill/>
  </p:spPr>
  <p:txBody>
    <a:bodyPr wrap="none" rtlCol="0">
      <a:spAutoFit/>
    </a:bodyPr>
    <a:lstStyle/>
    <a:p>
      <a:r>
        <a:rPr lang="en-US" dirty="0" smtClean="0"/>
        <a:t>This is text in a text box</a:t>
      </a:r>
      <a:endParaRPr lang="en-US" dirty="0"/>
    </a:p>
  </p:txBody>
</p:sp>

Group shape (some contents elided for size):

<p:grpSp>
  <p:nvGrpSpPr>
    <p:cNvPr id="4" name="Group 3"/>
    <p:cNvGrpSpPr/>
    <p:nvPr/>
  </p:nvGrpSpPr>
  <p:grpSpPr>
    <a:xfrm>
      <a:off x="2438400" y="2971800"/>
      <a:ext cx="4267200" cy="914400"/>
      <a:chOff x="2438400" y="2971800"/>
      <a:chExt cx="4267200" cy="914400"/>
    </a:xfrm>
  </p:grpSpPr>
  <p:sp>
    <p:nvSpPr>
      <p:cNvPr id="2" name="Rectangle 1"/>
      <p:cNvSpPr/>
      <p:nvPr/>
    </p:nvSpPr>
    <!-- some contents elided -->
  </p:sp>
  <p:sp>
    <p:nvSpPr>
      <p:cNvPr id="3" name="Oval 2"/>
      <p:cNvSpPr/>
      <p:nvPr/>
    </p:nvSpPr>
    <!-- some contents elided -->
  </p:sp>
</p:grpSp>

Graphical object (e.g. table, chart) in a graphic frame:

<p:graphicFrame>
  <p:nvGraphicFramePr>
    <p:cNvPr id="2" name="Table 1"/>
    <p:cNvGraphicFramePr>
      <a:graphicFrameLocks noGrp="1"/>
    </p:cNvGraphicFramePr>
    <p:nvPr/>
  </p:nvGraphicFramePr>
  <p:xfrm>
    <a:off x="1524000" y="1397000"/>
    <a:ext cx="6096000" cy="741680"/>
  </p:xfrm>
  <a:graphic>
    <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
      <!-- graphical object XML or ref goes here -->
    </a:graphicData>
  </a:graphic>
</p:graphicFrame>

Connector shape:

<p:cxnSp>
  <p:nvCxnSpPr>
    <p:cNvPr id="6" name="Straight Connector 5"/>
    <p:cNvCxnSpPr/>
    <p:nvPr/>
  </p:nvCxnSpPr>
  <p:spPr>
    <a:xfrm>
      <a:off x="3131840" y="3068960"/>
      <a:ext cx="2736304" cy="0"/>
    </a:xfrm>
    <a:prstGeom prst="line">
      <a:avLst/>
    </a:prstGeom>
  </p:spPr>
  <p:style>
    <a:lnRef idx="2">
      <a:schemeClr val="accent1"/>
    </a:lnRef>
    <a:fillRef idx="0">
      <a:schemeClr val="accent1"/>
    </a:fillRef>
    <a:effectRef idx="1">
      <a:schemeClr val="accent1"/>
    </a:effectRef>
    <a:fontRef idx="minor">
      <a:schemeClr val="tx1"/>
    </a:fontRef>
  </p:style>
</p:cxnSp>

Picture shape:

<p:pic>
  <p:nvPicPr>
    <p:cNvPr id="6" name="Picture 5" descr="python-logo.gif"/>
    <p:cNvPicPr>
      <a:picLocks noChangeAspect="1"/>
    </p:cNvPicPr>
    <p:nvPr/>
  </p:nvPicPr>
  <p:blipFill>
    <a:blip r:embed="rId2"/>
    <a:stretch>
      <a:fillRect/>
    </a:stretch>
  </p:blipFill>
  <p:spPr>
    <a:xfrm>
      <a:off x="5580112" y="1988840"/>
      <a:ext cx="2679700" cy="901700"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
      <a:avLst/>
    </a:prstGeom>
    <a:ln>
      <a:solidFill>
        <a:schemeClr val="bg1">
          <a:lumMod val="85000"/>
        </a:schemeClr>
      </a:solidFill>
    </a:ln>
  </p:spPr>
</p:pic>

Resources

Schema excerpt

<xsd:complexType name="CT_Shape">
  <xsd:sequence>
    <xsd:element name="nvSpPr" type="CT_ShapeNonVisual"/>
    <xsd:element name="spPr"   type="a:CT_ShapeProperties"/>
    <xsd:element name="style"  type="a:CT_ShapeStyle"        minOccurs="0"/>
    <xsd:element name="txBody" type="a:CT_TextBody"          minOccurs="0"/>
    <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="useBgFill" type="xsd:boolean" default="false"/>
</xsd:complexType>

<xsd:complexType name="CT_ShapeNonVisual">
  <xsd:sequence>
    <xsd:element name="cNvPr"   type="a:CT_NonVisualDrawingProps"/>
    <xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps"/>
    <xsd:element name="nvPr"    type="CT_ApplicationNonVisualDrawingProps"/>
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="CT_ShapeProperties">
  <xsd:sequence>
    <xsd:element name="xfrm"                type="CT_Transform2D"            minOccurs="0"/>
    <xsd:group   ref ="EG_Geometry"                                          minOccurs="0"/>
    <xsd:group   ref ="EG_FillProperties"                                    minOccurs="0"/>
    <xsd:element name="ln"                  type="CT_LineProperties"         minOccurs="0"/>
    <xsd:group   ref ="EG_EffectProperties"                                  minOccurs="0"/>
    <xsd:element name="scene3d"             type="CT_Scene3D"                minOccurs="0"/>
    <xsd:element name="sp3d"                type="CT_Shape3D"                minOccurs="0"/>
    <xsd:element name="extLst"              type="CT_OfficeArtExtensionList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>

<xsd:complexType name="CT_ShapeStyle">
  <xsd:sequence>
    <xsd:element name="lnRef"     type="CT_StyleMatrixReference"/>
    <xsd:element name="fillRef"   type="CT_StyleMatrixReference"/>
    <xsd:element name="effectRef" type="CT_StyleMatrixReference"/>
    <xsd:element name="fontRef"   type="CT_FontReference"/>
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="CT_TextBody">
  <xsd:sequence>
    <xsd:element name="bodyPr"   type="CT_TextBodyProperties"/>
    <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
    <xsd:element name="p"        type="CT_TextParagraph" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="CT_ExtensionListModify">
  <xsd:sequence>
    <xsd:group ref="EG_ExtensionList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="mod" type="xsd:boolean" default="false"/>
</xsd:complexType>

<!-- Supporting elements -->

<xsd:complexType name="CT_NonVisualDrawingProps">
  <xsd:sequence>
    <xsd:element name="hlinkClick" type="CT_Hyperlink"              minOccurs="0"/>
    <xsd:element name="hlinkHover" type="CT_Hyperlink"              minOccurs="0"/>
    <xsd:element name="extLst"     type="CT_OfficeArtExtensionList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="id"     type="ST_DrawingElementId" use="required"/>
  <xsd:attribute name="name"   type="xsd:string"          use="required"/>
  <xsd:attribute name="descr"  type="xsd:string"          default=""/>
  <xsd:attribute name="hidden" type="xsd:boolean"         default="false"/>
  <xsd:attribute name="title"  type="xsd:string"          default=""/>
</xsd:complexType>

<xsd:complexType name="CT_NonVisualDrawingShapeProps">
  <xsd:sequence>
    <xsd:element name="spLocks" type="CT_ShapeLocking"           minOccurs="0"/>
    <xsd:element name="extLst"  type="CT_OfficeArtExtensionList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="txBox" type="xsd:boolean" default="false"/>
</xsd:complexType>

<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
  <xsd:sequence>
    <xsd:element name="ph"          type="CT_Placeholder"      minOccurs="0"/>
    <xsd:group   ref ="a:EG_Media"                             minOccurs="0"/>
    <xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
    <xsd:element name="extLst"      type="CT_ExtensionList"    minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="isPhoto"   type="xsd:boolean" default="false"/>
  <xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>

<xsd:complexType name="CT_Transform2D">
  <xsd:sequence>
    <xsd:element name="off" type="CT_Point2D"        minOccurs="0"/>
    <xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="rot"   type="ST_Angle"    default="0"/>
  <xsd:attribute name="flipH" type="xsd:boolean" default="false"/>
  <xsd:attribute name="flipV" type="xsd:boolean" default="false"/>
</xsd:complexType>

<xsd:group name="EG_Geometry">
  <xsd:choice>
    <xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
    <xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
  </xsd:choice>
</xsd:group>

<xsd:complexType name="CT_CustomGeometry2D">
  <xsd:sequence>
    <xsd:element name="avLst"   type="CT_GeomGuideList"      minOccurs="0"/>
    <xsd:element name="gdLst"   type="CT_GeomGuideList"      minOccurs="0"/>
    <xsd:element name="ahLst"   type="CT_AdjustHandleList"   minOccurs="0"/>
    <xsd:element name="cxnLst"  type="CT_ConnectionSiteList" minOccurs="0"/>
    <xsd:element name="rect"    type="CT_GeomRect"           minOccurs="0"/>
    <xsd:element name="pathLst" type="CT_Path2DList"/>
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="CT_PresetGeometry2D">
  <xsd:sequence>
    <xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="prst" type="ST_ShapeType" use="required"/>
</xsd:complexType>

<xsd:group name="EG_FillProperties">
  <xsd:choice>
    <xsd:element name="noFill"    type="CT_NoFillProperties"/>
    <xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
    <xsd:element name="gradFill"  type="CT_GradientFillProperties"/>
    <xsd:element name="blipFill"  type="CT_BlipFillProperties"/>
    <xsd:element name="pattFill"  type="CT_PatternFillProperties"/>
    <xsd:element name="grpFill"   type="CT_GroupFillProperties"/>
  </xsd:choice>
</xsd:group>

<xsd:complexType name="CT_LineProperties">
  <xsd:sequence>
    <xsd:group   ref="EG_LineFillProperties"                     minOccurs="0"/>
    <xsd:group   ref="EG_LineDashProperties"                     minOccurs="0"/>
    <xsd:group   ref="EG_LineJoinProperties"                     minOccurs="0"/>
    <xsd:element name="headEnd" type="CT_LineEndProperties"      minOccurs="0"/>
    <xsd:element name="tailEnd" type="CT_LineEndProperties"      minOccurs="0"/>
    <xsd:element name="extLst"  type="CT_OfficeArtExtensionList" minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute name="w"    type="ST_LineWidth"/>
  <xsd:attribute name="cap"  type="ST_LineCap"/>
  <xsd:attribute name="cmpd" type="ST_CompoundLine"/>
  <xsd:attribute name="algn" type="ST_PenAlignment"/>
</xsd:complexType>

<xsd:complexType name="CT_Point2D">
  <xsd:attribute name="x" type="ST_Coordinate" use="required"/>
  <xsd:attribute name="y" type="ST_Coordinate" use="required"/>
</xsd:complexType>

<xsd:complexType name="CT_PositiveSize2D">
  <xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/>
  <xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/>
</xsd:complexType>

<xsd:group name="EG_EffectProperties">
  <xsd:choice>
    <xsd:element name="effectLst" type="CT_EffectList"/>
    <xsd:element name="effectDag" type="CT_EffectContainer"/>
  </xsd:choice>
</xsd:group>

<xsd:group name="EG_Media">
  <xsd:choice>
    <xsd:element name="audioCd"       type="CT_AudioCD"/>
    <xsd:element name="wavAudioFile"  type="CT_EmbeddedWAVAudioFile"/>
    <xsd:element name="audioFile"     type="CT_AudioFile"/>
    <xsd:element name="videoFile"     type="CT_VideoFile"/>
    <xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
  </xsd:choice>
</xsd:group>

<xsd:simpleType name="ST_DrawingElementId">
  <xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>

<xsd:simpleType name="ST_Angle">
  <xsd:restriction base="xsd:int"/>
</xsd:simpleType>