Application-specific metafile comment convention

This document describes a general convention for embedding of data of arbitrary size in a Windows Metafile (WMF).

The Windows Metafile format is Microsoft Windows' native graphics metafile (picture) format and is used in WMF files, on the clipboard, and in OLE objects. Data is embedded in WMF data using the MFCOMMENT escape function. Individual comments are restricted to 32Kb or less.

The convention described here allows for breaking the embedded data into multiple comments (or chunks), in order to support embedding data larger than 32Kb limit.

This format is used by MathType (starting with MathType 6.0b for Windows) for its MTEF and MathML embedded in WMFs.

An embedded comment may consist of one or more chunks. Each chunk consists of a header followed by the data for the chunk:

// Format of AppsMFCC Comment format:
#pragma pack(push,1)
typedef struct {
    Char  id[8]           // Must be "AppsMFCC"
    Word  version         // Must be 1
    DWord totalLen;       // Total of data bytes in all comments
    DWord dataLen;        // # of data bytes in this comment (see 'data' below) 
    Char  signature[1]    // Variable length, null terminated string (see below for full details)
    // dataLen bytes of data follows (aka the chunk data)
}       
    AppsMFCCHeader;
#pragma pack(pop) 

//--------------------------------------------------------------------------------------------------
// The total size of the chunk (header and data) must be <= Max comment size.

// Max Comment Size (max number bytes allowed in an AppsMFCC comment) ...
//   for file types that support only a 16-bit comment size (e.g. WMF)
#define MAX_APPSMFCC_16_CMT_LEN       0x00007FFE
//   for file types that support a 32-bit comment size (e.g. EMF)
#define MAX_APPSMFCC_32_CMT_LEN       0x7FFFFFFE

//--------------------------------------------------------------------------------------------------  
// Format of signature:
//  A signature is a variable length, null terminated string of the form:
//   "<Organization>/<App specific data name>[/<str>]"  
//
// Where:
//  <Organization> = the name of the organization/company owning the data (e.g. "Wiris")
//  <App specific data> = the type of (possibly application specific) data this chunk contains 
//  (e.g. "MTEF" or "MathML")
//  <str> = optional string (i.e. defined by the owner for their own purposes)
// None of these elements may contain "/" or "\" unless preceded by "\"

Rules and Assumptions

  1. When totalLen == dataLen, the comment is self contained (i.e. all data is in current comment).
  2. When totalLen > dataLen, more data must be read from subsequent AppsMFCC comments with the same <version#>/<Organization>/<App specific data name> until the entire data block is accumulated.
  3. When data is stored in multiple AppsMFCC comments the comments will be in order with no intervening AppsMFCC comments.
  4. When data is stored in multiple AppsMFCC comments the actual amount of data stored in each comment is at the discretion of the writing app (subject to the max restriction above).