A shape is the elemental object that composes a drawing. All graphical figures on a drawing are shapes. Each shape has a list of properties, which is stored in an array. A shape container contains the following records:
Record Type | Condition | Comments |
msofbtSpgr | Shape is a group shape. | Group-shape-specific information. |
msofbtSp | Always. | A shape atom record. |
msofbtOPT | Always. | The properties of a shape. |
msofbtAnchor or msofbtChildAnchor or msofbtClientAnchor | Always, except for the background shape. | The anchor or location of the shape. If the shape is saved to a clipboard, a msofbtAnchor record is used. If the shape is a child of a group shape, a msofbtChildAnchor is used. Otherwise, for top-level shapes, a host anchor record is present. |
msofbtClientData | Always. | A client data record, the content of which is up to the host. |
msofbtClientTextbox or msofbtTextbox | Shape has attached text. | If the shape has text, a text record is written. For clipboard streams, a msofbtTextbox record is used. Otherwise, a msofbtClientTextbox record is used, the content of which is up to the host. |
msofbtOleObject | Shape is an OLE object. | Used only in the clipboard format. |
msofbtDeletedPspl | Shape is deleted. | Link to previous spot of object. |
This record is present only in group shapes (not shapes in groups, shapes that are groups). The group shape record defines the coordinate system of the shape, which the anchors of the child shape are expressed in. All other information is stored in the shape records that follow.
typedef struct _FSPGR { RECT rcgBounds; } FSPGR;
The instance field of the record header contains the shape type; the record itself contains the shape ID and a group of persistent flags:
typedef struct _FSP { MSOSPID spid; // The shape id ULONG grfPersistent; } FSP;
The flags for the shape are:
typedef struct { ULONG fGroup : 1; // This shape is a group shape ULONG fChild : 1; // Not a top-level shape ULONG fPatriarch : 1; // This is the topmost group shape. // Exactly one of these per drawing. ULONG fDeleted : 1; // The shape has been deleted ULONG fOleShape : 1; // The shape is an OLE object ULONG fHaveMaster : 1; // Shape has a hspMaster property ULONG fFlipH : 1; // Shape is flipped horizontally ULONG fFlipV : 1; // Shape is flipped vertically ULONG fConnector : 1; // Connector type of shape ULONG fHaveAnchor : 1; // Shape has an anchor of some kind ULONG fBackground : 1; // Background shape ULONG fHaveSpt : 1; // Shape has a shape type property ULONG reserved : 20; // Not yet used }
A shape's properties are stored in a sorted array of property id-value pairs. Only the properties that differ from the per-shape-type defaults or the per-property defaults are saved. (Note that the per-property defaults are unrelated to the default property table stored in the drawing group container).
The format of a property table record is in another section of this document.
An anchor record is used for top-level shapes when the shape streamed to the clipboard. The content of the record is simply a RECT with a coordinate system of 100,000 units per inch and origin in the top-left of the drawing.
A child anchor record is used for all shapes that belong to a group. The content of the record is simply a RECT in the coordinate system of the parent group shape.
A textbox record is used when a shape with attached text is written to a clipboard stream. It just contains an RTF string.
An OLE object record is present when a shape that is an OLE object is saved to the clipboard. It contains the OLE object's storage, serialized using OleConvertIStorageToOLESTREAM.
Top-level deleted shapes save a pointer back into their former position in the shape tree, so that if they are undeleted via undo they can be easily put back into the main shape tree.
The record consists of a single FPSPL:
// FPSPL - File PSPL typedef struct _FPSPL { union { ULONG lAll; struct { ULONG spid : 30; // The SPID of the shape PSPL points at. ULONG fFirst : 1; // Is this a pointer to the m_splFirst? ULONG fLast : 1; // Is this a pointer to the m_splLast? }; }; } FPSPL;