# Microsoft Office 97 Drawing File Format

## Introduction

This document describes the file format of the Office Drawing Layer (Escher). With this document and knowledge of the host application's file format, the reader should be able to construct and interpret an Escher file stream.

## Object Container Hierarchy

Escher has an object containership hierarchy similar to other drawing programs. At the root of the hierarchy is a drawing group object. There is one drawing group per client document. Drawing groups contain drawings. Drawings in turn contain shapes that are the objects that actually mark a page. Next to the drawings in a drawing group is a collection that contains the images and pictures used by the drawings. Escher keeps pictures in a separate collection to be able to incrementally load and save them.

Figure 1 -- Containership Hierarchy

A few other points are worth noting

- Associated with each shape is a piece of client data that keeps the shape's anchor, text and OLE data, as well as host specific properties. The format of this structure is host-defined.
- Shapes store their properties in a separate structure called a property table. The property table is basically a sorted list of property id-value pairs.
- Each drawing group has a shape property table that stores the defaults for new shapes.
- Each drawing has a collection of rules that govern the shapes in the drawing.
- This object hierarchy does not exactly correspond to the record hierarchy in the file format. In the file format, drawings are not saved inside drawing groups, but in separate top-level containers. In this scheme, hosts can save drawing group information with per-document information, and save drawing information with per-sheet, per-slide, or per-page information.

### Use by the Host Application

Escher is part of the Office 97 DLL. It replaces the existing drawing layers of PowerPoint, Word, and Excel. Clients access the Escher services through custom APIs and COM interfaces defined in msodr.h. When serializing Escher data into a file, the client application provides an OLE IStream interface to Escher. This document describes the records Escher writes to this interface. However, it doesn't describe how the actual bytes are saved to disk. The client controls this format, since Escher writes to a client provided interface. Excel, for example, places the bytes of the Escher stream into BIFF records.

### Credits

Tagged chunks of data are a common file-format element. Escher's particular record structure follows the record structure used in PowerPoint 97, designed by Tony Lin. Parts of this document were copied from the PowerPoint file format SDK. Matthew Morgan did most of the work on the Escher file format. Rick Hawes did the shape work. John Bowler did the blip work.

## Records

The Escher file stream is a series of records that share a common header structure. Records can be categorized in to two groups.

Atoms | Records that contain information about an Escher object and are kept inside containers.
Containers | Records that keep atoms and other containers in a logical and organized way.

Each record, whether it's an atom or a container, has a common header. Container records are just the common header, while the atom records are the common header followed by some record specific data. Escher uses the structure of container records containing atom records and other container records throughout its stream.

### Common Header

The common record header is an 8-byte structure defined in msodr.h as follows:

    	typedef struct MSOFBH
       {
       struct
           {
           ULONG ver : 4;
           ULONG inst: 12;
           ULONG fbt : 16;
           };
       ULONG
       cbLength;
       } MSOFBH;

The fields are:

Record Type | Indicates the signature or type of the record. Each record has a symbolic and a numberic signature in msodr.h. Escher uses values from 0xF000 to 0xFFFF. Clients may define their own records in other ranges. A description of each of the different types can be found in the following sections.
Record Instance | (inst) Differentiates atoms. Depending on the instance a record's contents it can have different meanings. For example a list container can store a list of slides or a list of fonts, and its instance would vary accordingly. The instance of a record is useful for differentiating atoms when there is more than one atom of the same type in a particular container
Record Version | (ver) Indicates the version if the record is an atom. If the record is a container, this field has a value of 0xFFFF.
Record Length | (cbLength) Stores the length of the record in bytes. If the record is an atom, it refers to the length of the atom excluding the header. If the record is a container, it refers to the sum of the length of the atoms inside it, plus the length of the record headers.

### Notes for Implementers

The common header specifies the length of each record. Consequently, it is possible to parse the Escher record stream without knowledge of the actual contents of each record. The Escher team intends to take advantage of this fact in future versions. As new features are added, Escher will define new record types. Readers of the Escher file format should skip over record types unknown to the reader. In addition, readers should not expect a record to come in a certain order in a container. They can, however, expect that the containership hierarchy will not change. For example, readers do not need to handle the case of a shape record containing a drawing record.

When Escher writes to a client file, it stores client-specific records in it stream to preserve the client features and behaviors. On the other hand, when Escher writes to a clipboard stream, it uses a client-independent form of the file format to allow interchange between applications.

Escher saves records in Intel byte-order even on the Macintosh. The Macintosh version of Escher byte-swaps the records as they are loaded and as they are saved. Records are tightly packed, without alignment. The LONG type is 32 bits in length.

## Pointers

The general problem of saving pointers to objects in the file format is solved in ordinary fashion by giving objects unique identifiers, which are saved in the file format in place of the pointer values. At load time, these IDs are converted back into pointers.

The most common instances of this are pointers to shapes, which are saved as shape IDs, or SPIDs. SPIDs are unique per drawing group, and are parceled out by the drawing group to individual drawings in blocks of 1024. The drawing group keeps a table recording which drawing owns which block of SPIDs, so that, given a SPID, it is easy to determine which drawing the shape is in. That table makes up the bulk of the msofbtDgg record, and is the only place where pointers to drawings are saved (as DGIDs).

Record Name |  |  | Word | Excel | PowerPoint | FBT value | Version | Instance | Contents
msofbtDggContainer |  |  | X | X | X | F000 |  |  | per-document data
| msofbtDgg |  | X | X | X | F006 | 0 |  | an FDGG and several FIDCLs
| msofbtCLSID |  | C | C | C | F016 | 0 |  | the CLSID of the application that put the data on the clipboard
| msofbtOPT |  | X | X | X | F00B | 3 | count of properties | the document-wide default shape properties
| msofbtColorMRU |  | X | X | X | F11A | 0 | count of colors | the colors in the MRU swatch
| msofbtSplitMenuColors |  | X | X | X | F11E | 0 | count of colors | the colors in the top-level split menus
| msofbtBstoreContainer |  | X | X | X | F001 |  | count of BLIPs | all images in the document (JPEGs, metafiles, etc.)
|  | msofbtBSE | X | X | X | F007 | 2 | BLIP type | an FBSE (one per BLIP)
|  | msofbtBlip*** | X | X | X | F018 - F117 |  |  | range of fbts reserved for various kinds of BLIPs
msofbtDgContainer |  |  | X | X | X | F002 |  |  | per-sheet/page/slide data
| msofbtDg |  | X | X | X | F008 | 0 | drawing ID | an FDG
| msofbtRegroupItems |  | X | X | X | F118 | 0 | count of regroup entries | several FRITs
| msofbtColorScheme |  |  | C | C | F120 | 0 | count of colors | the colors of the source host's color scheme
| msofbtSpgrContainer |  | X | X | X | F003 |  |  | several SpContainers, the first of which is the group shape itself
| msofbtSpContainer |  | X | X | X | F004 |  |  | a shape
|  | msofbtSpgr | X | X | X | F009 | 1 |  | an FSPGR; only present if the shape is a group shape
|  | msofbtSp | X | X | X | F00A | 2 | shape type | an FSP
|  | msofbtOPT | X | X | X | F00B | 3 | count of properties | a shape property table
|  | msofbtTextbox | C | C | C | F00C | 0 |  | RTF text
|  | msofbtClientTextbox | X | X | X | F00D |  | host-defined | the text in the textbox, in a host-defined format
|  | msofbtAnchor | C | C | C | F00E | 0 |  | a RECT, in 100000ths of an inch
|  | msofbtChildAnchor | X | X | X | F00F | 0 |  | a RECT, in units relative to the parent group
|  | msofbtClientAnchor | X | X | X | F010 |  | host-defined | the location of the shape, in a host-defined format
|  | msofbtClientData | X | X | X | F011 |  | host-defined | host-specific data
|  | msofbtOleObject | C | C | C | F11F | 0 |  | a serialized IStorage for an OLE object
|  | msofbtDeletedPspl | X |  |  | F11D | 0 |  | an FPSPL; only present in top-level deleted shapes
| msofbtSolverContainer |  | X | X | X | F005 |  | count of rules | the rules governing shapes
|  | msofbtConnectorRule |  | X | X | F012 | 1 |  | an FConnectorRule
|  | msofbtAlignRule | X | X | X | F013 | 0 |  | an FAlignRule
|  | msofbtArcRule | X | X | X | F014 | 0 |  | an FARCRU
|  | msofbtClientRule |  |  |  | F015 |  | host-defined | host-defined
|  | msofbtCalloutRule | X | X | X | F017 | 0 |  | an FCORU
msofbtSelection |  |  |  | X |  | F119 | 0 |  | an FDGSL followed by the SPIDs of the shapes in the selection

## Drawing Group Container msofbtDggContainer

### Drawing Group Record msofbtDgg

The drawing group record is a variable length record consisting of a fixed part followed by an array. The fixed part is defined as follows.

    // FDGG - File DGG
    typedef struct _FDGG
       {
       MSOSPID spidMax; // The current maximum shape ID
       ULONG cidcl;     // The number of ID clusters (FIDCLs)
       ULONG cspSaved;  // The total number of shapes saved
                        // (including deleted shapes, if undo
                        // information was saved)
       ULONG cdgSaved;  // The total number of drawings saved
       } FDGG;

The fixed part is followed by an array of ID clusters. The ID clusters are used internally for the translation of shape ids (SPIDs) to shape handles (MSOHSPs).

    // File ID Cluster - used to save IDCLs
    typedef struct _FIDCL
       {
       MSODGID dgid;    // DG owning the SPIDs in this cluster
       ULONG cspidCur;  // number of SPIDs used so far
       } FIDCL;

### Class ID Record msofbtCLSID

The class ID record is only present in the clipboard format. It just contains an OLE CLSID record from the source application, and is used by the destination application to check where the clipboard data originated.

### Default Property Table Record msofbtOPT

This describes the default properties of newly created shapes. Only the properties that differ from the per-property defaults are saved. The format of the record is the same as that of the property table in a shape; a discussion of that format is in the Shape Properties section

### Color MRU Record msofbtColorMRU

The Color MRU record contains the colors in the most-recently-used-colors swatch that appears at the bottom of color dropdowns. The instance field contains the number of colors; the data of the record contains the colors in order from left to right. < > < >

### Split Menu Colors Record msofbtSplitMenuColors

The single MRU colors of the top-level Fill Color, Line Color, Shadow Color, and 3D Color split menus are saved to a SplitMenuColors record in that order, with the number of colors (currently always four) in the instance field.

### BStore Container msofbtBstoreContainer

The images and pictures in a drawing can be dominate the size of a drawing. Consequently, Escher handles these objects in a special way. As an abstraction, Escher names these objects BLIPs for Big Large Image or Picture. Currently, there are five types of blips supported in Escher: Windows Metafiles, Enhanced Metafiles, JPEG Interchange Format, Portable Network Graphics (PNG) and Macintosh PICT. Other types may be defined in future versions. Escher stores all the BLIPs in a document in a separate container called the BStore. It reference counts the BLIPs, so that if a picture is inserted multiple times in a document it is only stored once in the BStore but is multiply referenced by different shapes. The host may choose to store the blip data in a separate delay stream. If a delay stream is used, Escher can incrementally load the blips as they are displayed, not when the document is loaded. (As of Office 97, Word and PowerPoint use a delay stream, and Excel does not.) The BStore container is just an array of Blip Store Entry (BSE) records. Each shape stores indices into the array for the BLIPs they use. BLIPs are used not only for inserted pictures, but also for the textured and pictures fills of the shape.

#### BLIP Store Entry Record msofbtBSE

Each BLIP in the BStore is serialized to a File BLIP Store Entry (FBSE) record. The instance field encodes the type of the blip. A fixed size header contains the rest of the common information about the BLIP. If the cbName field in the FBSE is nonzero, a null-terminated Unicode string is written immediately after the FBSE in the file.

    // FBSE - File Blip Store Entry
    typedef struct _FBSE
       {
       BYTE      btWin32;    // Required type on Win32
       BYTE      btMacOS;    // Required type on Mac
       BYTE      rgbUid[16]; // Identifier of blip
       WORD      tag;        // currently unused
       ULONG     size;       // Blip size in stream
       ULONG     cRef;       // Reference count on the blip
       MSOFO     foDelay;    // File offset in the delay stream
       BYTE      usage;      // How this blip is used (MSOBLIPUSAGE)
       BYTE      cbName;     // length of the blip name
       BYTE      unused2;    // for the future
       BYTE      unused3;    // for the future
       } FBSE;

    typedef enum
       {
       msoblipUsageDefault,  // All non-texture fill blips get this.
       msoblipUsageTexture,
       msoblipUsageMax = 255 // Since this is stored in a byte
       } MSOBLIPUSAGE;

    typedef enum
       {                          // GEL provided types...
       msoblipERROR = 0,          // An error occurred during loading
       msoblipUNKNOWN,            // An unknown blip type
       msoblipEMF,                // Windows Enhanced Metafile
       msoblipWMF,                // Windows Metafile
       msoblipPICT,               // Macintosh PICT
       msoblipJPEG,               // JFIF
       msoblipPNG,                // PNG
       msoblipDIB,                // Windows DIB
       msoblipFirstClient = 32,   // First client defined blip type
       msoblipLastClient  = 255   // Last client defined blip type
       } MSOBLIPTYPE;

    typedef enum
       {
       msobiUNKNOWN = 0,
       msobiWMF  = 0x216,      // Metafile header then compressed WMF
       msobiEMF  = 0x3D4,      // Metafile header then compressed EMF
       msobiPICT = 0x542,      // Metafile header then compressed PICT
       msobiPNG  = 0x6E0,      // One byte tag then PNG data
       msobiJFIF = 0x46A,      // One byte tag then JFIF data
       msobiJPEG = msobiJFIF,
       msobiDIB  = 0x7A8,      // One byte tag then DIB data
       msobiClient=0x800,      // Clients should set this bit
       }
    MSOBI;                     // Blip signature as encoded in the MSOFBH.inst

The btWin32 and btMacOS fields store the MSOBLIPTYPE for the respective operating systems. When the OS blip type doesn't match the blip type of stored, Escher will attempt to convert the blip. For example, a PICT will be stored as a msoblipPICT with a btWin32 field of msoblipWMF and a btMacOS field of msoblipPICT. When the PICT blip is loaded on Windows, the stored field will not match the OS field, so PICTtoWMF filter will be called to create a msoblipWMF BLIP. A few additional facts are worth noting. Clients can define their own BLIP types. When loading client defined blip types Escher calls the clients to load the blips. Each BSE contains a 16-byte checksum that is used to quickly compare a BLIP with other BLIPs in the store. Any algorithm could be used for this checksum. Escher uses the RSA Data Security, Inc. MD4 Message-Digest Algorithm for the checksums of its BLIP types. Finally, the cRef field can be 0, indicating an empty slot in the BStore. If a delay stream is not used, then the BLIP data follows the BSE header in a separate record. The FBT of the BLIP record is the MSOBLIPTYPE plus msofbtBlipFirst (0xF018). (If a delay stream is being used, the BLIP's record header and data are both written there instead.)

##### Metafile/PICT Blips

Those blips have one of the following signatures: msobiEMF, msobiWMF, or msobiPICT. They are normally stored in a compressed format using the LZ compression algorithm in the format used by GNU Zip deflate/inflate with a 32k window. The format is zlib format . The only metafile compression version number currently defined identifies this format and is analogous to the PNG compression type value in the PNG file format. The filter values (MSOBLIPFILTER) define pre-filtering of metafile data to give better compression. Currently no pre-filtering is done (it is likely that filtering on a per-record basis will give substantially better compression in the future). However, if there is an exception due to out-of-memory or out-of-disk space when saving those blips, the compression operation is skipped and the blips are then saved in a non-compressed format- in this case the compressed bits are simply the original metafile data.. When the blips are loaded back in memory, a check is performed based on a "compression status" flag (MSOBLIPCOMPRESSION) that follows the blip header encoded as follows:

    typedef enum
       {
       msocompressionDeflate = 0,
       msocompressionNone = 254,    // Used only if compression fails
       msocompressionTest = 255,    // For testing only
       }
    MSOBLIPCOMPRESSION;

    typedef enum
       {
       msofilterAdaptive = 0,       // PNG type - not used/supported for metafile
       msofilterNone = 254,
       msofilterTest = 255,         // For testing only
       }
    MSOBLIPFILTER;

    /* The secondary, or data, UID - should always be set. */
    BYTE  m_rgbUid[16];
    /* The primary UID - this defaults to 0, in which case the primary ID is
       that of the internal data. NOTE!: The primary UID is only saved to disk
       if (blip_instance ^ blip_signature == 1). Blip_instance is MSOFBH.inst and
       blip_signature is one of the values defined in MSOBI */
    BYTE  m_rgbUidPrimary[16]; /   / optional based on the above check

    /* Metafile Blip overhead = 34 bytes. m_cb gives the number of
       bytes required to store an uncompressed version of the file, m_cbSave
       is the compressed size.  m_mfBounds gives the boundary of all the
       drawing calls within the metafile (this may just be the bounding box
       or it may allow some whitespace, for a WMF this comes from the
       SetWindowOrg and SetWindowExt records of the metafile). */
    int           m_cb;           // Cache of the metafile size
    RECT          m_rcBounds;     // Boundary of metafile drawing commands
    POINT         m_ptSize;       // Size of metafile in EMUs
    int           m_cbSave;       // Cache of saved size (size of m_pvBits)
    BYTE          m_fCompression; // MSOBLIPCOMPRESSION
    BYTE          m_fFilter;      // always msofilterNone
    void         *m_pvBits;       // Compressed bits of metafile.

##### Bitmap Blips

Those blips have one of the following signatures: msobiJPEG, msobiPNG, or msobiDIB. They have the same UID header as described in the Metafile Blip case. The data after the header is just a single BYTE "tag" value and is followed by the compressed data of the bitmap in the relevant format (JFIF or PNG, bytes as would be stored in a file). For the msobiDIB format, the data is in the standard DIB format as a BITMAPINFO ER, BITMAPCORE ER or BITMAPV4 ER followed by the color map (DIB_RGB_COLORS) and the bits. This data is not compressed (the format is used for very small DIB bitmaps only). To determine where the bits are located, refer to the following header:

    /* The secondary, or data, UID - should always be set. */
    BYTE  m_rgbUid[16];
    /* The primary UID - this defaults to 0, in which case the primary ID is
       that of the internal data. NOTE!: The primary UID is only saved to disk
       if (blip_instance ^ blip_signature == 1). Blip_instance is MSOFBH.finst and
       blip_signature is one of the values defined in MSOBI*/
    BYTE  m_rgbUidPrimary[16];    // optional based on the above check
    BYTE  m_bTag;
    void  *m_pvBits;              // raster bits of the blip.

< > < >

## Drawing Container msofbtDgContainer

The drawing container contains all per-slide/sheet types of information, including the shapes themselves. With a few exceptions, shapes are stored hierarchically according to how they've been grouped (through use of the Draw/Group command). For normal shapes, there is a special parent group shape called the patriarch that contains all of the top-level shapes (which in turn may contain other shapes). The patriarch is always the first msofbtSpgrContainer in the drawing container. A few kinds of shapes are stored separately from the patriarch. The background shape, if there is one, is saved in its own msofbtSpContainer after the patriarch and its children. Additionally, if undo information is being saved and there are deleted shapes that could be brought back via Undo, the deleted shapes are saved. Note that there is no patriarch for the deleted shapes, so the top-level deleted shapes are saved separately into the drawing container. (Deleted groups still contain their children, though.)

Record Type | Condition | Comments
msofbtDg | Always. | Basic drawing information.
msofbtRegroupItems | Shapes have been ungrouped. | Mappings to reconstitute groups.
msofbtSpgrContainer | Always. | Patriarch shape, with all non-background non-deleted shapes inside it.
msofbtSpContainer with fBackground bit set in the FSP (see below). | Application uses a background shape (currently Word and PowerPoint only). | Special shape used as background of the document, e.g. the background texture of a Web page.
Other msofbtSpContainers and msofbtSpgrContainers | Undo is being saved, and there are deleted shapes in the drawing. | Shapes that have been deleted but that could be brought back via Undo.
msofbtSolverContainer | There are rules in the drawing. | Rules governing shapes in the drawing.
msofbtColorScheme | The application uses a color scheme. | Only present in the clipboard format.

< > < >

### Drawing Record msofbtDg

The drawing record is very simple, with just a count and MSOSPID seed. The attentive reader may expect to find the size of the drawing recorded here, but that information is stored elsewhere by the host application.

    // FDG - File DG
    typedef struct _FDG
       {
       ULONG     csp;          // The number of shapes in this drawing
       MSOSPID   spidCur;      // The last MSOSPID given to an SP in this DG
       } FDG;

< > < >

### Regroup msofbtRegroupItems

Each shape in a drawing has a regroup ID (separate from the shape ID), so that the regroup command can find shapes that were once grouped. In order to handle nested cases (e.g. ungroup, ungroup, ungroup, regroup, regroup, regroup), there is a table logging changes to regroup IDs. Each entry has an old ID and a new ID and records the change of all instances of the old ID to the new ID. The instance of an msofbtRegroupItems record contains the number of entries, and the record itself is just that many FRITs (File Regroup Items).

typedef struct _FRIT // File Regroup item

       {
       FRID fridNew;
       FRID fridOld;
       } FRIT;

< > < >

### Group Container msofbtSpgrContainer

A group is a collection of other shapes. The contained shapes are placed in the coordinate system of the group. The group container contains a variable number of shapes (msofbtSpContainer) and other groups (msofbtSpgrContainer, for nested groups). The group itself is a shape, and always appears as the first msofbtSpContainer in the group container. < > < >

### Shape Container msofbtSpContainer

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.

#### Group Shape Record msofbtSpgr

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;

#### Shape Record msofbtSp

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
    }

#### Property Table Record msofbtOPT

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.

#### Anchor Record msofbtAnchor

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.

#### Child Anchor Record msofbtChildAnchor

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.

#### Textbox Record msofbtTextbox

A textbox record is used when a shape with attached text is written to a clipboard stream. It just contains an RTF string.

#### OLE Object Record msofbtOleObject

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.

#### Deleted PSPL Record msofbtDeletedPspl

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;

< > < >

### Solver Container msofbtSolverContainer

Rules give special behaviors to shapes. Rules can govern a single shape, like in the case of a callout shape, or multiple shapes, as in the case of connectors. Each drawing can have a list of rules associated with it.

#### Connector Rule Record msofbtConnectorRule

Governs a connector shape.

    typedef struct _FConnectorRule
       {
       ULONG ruid;       // rule ID
       MSOSPID spidA;    // SPID of shape A
       MSOSPID spidB;    // SPID of shape B
       MSOSPID spidC;    // SPID of connector shape
       ULONG cptiA;      // Connection site Index of shape A
       ULONG cptiB;      // Connection site Index of shape B
       } FConnectorRule;

#### Align Rule Record msofbtAlignRule

Aligns shapes. The FAlignRule record is followed by the SPIDs of the proxy shapes.

    // FAlignRule
    typedef struct _FAlignRule
       {
       ULONG ruid;       // rule ID
       ULONG align;      // alignment – see below
       ULONG cProxies;   // number of shapes governed by rule
       } FAlignRule;

    // ALIGN == Shape alignment (Horz and vert can be or'ed together)
    #define alignHorz      0x000F   // mask for horizontal component
    #define alignLeft      0x0001   // left edges
    #define alignCenter    0x0002   // horizontal center
    #define alignRight     0x0003   // right edges
    #define alignVert      0x00F0   // mask for vertical component
    #define alignTop       0x0010   // top edges
    #define alignMiddle    0x0020   // vertical center
    #define alignBottom    0x0030   // bottom edges
    #define alignRelative  0x0100   // Relative to the page

#### Arc Rule Record msofbtArcRule

One Arc rule per elliptical arc shape.

    // FARCRU -- Arc Rule
    typedef struct _FARCRU
       {
       ULONG      ruid; // rule ID
       MSOSPID    spid; // spid of arc shape
       } FARCRU;

#### Callout Rule Record msofbtCalloutRule

One callout rule per callout shape.

    // FCORU   -- Callout Rule
    typedef struct _FCORU
       {
       ULONG      ruid; // rule ID
       MSOSPID    spid; // spid of callout shape
       } FCORU;

< > < >

### Color Scheme msofbtColorScheme

Hosts may define their own color scheme and store colors in shape properties that are an index to that scheme plus an indicating flag (see Appendix B). Since hosts' color schemes are independent of each other, the color scheme is saved when rendering to the clipboard. If the clipboard data is pasted back into the same application, the color scheme block is ignored; otherwise, it is used to translate scheme colors in properties into RGB values. The data in the block is an array of RGB values, saved as LONGs in order of color scheme index. < > < >

## Selections msofbtSelection

Selections of shapes are saved as top-level file blocks; they are never placed in a container. (Note: As of Office 97, only Excel saves shape selections; Word and PowerPoint do not.) The selection record consists of an FDGSL followed by the SPIDs of the shapes in the selection.

    // FDGSL - File Drawing Selection
    typedef struct _FDGSL
       {
       ULONG         cpsp;       // number of shapes in the selection
       ULONG         dgslk;      // kind of selection (an MSODGSLK)
       MSOSPID       spidFocus;  // SPID of the focus shape
       } FDGSL;

    // DGSLK = DrawinG SeLection Kind.
    typedef enum
       {
       msodgslkNormal,          // Normal Selection Mode.
       msodgslkRotate,          // Rotate selection mode
       msodgslkReshape,         // Reshape Selection Mode.
       msodgslkUnused,
       msodgslkWrapPolygon,     // Display and edit of wrap polygons.
       msodgslkTextEdit         // Text Edit Mode.
       } MSODGSLK;

< > < >

## Shape Properties msofbtOPT

The first part of an OPT record is an array of FOPTEs, consisting of ID-value pairs tightly packed:

    typedef struct _FOPTE
       {
       struct
          {
          USHORT pid : 14;     // Property ID
          USHORT fBid : 1;     // value is a blip ID – only valid if fComplex is FALSE
          USHORT fComplex : 1; // complex property, value is length
          };
       ULONG   op;  // Value
       } FOPTE;

The FOPTE array is sorted by property ID. Some property values, such as Unicode strings, don't fit in 32 bits. For these properties, the fComplex bit is set in the FOPTE, and the length of the data is saved in the value slot. The data of the complex properties follows the FOPTE array in the file record (sorted by property ID). BLIPs are usually saved in the BLIP Store, so, in most cases, BLIP properties just store a BLIP ID (basically an index into an array in the BLIP Store). This is signaled by the fBid flag; note however that this flag is only valid if fComplex is FALSE. Boolean properties are grouped in bitfields by property set; note that the Boolean properties in each property set below are contiguous. They are saved under the property ID of the last Boolean property in the set, and are placed in the value field in reverse order starting with the last property in the low bit. Notes on types and units:

- MSOHSP properties are basically just pointers to shapes, and they are therefore saved as SPIDs.
- WCHAR* properties are Unicode strings; char* properties are ASCII strings.
- IMsoArray properties are arrays. They are always complex when non-NULL. The complex-data part is saved as three shorts (16 bits each) followed by the array data. The first short is the number of elements in the array; the second short is the number of elements allocated for the array in memory (always greater than or equal to the first short); and the third short is the size of each array element.
- Absolute distances are specified in English Metric Units (EMUs), occasionally referred to as A units; there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point.
- A coordinate space relative to the size of the shape is specified with the geoLeft, geoTop, geoRight, and geoBottom properties; coordinates in this space are said to be in G units.
- Many quantities are specified as fixed-point 16.16 numbers; that is, the quantity fits in a LONG, where the high word specifies the integer part and the low word specifies the fractional part. In this system, 1<<16 signifies 1, 1<<17 signifies 2, and 1<<15 signifies ½.

The property listings below contain only those properties which are saved in OPT records in the file. Properties which are never saved, or which appear elsewhere in the file format, have been omitted. < > < >

### Transform

Property | PID | Type | Default | Description
rotation | 4 | LONG | 0 | fixed point: 16.16 degrees

< > < >

### Protection

Changes the behavior of a shape by restricting direct manipulation.

Property | PID | Type | Default | Description
fLockRotation | 119 | BOOL | FALSE | No rotation
fLockAspectRatio | 120 | BOOL | FALSE | Don't allow changes in aspect ratio
fLockPosition | 121 | BOOL | FALSE | Don't allow the shape to be moved
fLockAgainstSelect | 122 | BOOL | FALSE | Shape may not be selected
fLockCropping | 123 | BOOL | FALSE | No cropping this shape
fLockVertices | 124 | BOOL | FALSE | Edit Points not allowed
fLockText | 125 | BOOL | FALSE | Do not edit text
fLockAdjustHandles | 126 | BOOL | FALSE | Do not adjust
fLockAgainstGrouping | 127 | BOOL | FALSE | Do not group this shape

< > < >

### Text

How text fits in a shape. Text is host-dependent, so some hosts may ignore some of these properties.

Property | PID | Type | Default | Description
lTxid | 128 | LONG | 0 | id for the text, value determined by the host
dxTextLeft | 129 | LONG | 1/10 inch | margins relative to shape's inscribed text rectangle (in EMUs)
dyTextTop | 130 | LONG | 1/20 inch |
dxTextRight | 131 | LONG | 1/10 inch |
dyTextBottom | 132 | LONG | 1/20 inch |
WrapText | 133 | MSOWRAPMODE | FALSE | Wrap text at shape margins
scaleText | 134 | LONG | 0 | Text zoom/scale (used if fFitTextToShape)
anchorText | 135 | MSOANCHOR | Top | How to anchor the text
txflTextFlow | 136 | MSOTXFL | HorzN | Text flow
cdirFont | 137 | MSOCDIR | msocdir0 | Font rotation
hspNext | 138 | MSOHSP | NULL | ID of the next shape (used by Word for linked textboxes)
txdir | 139 | MSOTXDIR | LTR | Bi-Di Text direction
fSelectText | 187 | BOOL | TRUE | TRUE if single click selects text, FALSE if two clicks
fAutoTextMargin | 188 | BOOL | FALSE | use host's margin calculations
fRotateText | 189 | BOOL | FALSE | Rotate text with shape
fFitShapeToText | 190 | BOOL | FALSE | Size shape to fit text size
fFitTextToShape | 191 | BOOL | FALSE | Size text to fit shape size

< > < >

### GeoText

Effect text of the shape - this is what the WordArt tools use, and is separate from the attached text present in ordinary textboxes. Theoretically, a shape could have both (a WordArt with attached text), but this is not currently allowed by the UI. Note that font information is provided here. The default text size is in points, the text effect geometry interfaces require the device size of a point to interpret this. The default point size is a 16.16 fixed-point number. A text effect is present if the fGText boolean is set and either the gtextUNICODE (UNICODE) or gtextRTF (RTF) is present, the UNICODE string takes precedence, however it cannot include any additional font information (unlike the RTF).

Property | PID | Type | Default | Description
gtextUNICODE | 192 | WCHAR* | NULL | UNICODE text string
gtextRTF | 193 | char* | NULL | RTF text string
gtextAlign | 194 | MSOGEOTEXTALIGN | Center | alignment on curve
gtextSize | 195 | LONG | 36<<16 | default point size
gtextSpacing | 196 | LONG | 1<<16 | fixed point 16.16
gtextFont | 197 | WCHAR* | NULL | font family name
gtextFReverseRows | 240 | BOOL | FALSE | Reverse row order
fGtext | 241 | BOOL | FALSE | Has text effect
gtextFVertical | 242 | BOOL | FALSE | Rotate characters
gtextFKern | 243 | BOOL | FALSE | Kern characters
gtextFTight | 244 | BOOL | FALSE | Tightening or tracking
gtextFStretch | 245 | BOOL | FALSE | Stretch to fit shape
gtextFShrinkFit | 246 | BOOL | FALSE | Char bounding box
gtextFBestFit | 247 | BOOL | FALSE | Scale text-on-path
gtextFNormalize | 248 | BOOL | FALSE | Stretch char height
gtextFDxMeasure | 249 | BOOL | FALSE | Do not measure along path
gtextFBold | 250 | BOOL | FALSE | Bold font
gtextFItalic | 251 | BOOL | FALSE | Italic font
gtextFUnderline | 252 | BOOL | FALSE | Underline font
gtextFShadow | 253 | BOOL | FALSE | Shadow font
gtextFSmallcaps | 254 | BOOL | FALSE | Small caps font
gtextFStrikethrough | 255 | BOOL | FALSE | Strike through font

< > < >

### Blip

How a BLIP fits into a shape. This includes cropping information as well as picture display modifications such as brightness and contrast.

Property | PID | Type | Default | Description
cropFromTop | 256 | LONG | 0 | 16.16 fraction times total image width or height, as appropriate.
cropFromBottom | 257 | LONG | 0 |
cropFromLeft | 258 | LONG | 0 |
cropFromRight | 259 | LONG | 0 |
pib | 260 | IMsoBlip* | NULL | Blip to display
pibName | 261 | WCHAR* | NULL | Blip file name
pibFlags | 262 | MSOBLIPFLAGS | Comment | Blip flags
pictureTransparent | 263 | LONG | ~0 | transparent color (none if ~0UL)
pictureContrast | 264 | LONG | 1<<16 | contrast setting
pictureBrightness | 265 | LONG | 0 | brightness setting
pictureGamma | 266 | LONG | 0 | 16.16 gamma
pictureId | 267 | LONG | 0 | Host-defined ID for OLE objects (usually a pointer)
pictureDblCrMod | 268 | MSOCLR | This | Modification used if shape has double shadow
pictureFillCrMod | 269 | MSOCLR | undefined |
pictureLineCrMod | 270 | MSOCLR | undefined |
pibPrint | 271 | IMsoBlip* | NULL | Blip to display when printing
pibPrintName | 272 | WCHAR* | NULL | Blip file name
pibPrintFlags | 273 | MSOBLIPFLAGS | Comment | Blip flags
fNoHitTestPicture | 316 | BOOL | FALSE | Do not hit test the picture
pictureGray | 317 | BOOL | FALSE | grayscale display
pictureBiLevel | 318 | BOOL | FALSE | bi-level display
pictureActive | 319 | BOOL | FALSE | Server is active (OLE objects only)

< >< > Geometry < bgcolor="#FFFFFF">

### Geometry

The geometry of the shape. Typically, these properties reside in a shape type definition, and so are not written to the file. However, freeform shapes drawing using the polygon tools set the pVertices and pSegmentInfo properties to define their geometries.

Property | PID | Type | Default | Description
geoLeft | 320 | LONG | 0 | Defines the G (geometry) coordinate space.
geoTop | 321 | LONG | 0 |
geoRight | 322 | LONG | 21600 |
geoBottom | 323 | LONG | 21600 |
shapePath | 324 | MSOSHAPEPATH | msoshapeLinesClosed |
pVertices | 325 | IMsoArray | NULL | An array of points, in G units.
pSegmentInfo | 326 | IMsoArray | NULL |
adjustValue | 327 | LONG | 0 | Adjustment values corresponding to the positions of the adjust handles of the shape. The number of values used and their allowable ranges vary from shape type to shape type.
adjust2Value | 328 | LONG | 0 |
adjust3Value | 329 | LONG | 0 |
adjust4Value | 330 | LONG | 0 |
adjust5Value | 331 | LONG | 0 |
adjust6Value | 332 | LONG | 0 |
adjust7Value | 333 | LONG | 0 |
adjust8Value | 334 | LONG | 0 |
adjust9Value | 335 | LONG | 0 |
adjust10Value | 336 | LONG | 0 |
fShadowOK | 378 | BOOL | TRUE | Shadow may be set
f3DOK | 379 | BOOL | TRUE | 3D may be set
fLineOK | 380 | BOOL | TRUE | Line style may be set
fGtextOK | 381 | BOOL | FALSE | Text effect (WordArt) supported
fFillShadeShapeOK | 382 | BOOL | FALSE |
fFillOK | 383 | BOOL | TRUE | OK to fill the shape through the UI or VBA?

< > < >

### Fill Style

Two main colors are defined - a foreground color and a background color. Different fillTypes use these values differently. In addition to the foreground and background any number of shade colors can be defined. Each shade color is associated with a "position" which says how far into the shade the color appears – colors must be given in position order. For a solid fill the foreground color is used and the background (and everything else except transparency) is ignored. For pattern and texture fills the fillBlip identifies a BLIP, which will be used for the fill. fillWidth and fillHeight define the desired pattern/texture size in EMUs. The pattern/tile will be expanded to this size. If the pattern is a bitmap the actual size will be rounded to a close integer multiple of the original (pixel) size of the bitmap. If the size is 0 then the pattern/tile will not be expanded or contracted at all in pixel terms, so the fill will be device dependent - this may result in non-proportional scaling between devices (on devices with non-square pixels). For a pattern the foreground and background colors define the colors to use when filling with a pattern, for a texture the colors are in the bitmap (this is the only difference). For both pattern and texture fills the fill is registered with (0,0) on the view in which the effect appears unless fillShape is set to TRUE, in which case the pattern/texture is registered relative to the shape (so it moves with the shape). For a picture fill the fillBlip is centered in the shape - not tiled. For a shaded fill the colors define shade bands to use across the shade, shading between each pair of colors. The positions are the positions of the shade at which the given color appears - the shade ends with the first index that is >= 1 (in 16.16 notation), the indices must be in ascending order or the result is undefined. The interpretation of the shade start and shade end points varies according to the exact shade type. The fillBackground fill indicates a fill inherited from a background object.

Property | PID | Type | Default | Description
fillType | 384 | MSOFILLTYPE | Solid | Type of fill
fillColor | 385 | MSOCLR | white | Foreground color
fillOpacity | 386 | LONG | 1<<16 | Fixed 16.16
fillBackColor | 387 | MSOCLR | white | Background color
fillBackOpacity | 388 | LONG | 1<<16 | Shades only
fillCrMod | 389 | MSOCLR | undefined | Modification for BW views
fillBlip | 390 | IMsoBlip* | NULL | Pattern/texture
fillBlipName | 391 | WCHAR* | NULL | Blip file name
fillBlipFlags | 392 | MSOBLIPFLAGS | Comment | Blip flags
fillWidth | 393 | LONG | 0 | How big (A units) to make a metafile texture.
fillHeight | 394 | LONG | 0 |
fillAngle | 395 | LONG | 0 | Fade angle - degrees in 16.16
fillFocus | 396 | LONG | 0 | Linear shaded fill focus percent
fillToLeft | 397 | LONG | 0 | Fraction 16.16
fillToTop | 398 | LONG | 0 | Fraction 16.16
fillToRight | 399 | LONG | 0 | Fraction 16.16
fillToBottom | 400 | LONG | 0 | Fraction 16.16
fillRectLeft | 401 | LONG | 0 | For shaded fills, use the specified rectangle instead of the shape's bounding rect to define how large the fade is going to be.
fillRectTop | 402 | LONG | 0 |
fillRectRight | 403 | LONG | 0 |
fillRectBottom | 404 | LONG | 0 |
fillDztype | 405 | MSODZTYPE | Default |
fillShadePreset | 406 | LONG | 0 | Special shades
fillShadeColors | 407 | IMsoArray | NULL | a preset array of colors
fillOriginX | 408 | LONG | 0 |
fillOriginY | 409 | LONG | 0 |
fillShapeOriginX | 410 | LONG | 0 |
fillShapeOriginY | 411 | LONG | 0 |
fillShadeType | 412 | MSOSHADETYPE | Default | Type of shading, if a shaded (gradient) fill.
fFilled | 443 | BOOL | TRUE | Is shape filled?
fHitTestFill | 444 | BOOL | TRUE | Should we hit test fill?
fillShape | 445 | BOOL | TRUE | Register pattern on shape
fillUseRect | 446 | BOOL | FALSE | Use the large rect?
fNoFillHitTest | 447 | BOOL | FALSE | Hit test a shape as though filled

< > < >

### Line Style

Lines are centered about the infinitely thin proto-line along which they are drawn. Complex dash effects are supported only for simple lines (e.g. changing the end cap) - defaults should be used for other line styles. The line width is in EMUs; a line width of zero should not be used - there is no logical interpretation on a high-resolution printer.

Property | PID | Type | Default | Description
lineColor | 448 | MSOCLR | black | Color of line
lineOpacity | 449 | LONG | 1<<16 | Not implemented
lineBackColor | 450 | MSOCLR | white | Background color
lineCrMod | 451 | MSOCLR | undefined | Modification for BW views
lineType | 452 | MSOLINETYPE | Solid | Type of line
lineFillBlip | 453 | IMsoBlip* | NULL | Pattern/texture
lineFillBlipName | 454 | WCHAR* | NULL | Blip file name
lineFillBlipFlags | 455 | MSOBLIPFLAGS | Comment | Blip flags
lineFillWidth | 456 | LONG | 0 | How big (A units) to make a metafile texture.
lineFillHeight | 457 | LONG | 0 |
lineFillDztype | 458 | MSODZTYPE | Default | How to interpret fillWidth/Height numbers.
lineWidth | 459 | LONG | 9525 | A units; 1pt == 12700 EMUs
lineMiterLimit | 460 | LONG | 8<<16 | ratio (16.16) of width
lineStyle | 461 | MSOLINESTYLE | Simple | Draw parallel lines?
lineDashing | 462 | MSOLINEDASHING | Solid | Can be overridden by:
lineDashStyle | 463 | IMsoArray | NULL | As Win32 ExtCreatePen
lineStartArrowhead | 464 | MSOLINEEND | NoEnd | Arrow at start
lineEndArrowhead | 465 | MSOLINEEND | NoEnd | Arrow at end
lineStartArrowWidth | 466 | MSOLINEENDWIDTH | MediumWidthArrow | Arrow at start
lineStartArrowLength | 467 | MSOLINEENDLENGTH | MediumLenArrow | Arrow at end
lineEndArrowWidth | 468 | MSOLINEENDWIDTH | MediumWidthArrow | Arrow at start
lineEndArrowLength | 469 | MSOLINEENDLENGTH | MediumLenArrow | Arrow at end
lineJoinStyle | 470 | MSOLINEJOIN | JoinRound | How to join lines
lineEndCapStyle | 471 | MSOLINECAP | EndCapFlat | How to end lines
fArrowheadsOK | 507 | BOOL | FALSE | Allow arrowheads if prop. is set
fLine | 508 | BOOL | TRUE | Any line?
fHitTestLine | 509 | BOOL | TRUE | Should we hit test lines?
lineFillShape | 510 | BOOL | TRUE | Register pattern on shape
fNoLineDrawDash | 511 | BOOL | FALSE | Draw a dashed line if no line

< > < >

### Shadow Style

The interpretation of the transform properties depends on the type of shadow: msoshadowOffset, msoshadowDouble: Only the offset is used. It is interpreted as an absolute offset expressed in EMUs. The default corresponds to 1/36" in both X and Y (2 or 3 pixels on screen depending on monitor resolution). The offset is relative to the drawing axes (as msoshadowDrawing below, not msoshadowRich) so a shadow offset to the bottom right of the drawing is still offset (by the same amount) to the bottom right if the shape is rotated. The "double" case causes two shadows to be drawn, the first (lower) at the second offset and in the shadowHighlightColor. If the second offset is 0,0 it defaults to being the inverse of the first. msoshadowRich: The offsets and transformation properties are in absolute units measured relative to the shape on the drawing - the shadow moves with the shape, but anisotropic scaling of the shape changes the proportions of the shadow, not its angles. Compare with the following where such scaling scales the shadow in proportion too, thus changes the angle between (e.g.) a vertical line in the shape and it's shadow. msoshadowShape: The offsets and transformation properties are relative to the shape; 1.0 corresponds to the shape width/height as appropriate. The shadow is cast relative to the shape then scaled with the shape, so it moves with the shape. The units are simple numbers (ratios of the G unit space effectively). This transformation type is unnatural in real world terms, but behaves nicely in geometric terms. The offset elements of the property set are treated as fixed-point 16.16 values. msoshadowDrawing: A rich shadow cast onto a plane in drawing space. The transform is applied to the drawing coordinates of the shape and is thus expressed in EMUs. This shadow type enables creation of shadows from multiple objects, however the shadows may overlap higher (different) objects if the shadow plane and shape drawing planes overlap on the screen. The shadowWeight parameter is used as in the perspective property set to apply addiitonal scaling to the perspective parameters - these are divided by the weight. Shadow transformations are independent of the perspective transformation applied to a shape - either hte perspective transformation or the shadow transformation is used as appropriate.

Property | PID | Type | Default | Description
shadowType | 512 | MSOSHADOWTYPE | Offset | Type of effect
shadowColor | 513 | MSOCLR | 0x808080 | Foreground color
shadowHighlight | 514 | MSOCLR | 0xCBCBCB | Embossed color
shadowCrMod | 515 | MSOCLR | undefined | Modification for BW views
shadowOpacity | 516 | LONG | 1<<16 | Fixed 16.16
shadowOffsetX | 517 | LONG | 25400 | Offset shadow
shadowOffsetY | 518 | LONG | 25400 | Offset shadow
shadowSecondOffsetX | 519 | LONG | 0 | Double offset shadow
shadowSecondOffsetY | 520 | LONG | 0 | Double offset shadow
shadowScaleXToX | 521 | LONG | 1<<16 | 16.16
shadowScaleYToX | 522 | LONG | 0 | 16.16
shadowScaleXToY | 523 | LONG | 0 | 16.16
shadowScaleYToY | 524 | LONG | 1<<16 | 16.16
shadowPerspectiveX | 525 | LONG | 0 | 16.16 / weight
shadowPerspectiveY | 526 | LONG | 0 | 16.16 / weight
shadowWeight | 527 | LONG | 1<<8 | scaling factor
shadowOriginX | 528 | LONG | 0 |
shadowOriginY | 529 | LONG | 0 |
fShadow | 574 | BOOL | FALSE | Any shadow?
fshadowObscured | 575 | BOOL | FALSE | Excel5-style shadow

< > < >

### Perspective Style

This is just a 2D transformation matrix (3x3). Specifying peculiar values will cause the shape to render completely outside its geometry - normally clients will constrain the values to get reasonable results. The transformation may be applied at various times as the geometry is processed, this affects the behavior of the perspective which results in the same way as the corresponding shadow perspective types.

msoxformAbsolute | Equivalent to msoshadowRich
msoxformShape | Equivalent to msoshadowShape
msoxformDrawing | Equivalent to msoshadowDrawing

In the case of perspective the msoxformShape form is the default - the perspective will then scale proportionally with the overall shape scaling. All parameters except the weight and offset elements are 16.16 fixed-point numbers. The offset is interpreted according to the perspective type, if the type is msoxformShape then the offset is assumed to be a 16.16 fixed point value, otherwise it is assumed to be an integral value (effectively a number of EMUs). The weight acts as an additional divisor for the perspectivePerspectiveX/Y elements - the values in the transformation matrix are obtained by dividing the property values by the weight, the default value of 256 gives a useful range of values for the msoxformShape case, for the other cases the weight should normally be around 1 to 256 times the size of the shape in the coordinate space.

Property | PID | Type | Default | Description
perspectiveType | 576 | MSOXFORMTYPE | Shape | Where transform applies
perspectiveOffsetX | 577 | LONG | 0 | The LONG values define a transformation matrix, effectively, each value is scaled by the perspectiveWeight parameter.
perspectiveOffsetY | 578 | LONG | 0 |
perspectiveScaleXToX | 579 | LONG | 1<<16 |
perspectiveScaleYToX | 580 | LONG | 0 |
perspectiveScaleXToY | 581 | LONG | 0 |
perspectiveScaleYToY | 582 | LONG | 1<<16 |
perspectivePerspectiveX | 583 | LONG | 0 |
perspectivePerspectiveY | 584 | LONG | 0 |
perspectiveWeight | 585 | LONG | 1<<8 | Scaling factor
perspectiveOriginX | 586 | LONG | 1<<15 |
perspectiveOriginY | 587 | LONG | 1<<15 |
fPerspective | 639 | BOOL | FALSE | On/off

< > < >

### 3D Object

Material properties of a 3D object. A 3D effect overrides the fill and line effects and corresponding colors. Extrusion depths are always specified in absolute units.

Property | PID | Type | Default | Description
c3DSpecularAmt | 640 | LONG | 0 | Fixed-point 16.16
c3DDiffuseAmt | 641 | LONG | 65536 | Fixed-point 16.16
c3DShininess | 642 | LONG | 5 | Default gives OK results
c3DEdgeThickness | 643 | LONG | 12700 | Specular edge thickness
c3DExtrudeForward | 644 | LONG | 0 | Distance of extrusion in EMUs
c3DExtrudeBackward | 645 | LONG | 457200 |
c3DExtrudePlane | 646 | LONG | 0 | Extrusion direction
c3DExtrusionColor | 647 | MSOCLR | FillThenLine | Basic color of extruded part of shape; the lighting model used will determine the exact shades used when rendering.
c3DCrMod | 648 | MSOCLR | undefined | Modification for BW views
f3D | 700 | BOOL | FALSE | Does this shape have a 3D effect?
fc3DMetallic | 701 | BOOL | 0 | Use metallic specularity?
fc3DUseExtrusionColor | 702 | BOOL | FALSE |
fc3DLightFace | 703 | BOOL | TRUE |

< > < >

### 3D Style

Properties of a 3D view; note that distances are in drawing units.

Property | PID | Type | Default | Description
c3DYRotationAngle | 704 | LONG | 0 | degrees (16.16) about y axis
c3DXRotationAngle | 705 | LONG | 0 | degrees (16.16) about x axis
c3DRotationAxisX | 706 | LONG | 100 | These specify the rotation axis; only their relative magnitudes matter.
c3DRotationAxisY | 707 | LONG | 0 |
c3DRotationAxisZ | 708 | LONG | 0 |
c3DRotationAngle | 709 | LONG | 0 | degrees (16.16) about axis
c3DRotationCenterX | 710 | LONG | 0 | rotation center x (16.16 or g-units)
c3DRotationCenterY | 711 | LONG | 0 | rotation center y (16.16 or g-units)
c3DRotationCenterZ | 712 | LONG | 0 | rotation center z (absolute (emus))
c3DRenderMode | 713 | MSO3DRENDERMODE | FullRender | Full,wireframe, or bcube
c3DTolerance | 714 | LONG | 30000 | pixels (16.16)
c3DXViewpoint | 715 | LONG | 1250000 | X view point (emus)
c3DYViewpoint | 716 | LONG | -1250000 | Y view point (emus)
c3DZViewpoint | 717 | LONG | 9000000 | Z view distance (emus)
c3DOriginX | 718 | LONG | 32768 |
c3DOriginY | 719 | LONG | -32768 |
c3DSkewAngle | 720 | LONG | -8847360 | degree (16.16) skew angle
c3DSkewAmount | 721 | LONG | 50 | Percentage skew amount
c3DAmbientIntensity | 722 | LONG | 20000 | Fixed point intensity
c3DKeyX | 723 | LONG | 50000 | Key light source direc-
c3DKeyY | 724 | LONG | 0 | tion; only their relative
c3DKeyZ | 725 | LONG | 10000 | magnitudes matter
c3DKeyIntensity | 726 | LONG | 38000 | Fixed point intensity
c3DFillX | 727 | LONG | -50000 | Fill light source direc-
c3DFillY | 728 | LONG | 0 | tion; only their relative
c3DFillZ | 729 | LONG | 10000 | magnitudes matter
c3DFillIntensity | 730 | LONG | 38000 | Fixed point intensity
fc3DConstrainRotation | 763 | BOOL | TRUE |
fc3DRotationCenterAuto | 764 | BOOL | FALSE |
fc3DParallel | 765 | BOOL | 1 | Parallel projection?
fc3DKeyHarsh | 766 | BOOL | 1 | Is key lighting harsh?
fc3DFillHarsh | 767 | BOOL | 0 | Is fill lighting harsh?

< > < >

### Shape

Miscellaneous properties of a single shape which do not apply to group shapes.

Property | PID | Type | Default | Description
hspMaster | 769 | MSOHSP | NULL | master shape
cxstyle | 771 | MSOCXSTYLE | None | Type of connector
bWMode | 772 | MSOBWMODE | Automatic | Settings for modifications to be made when in different forms of black-and-white mode.
bWModePureBW | 773 | MSOBWMODE | Automatic |
bWModeBW | 774 | MSOBWMODE | Automatic |
fOleIcon | 826 | BOOL | FALSE | For OLE objects, whether the object is in icon form
fPreferRelativeResize | 827 | BOOL | FALSE | For UI only. Prefer relative resizing.
fLockShapeType | 828 | BOOL | FALSE | Lock the shape type (don't allow Change Shape)
fDeleteAttachedObject | 830 | BOOL | FALSE |
fBackground | 831 | BOOL | FALSE | If TRUE, this is the background shape.

< > < >

### Callout

Properties of a callout shape.

Property | PID | Type | Default | Description
spcot | 832 | MSOSPCOT | TwoSegment | Callout type
dxyCalloutGap | 833 | LONG | 1/12 inch | Distance from box to first point.(EMUs)
spcoa | 834 | MSOSPCOA | Any | Callout angle
spcod | 835 | MSOSPCOD | Specified | Callout drop type
dxyCalloutDropSpecified | 836 | LONG | 9 points | if msospcodSpecified, the actual drop distance
dxyCalloutLengthSpecified | 837 | LONG | 0 | if fCalloutLengthSpecified, the actual distance
fCallout | 889 | BOOL | FALSE | Is the shape a callout?
fCalloutAccentBar | 890 | BOOL | FALSE | does callout have accent bar
fCalloutTextBorder | 891 | BOOL | TRUE | does callout have a text border
fCalloutMinusX | 892 | BOOL | FALSE |
fCalloutMinusY | 893 | BOOL | FALSE |
fCalloutDropAuto | 894 | BOOL | FALSE | If true, then we occasionally invert the drop distance
fCalloutLengthSpecified | 895 | BOOL | FALSE | if true, we look at dxyCalloutLengthSpecified

< > < >

### Group Shape

Miscellaneous shape properties that can apply to group shapes.

Property | PID | Type | Default | Description
wzName | 896 | WCHAR* | NULL | Shape Name (present only if explicitly set)
wzDescription | 897 | WCHAR* | NULL | alternate text
pihlShape | 898 | IHlink* | NULL | The hyperlink in the shape.
pWrapPolygonVertices | 899 | IMsoArray | NULL | The polygon that text will be wrapped around (Word)
dxWrapDistLeft | 900 | LONG | 1/8 inch | Left wrapping distance from text (Word)
dyWrapDistTop | 901 | LONG | 0 | Top wrapping distance from text (Word)
dxWrapDistRight | 902 | LONG | 1/8 inch | Right wrapping distance from text (Word)
dyWrapDistBottom | 903 | LONG | 0 | Bottom wrapping distance from text (Word)
lidRegroup | 904 | LONG | 0 | Regroup ID
fEditedWrap | 953 | BOOL | FALSE | Has the wrap polygon been edited?
fBehindDocument | 954 | BOOL | FALSE | Word-only (shape is behind text)
fOnDblClickNotify | 955 | BOOL | FALSE | Notify client on a double click
fIsButton | 956 | BOOL | FALSE | A button shape (i.e., clicking performs an action). Set for shapes with attached hyperlinks or macros.
fOneD | 957 | BOOL | FALSE | 1D adjustment
fHidden | 958 | BOOL | FALSE | Do not display
fPrint | 959 | BOOL | TRUE | Print this shape

< > < >

## Appendix A: Change History

Date |  | Change
1/11/96 |  | Created the document. Left work to be done in the BStore and Complex shape properties.
1/23/97 |  | Extensively updated and reorganized document. Added overview and shape hierarchy information. Added more complete shape property information.
4/15/97 |  | Add details on compression of Metafile Blips. See section "Metafile/PICT Blips"

< > < >

## Appendix B: Colors

Colors are always saved as four-byte LONG values. If the high byte is zero, then the low three bytes contain a normal RGB COLORREF. Otherwise, the value of the high byte is used as a bitfield of flags (notice that the values below are the indices of the bits that are set).

    typedef enum
       {
       msocolorFlagPaletteIndex,  // PALETTEINDEX macro
       msocolorFlagPaletteRGB,    // PALETTERGB macro
       msocolorFlagSystemRGB,     // MSOSYSTEMRGB
       msocolorFlagSchemeIndex,   // MSOSCHEMECOLOR
       msocolorFlagSysIndex,      // MSOSYSCOLOR
       } MSOCOLORINDEX;

Windows defines the first two. The third (SystemRGB) is a flag that it set on an otherwise normal RGB value to indicate to the rendering engine to bypass its normal halftone dithering process and just render the color directly using Windows. The presence of either of the last two flags indicates that the low three bytes are an index into a predefined array of colors. For SchemeIndex colors, the host application provides the translation to RGB colors when necessary (PowerPoint and Excel both use this). SysIndex colors are indices into colors tracked by Escher itself:

    typedef enum
       {
       msosyscolorButtonFace,          // COLOR_BTNFACE
       msosyscolorWindowText,          // COLOR_WINDOWTEXT
       msosyscolorMenu,                // COLOR_MENU
       msosyscolorHighlight,           // COLOR_HIGHLIGHT
       msosyscolorHighlightText,       // COLOR_HIGHLIGHTTEXT
       msosyscolorCaptionText,         // COLOR_CAPTIONTEXT
       msosyscolorActiveCaption,       // COLOR_ACTIVECAPTION
       msosyscolorButtonHighlight,     // COLOR_BTNHIGHLIGHT
       msosyscolorButtonShadow,        // COLOR_BTNSHADOW
       msosyscolorButtonText,          // COLOR_BTNTEXT
       msosyscolorGrayText,            // COLOR_GRAYTEXT
       msosyscolorInactiveCaption,     // COLOR_INACTIVECAPTION
       msosyscolorInactiveCaptionText, // COLOR_INACTIVECAPTIONTEXT
       msosyscolorInfoBackground,      // COLOR_INFOBK
       msosyscolorInfoText,            // COLOR_INFOTEXT
       msosyscolorMenuText,            // COLOR_MENUTEXT
       msosyscolorScrollbar,           // COLOR_SCROLLBAR
       msosyscolorWindow,              // COLOR_WINDOW
       msosyscolorWindowFrame,         // COLOR_WINDOWFRAME
       msosyscolor3DLight,             // COLOR_3DLIGHT
       msosyscolorMax,                 // Count of system colors

       msocolorFillColor =0xF0,  // Use the fillColor property
       msocolorLineOrFillColor,  // Use the line color only if there is a line
       msocolorLineColor,        // Use the lineColor property
       msocolorShadowColor,      // Use the shadow color
       msocolorThis,             // Use this color (only valid as described below)
       msocolorFillBackColor,    // Use the fillBackColor property
       msocolorLineBackColor,    // Use the lineBackColor property
       msocolorFillThenLine,     // Use the fillColor unless no fill and line
       msocolorIndexMask =0xFF,  // Extract the color index

       msocolorProcessMask      =0xFFFF00, // All the processing bits
       msocolorModificationMask =0x0F00,   // Just the function
       msocolorModFlagMask      =0xF000,   // Just the additional flags
       msocolorDarken           =0x0100,   // Darken color by parameter/255
       msocolorLighten          =0x0200,   // Lighten color by parameter/255
       msocolorAdd              =0x0300,   // Add grey level RGB(param,param,param)
       msocolorSubtract         =0x0400,   // Subtract grey level RGB(p,p,p)
       msocolorReverseSubtract  =0x0500,   // Subtract from grey level RGB(p,p,p)
       /* In the following "black" means maximum component value, white minimum.
          The operation is per component, to guarantee white combine with
       msocolorGray */
       msocolorBlackWhite       =0x0600,   // Black if < uParam, else white (>=)
       msocolorInvert           =0x2000,   // Invert color (at the *end*)
       msocolorInvert128        =0x4000,   // Invert by toggling the top bit
       msocolorGray             =0x8000,   // Make the color gray (before the above!)
       msocolorBParamMask       =0xFF0000, // Parameter used as above
       msocolorBParamShift =16,            // To extract the parameter value
       }
    MSOSYSCOLORINDEX;

< > < >

## Appendix C: Shape Types

Internally, a shape type is defined as a fixed set of property values, the most important being the geometry of the shape (the pVertices property, etc.). Each shape stores in itself only those properties that differ from its shape type. When a shape is asked for a property that isn't in its local table, it looks in the shape type's table. If the shape type doesn't define a value for the property, then the property's default value is used. In the file format, shapes store their shape types in the instance field of the msofbtSp record.

    typedef enum
       {
       msosptMin = 0,
       msosptNotPrimitive = msosptMin,
       msosptRectangle = 1,
       msosptRoundRectangle = 2,
       msosptEllipse = 3,
       msosptDiamond = 4,
       msosptIsocelesTriangle = 5,
       msosptRightTriangle = 6,
       msosptParallelogram = 7,
       msosptTrapezoid = 8,
       msosptHexagon = 9,
       msosptOctagon = 10,
       msosptPlus = 11,
       msosptStar = 12,
       msosptArrow = 13,
       msosptThickArrow = 14,
       msosptHomePlate = 15,
       msosptCube = 16,
       msosptBalloon = 17,
       msosptSeal = 18,
       msosptArc = 19,
       msosptLine = 20,
       msosptPlaque = 21,
       msosptCan = 22,
       msosptDonut = 23,
       msosptTextSimple = 24,
       msosptTextOctagon = 25,
       msosptTextHexagon = 26,
       msosptTextCurve = 27,
       msosptTextWave = 28,
       msosptTextRing = 29,
       msosptTextOnCurve = 30,
       msosptTextOnRing = 31,
       msosptStraightConnector1 = 32,
       msosptBentConnector2 = 33,
       msosptBentConnector3 = 34,
       msosptBentConnector4 = 35,
       msosptBentConnector5 = 36,
       msosptCurvedConnector2 = 37,
       msosptCurvedConnector3 = 38,
       msosptCurvedConnector4 = 39,
       msosptCurvedConnector5 = 40,
       msosptCallout1 = 41,
       msosptCallout2 = 42,
       msosptCallout3 = 43,
       msosptAccentCallout1 = 44,
       msosptAccentCallout2 = 45,
       msosptAccentCallout3 = 46,
       msosptBorderCallout1 = 47,
       msosptBorderCallout2 = 48,
       msosptBorderCallout3 = 49,
       msosptAccentBorderCallout1 = 50,
       msosptAccentBorderCallout2 = 51,
       msosptAccentBorderCallout3 = 52,
       msosptRibbon = 53,
       msosptRibbon2 = 54,
       msosptChevron = 55,
       msosptPentagon = 56,
       msosptNoSmoking = 57,
       msosptSeal8 = 58,
       msosptSeal16 = 59,
       msosptSeal32 = 60,
       msosptWedgeRectCallout = 61,
       msosptWedgeRRectCallout = 62,
       msosptWedgeEllipseCallout = 63,
       msosptWave = 64,
       msosptFoldedCorner = 65,
       msosptLeftArrow = 66,
       msosptDownArrow = 67,
       msosptUpArrow = 68,
       msosptLeftRightArrow = 69,
       msosptUpDownArrow = 70,
       msosptIrregularSeal1 = 71,
       msosptIrregularSeal2 = 72,
       msosptLightningBolt = 73,
       msosptHeart = 74,
       msosptPictureFrame = 75,
       msosptQuadArrow = 76,
       msosptLeftArrowCallout = 77,
       msosptRightArrowCallout = 78,
       msosptUpArrowCallout = 79,
       msosptDownArrowCallout = 80,
       msosptLeftRightArrowCallout = 81,
       msosptUpDownArrowCallout = 82,
       msosptQuadArrowCallout = 83,
       msosptBevel = 84,
       msosptLeftBracket = 85,
       msosptRightBracket = 86,
       msosptLeftBrace = 87,
       msosptRightBrace = 88,
       msosptLeftUpArrow = 89,
       msosptBentUpArrow = 90,
       msosptBentArrow = 91,
       msosptSeal24 = 92,
       msosptStripedRightArrow = 93,
       msosptNotchedRightArrow = 94,
       msosptBlockArc = 95,
       msosptSmileyFace = 96,
       msosptVerticalScroll = 97,
       msosptHorizontalScroll = 98,
       msosptCircularArrow = 99,
       msosptNotchedCircularArrow = 100,
       msosptUturnArrow = 101,
       msosptCurvedRightArrow = 102,
       msosptCurvedLeftArrow = 103,
       msosptCurvedUpArrow = 104,
       msosptCurvedDownArrow = 105,
       msosptCloudCallout = 106,
       msosptEllipseRibbon = 107,
       msosptEllipseRibbon2 = 108,
       msosptFlowChartProcess = 109,
       msosptFlowChartDecision = 110,
       msosptFlowChartInputOutput = 111,
       msosptFlowChartPredefinedProcess = 112,
       msosptFlowChartInternalStorage = 113,
       msosptFlowChartDocument = 114,
       msosptFlowChartMultidocument = 115,
       msosptFlowChartTerminator = 116,
       msosptFlowChartPreparation = 117,
       msosptFlowChartManualInput = 118,
       msosptFlowChartManualOperation = 119,
       msosptFlowChartConnector = 120,
       msosptFlowChartPunchedCard = 121,
       msosptFlowChartPunchedTape = 122,
       msosptFlowChartSummingJunction = 123,
       msosptFlowChartOr = 124,
       msosptFlowChartCollate = 125,
       msosptFlowChartSort = 126,
       msosptFlowChartExtract = 127,
       msosptFlowChartMerge = 128,
       msosptFlowChartOfflineStorage = 129,
       msosptFlowChartOnlineStorage = 130,
       msosptFlowChartMagneticTape = 131,
       msosptFlowChartMagneticDisk = 132,
       msosptFlowChartMagneticDrum = 133,
       msosptFlowChartDisplay = 134,
       msosptFlowChartDelay = 135,
       msosptTextPlainText = 136,
       msosptTextStop = 137,
       msosptTextTriangle = 138,
       msosptTextTriangleInverted = 139,
       msosptTextChevron = 140,
       msosptTextChevronInverted = 141,
       msosptTextRingInside = 142,
       msosptTextRingOutside = 143,
       msosptTextArchUpCurve = 144,
       msosptTextArchDownCurve = 145,
       msosptTextCircleCurve = 146,
       msosptTextButtonCurve = 147,
       msosptTextArchUpPour = 148,
       msosptTextArchDownPour = 149,
       msosptTextCirclePour = 150,
       msosptTextButtonPour = 151,
       msosptTextCurveUp = 152,
       msosptTextCurveDown = 153,
       msosptTextCascadeUp = 154,
       msosptTextCascadeDown = 155,
       msosptTextWave1 = 156,
       msosptTextWave2 = 157,
       msosptTextWave3 = 158,
       msosptTextWave4 = 159,
       msosptTextInflate = 160,
       msosptTextDeflate = 161,
       msosptTextInflateBottom = 162,
       msosptTextDeflateBottom = 163,
       msosptTextInflateTop = 164,
       msosptTextDeflateTop = 165,
       msosptTextDeflateInflate = 166,
       msosptTextDeflateInflateDeflate = 167,
       msosptTextFadeRight = 168,
       msosptTextFadeLeft = 169,
       msosptTextFadeUp = 170,
       msosptTextFadeDown = 171,
       msosptTextSlantUp = 172,
       msosptTextSlantDown = 173,
       msosptTextCanUp = 174,
       msosptTextCanDown = 175,
       msosptFlowChartAlternateProcess = 176,
       msosptFlowChartOffpageConnector = 177,
       msosptCallout90 = 178,
       msosptAccentCallout90 = 179,
       msosptBorderCallout90 = 180,
       msosptAccentBorderCallout90 = 181,
       msosptLeftRightUpArrow = 182,
       msosptSun = 183,
       msosptMoon = 184,
       msosptBracketPair = 185,
       msosptBracePair = 186,
       msosptSeal4 = 187,
       msosptDoubleWave = 188,
       msosptActionButtonBlank = 189,
       msosptActionButtonHome = 190,
       msosptActionButtonHelp = 191,
       msosptActionButtonInformation = 192,
       msosptActionButtonForwardNext = 193,
       msosptActionButtonBackPrevious = 194,
       msosptActionButtonEnd = 195,
       msosptActionButtonBeginning = 196,
       msosptActionButtonReturn = 197,
       msosptActionButtonDocument = 198,
       msosptActionButtonSound = 199,
       msosptActionButtonMovie = 200,
       msosptHostControl = 201,
       msosptTextBox = 202,
       msosptMax,
       msosptNil = 0x0FFF,
     } MSOSPT;

< > < >

## Appendix D: Miscellaneous Enumerated Types

    // MSOSHAPEPATH
    typedef enum
       {
       msoshapeLines,        // A line of straight segments
       msoshapeLinesClosed,  // A closed polygonal object
       msoshapeCurves,       // A line of Bezier curve segments
       msoshapeCurvesClosed, // A closed shape with curved edges
       msoshapeComplex,      // pSegmentInfo must be non-empty
       } MSOSHAPEPATH;

    // MSOWRAPMODE
    typedef enum
       {
       msowrapSquare,
       msowrapByPoints,
       msowrapNone,
       msowrapTopBottom,
       msowrapThrough,
       } MSOWRAPMODE;

    // MSOBWMODE
    typedef enum
       {
       msobwColor,          // only used for predefined shades
       msobwAutomatic,      // depends on object type
       msobwGrayScale,      // shades of gray only
       msobwLightGrayScale, // shades of light gray only
       msobwInverseGray,    // dark gray mapped to light gray, etc.
       msobwGrayOutline,    // pure gray and white
       msobwBlackTextLine,  // black text and lines, all else grayscale
       msobwHighContrast,   // pure black and white mode (no grays)
       msobwBlack,          // solid black
       msobwWhite,          // solid white
       msobwDontShow,       // object not drawn
       msobwNumModes        // number of Black and white modes
       } MSOBWMODE;

    // MSOANCHOR
    typedef enum
       {
       msoanchorTop,
       msoanchorMiddle,
       msoanchorBottom,
       msoanchorTopCentered,
       msoanchorMiddleCentered,
       msoanchorBottomCentered,
       msoanchorTopBaseline,
       msoanchorBottomBaseline,
       msoanchorTopCenteredBaseline,
       msoanchorBottomCenteredBaseline
       } MSOANCHOR;

    // MSOCDIR
    typedef enum
       {
       msocdir0,       // Right
       msocdir90,      // Down
       msocdir180,     // Left
       msocdir270      // Up
       } MSOCDIR;

    // MSOCXSTYLE – connector style
    typedef enum
       {
       msocxstyleStraight = 0,
       msocxstyleBent,
       msocxstyleCurved,
       msocxstyleNone
       } MSOCXSTYLE;

    // MSOTXFL -- text flow
    typedef enum
       {
       msotxflHorzN,           // Horizontal non-@
       msotxflTtoBA,           // Top to Bottom @-font
       msotxflBtoT,            // Bottom to Top non-@
       msotxflTtoBN,           // Top to Bottom non-@
       msotxflHorzA,           // Horizontal @-font
       msotxflVertN,           // Vertical, non-@
       } MSOTXFL;

    // MSOTXDIR - text direction (needed for Bi-Di support)
    typedef enum
       {
       msotxdirLTR,           // left-to-right text direction
       msotxdirRTL,           // right-to-left text direction
        msotxdirContext,      // context text direction
        } MSOTXDIR;

    // MSOSPCOT -- Callout Type
    typedef enum
       {
       msospcotRightAngle = 1,
       msospcotOneSegment = 2,
       msospcotTwoSegment = 3,
       msospcotThreeSegment = 4,
       } MSOSPCOT;

    // MSOSPCOA -- Callout Angle
    typedef enum
       {
       msospcoaAny,
       msospcoa30,
       msospcoa45,
       msospcoa60,
       msospcoa90,
       msospcoa0,
       } MSOSPCOA;

    // MSOSPCOD -- Callout Drop
    typedef enum
       {
       msospcodTop,
       msospcodCenter,
       msospcodBottom,
       msospcodSpecified,
       } MSOSPCOD;

    // MSOGEOTEXTALIGN – WordArt alignment
    typedef enum
       {
       msoalignTextStretch,      /* Stretch each line of text to fit width. */
       msoalignTextCenter,       /* Center text on width. */
       msoalignTextLeft,         /* Left justify. */
       msoalignTextRight,        /* Right justify. */
       msoalignTextLetterJust,   /* Spread letters out to fit width. */
       msoalignTextWordJust,     /* Spread words out to fit width. */
       msoalignTextInvalid       /* Invalid */
       } MSOGEOTEXTALIGN;

    // MSOBLIPFLAGS – flags for pictures
    typedef enum
       {
       msoblipflagDefault = 0,
       msoblipflagComment = 0,   // Blip name is a comment
       msoblipflagFile,          // Blip name is a file name
       msoblipflagURL,           // Blip name is a full URL
       msoblipflagType = 3,      // Mask to extract type
       /* Or the following flags with any of the above. */
       msoblipflagDontSave = 4,  // A "dont" is the depression in the metal
                                 // body work of an automobile caused when a
                                 // cyclist violently thrusts his or her nose
                                 // at it, thus a DontSave is another name for
                                 // a cycle lane.
       msoblipflagDoNotSave = 4, // For those who prefer English
       msoblipflagLinkToFile = 8,
       } MSOBLIPFLAGS;

    // MSO3DRENDERMODE
    typedef enum
       {
       msoFullRender,      // Generate a full rendering
       msoWireframe,       // Generate a wireframe
       msoBoundingCube,    // Generate a bounding cube
       } MSO3DRENDERMODE;

    // MSOXFORMTYPE
    typedef enum
       {
       msoxformAbsolute,   // Apply transform in absolute space centered on shape
       msoxformShape,      // Apply transform to shape geometry
       msoxformDrawing     // Apply transform in drawing space
       } MSOXFORMTYPE;

    // MSOSHADOWTYPE
    typedef enum
       {
       msoshadowOffset,    // N pixel offset shadow
       msoshadowDouble,    // Use second offset too
       msoshadowRich,      // Rich perspective shadow (cast relative to shape)
       msoshadowShape,     // Rich perspective shadow (cast in shape space)
       msoshadowDrawing,   // Perspective shadow cast in drawing space
       msoshadowEmbossOrEngrave,
       } MSOSHADOWTYPE;

    // MSODZTYPE - the type of a (length) measurement
    typedef enum
       {
       msodztypeMin          = 0,
       msodztypeDefault      = 0,  // Default size, ignore the values
       msodztypeA            = 1,  // Values are in EMUs
       msodztypeV            = 2,  // Values are in pixels
       msodztypeShape        = 3,  // Values are 16.16 fractions of shape size
       msodztypeFixedAspect  = 4,  // Aspect ratio is fixed
       msodztypeAFixed       = 5,  // EMUs, fixed aspect ratio
       msodztypeVFixed       = 6,  // Pixels, fixed aspect ratio
       msodztypeShapeFixed   = 7,  // Proportion of shape, fixed aspect ratio
       msodztypeFixedAspectEnlarge
                             = 8,  // Aspect ratio is fixed, favor larger size
       msodztypeAFixedBig    = 9,  // EMUs, fixed aspect ratio
       msodztypeVFixedBig    = 10, // Pixels, fixed aspect ratio
       msodztypeShapeFixedBig= 11, // Proportion of shape, fixed aspect ratio
       msodztypeMax         = 11
       } MSODZTYPE;

    // MSOFILLTYPE
    typedef enum
       {
       msofillSolid,             // Fill with a solid color
       msofillPattern,           // Fill with a pattern (bitmap)
       msofillTexture,           // A texture (pattern with its own color map)
       msofillPicture,           // Center a picture in the shape
       msofillShade,             // Shade from start to end points
       msofillShadeCenter,       // Shade from bounding rectangle to end point
       msofillShadeShape,        // Shade from shape outline to end point
       msofillShadeScale,        // Similar to msofillShade, but the fillAngle
                                 // is additionally scaled by the aspect ratio of
                                 // the shape. If shape is square, it is the
                                 // same as msofillShade.
       msofillShadeTitle,        // special type - shade to title ---  for PP
       msofillBackground         // Use the background fill color/pattern
       } MSOFILLTYPE;

    // MSOSHADETYPE – how to interpret the colors in a shaded fill.
    typedef enum
       {
       msoshadeNone  = 0,        // Interpolate without correction between RGBs
       msoshadeGamma = 1,        // Apply gamma correction to colors
       msoshadeSigma = 2,        // Apply a sigma transfer function to position
       msoshadeBand  = 4,        // Add a flat band at the start of the shade
       msoshadeOneColor = 8,     // This is a one color shade

       /* A parameter for the band or sigma function can be stored in the top
          16 bits of the value - this is a proportion of *each* band of the
          shade to make flat (or the approximate equal value for a sigma
          function).  NOTE: the parameter is not used for the sigma function,
          instead a built in value is used.  This value should not be changed
          from the default! */
       msoshadeParameterShift = 16,
       msoshadeParameterMask  = 0xffff0000,

       msoshadeDefault = (msoshadeGamma|msoshadeSigma|
                         (16384<<msoshadeParameterShift))
       } MSOSHADETYPE;

    //   MSOLINESTYLE - compound line style
    typedef enum
       {
       msolineSimple,            // Single line (of width lineWidth)
       msolineDouble,            // Double lines of equal width
       msolineThickThin,         // Double lines, one thick, one thin
       msolineThinThick,         // Double lines, reverse order
       msolineTriple             // Three lines, thin, thick, thin
       } MSOLINESTYLE;

    // MSOLINETYPE - how to "fill" the line contour
    typedef enum
       {
       msolineSolidType,         // Fill with a solid color
       msolinePattern,           // Fill with a pattern (bitmap)
       msolineTexture,           // A texture (pattern with its own color map)
       msolinePicture            // Center a picture in the shape
       } MSOLINETYPE;

    // MSOLINEDASHING - dashed line style
    typedef enum
       {
       msolineSolid,              // Solid (continuous) pen
       msolineDashSys,            // PS_DASH system   dash style
       msolineDotSys,             // PS_DOT system   dash style
       msolineDashDotSys,         // PS_DASHDOT system dash style
       msolineDashDotDotSys,      // PS_DASHDOTDOT system dash style
       msolineDotGEL,             // square dot style
       msolineDashGEL,            // dash style
       msolineLongDashGEL,        // long dash style
       msolineDashDotGEL,         // dash short dash
       msolineLongDashDotGEL,     // long dash short dash
       msolineLongDashDotDotGEL   // long dash short dash short dash
       } MSOLINEDASHING;

    // MSOLINEEND - line end effect
    typedef enum
       {
       msolineNoEnd,
       msolineArrowEnd,
       msolineArrowStealthEnd,
       msolineArrowDiamondEnd,
       msolineArrowOvalEnd,
       msolineArrowOpenEnd,
       } MSOLINEEND;

    // MSOLINEENDWIDTH - size of arrowhead
    typedef enum
       {
       msolineNarrowArrow,
       msolineMediumWidthArrow,
       msolineWideArrow
       } MSOLINEENDWIDTH;

    //   MSOLINEENDLENGTH - size of arrowhead
    typedef enum
       {
       msolineShortArrow,
       msolineMediumLenArrow,
       msolineLongArrow
       } MSOLINEENDLENGTH;

    //   MSOLINEJOIN - line join style.
    typedef enum
       {
       msolineJoinBevel,     // Join edges by a straight line
       msolineJoinMiter,     // Extend edges until they join
       msolineJoinRound      // Draw an arc between the two edges
       } MSOLINEJOIN;

    //   MSOLINECAP - line cap style (applies to ends of dash segments too).
    typedef enum
       {
       msolineEndCapRound,   // Rounded ends - the default
       msolineEndCapSquare,  // Square protrudes by half line width
       msolineEndCapFlat     // Line ends at end point
       } MSOLINECAP;