home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Extras / IFF / IFF_Forms / DR2D.doc < prev    next >
Encoding:
Text File  |  1993-03-01  |  34.2 KB  |  946 lines

  1. 2-D Object standard format
  2.  
  3. FORM DR2D
  4.  
  5. Description by Ross Cunniff and John Orr
  6.  
  7.  
  8. A standard IFF FORM to describe 2D drawings has been sorely needed for
  9. a long time.  Several commercial drawing packages have been available
  10. for some time but none has established its file format as the Amiga
  11. standard.  The absence of a 2D drawing standard hinders the
  12. development of applications that use 2D drawings as it forces each
  13. application to understand several private standards instead of a
  14. single one.  Without a standard, data exchange for both the developer
  15. and the user is difficult, if not impossible.
  16.  
  17. The DR2D FORM fills this void.  This FORM was developed by Taliesin,
  18. Inc. for use as the native file format for their two-dimensional
  19. structured drawing package, ProVector.  Saxon Industries and Soft
  20. Logik Publishing Corporation are planning to support this new FORM in
  21. the near future.
  22.  
  23. Many of the values stored in the DR2D FORM are stored as IEEE single
  24. precision floating point numbers.  These numbers consist of 32 bits,
  25. arranged as follows:
  26.  
  27.  _______________________________________________________________________
  28. | s e e e e e e e | e m m m m m m m | m m m m m m m m | m m m m m m m m |
  29.  -----------------------------------------------------------------------
  30.   31            24  23            16  15            8   7             0
  31.  
  32.  
  33. where: 
  34.  
  35.     s    is the sign of the number where 1 is negative and 0 is
  36.           positive. 
  37.     e    is the 8 bit exponent in excess 127 form.  This number
  38.           is the power of two to which the mantissa is raised
  39.           (Excess 127 form means that 127 is added to the
  40.           exponent before packing it into the IEEE number.) 
  41.     m    is the 23 bit mantissa.  It ranges from 1.0000000 to
  42.           1.999999..., where the leading base-ten one is
  43.           assumed. 
  44.  
  45. An IEEE single precision with the value of 0.0000000 has all its bits
  46. cleared. 
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56. The DR2D Chunks
  57.  
  58.  
  59. FORM (0x464F524D)      /* All drawings are a FORM */
  60.  
  61.     struct FORMstruct {
  62.         ULONG    ID;            /* DR2D */
  63.         ULONG    Size;
  64.     };
  65.  
  66.  
  67. DR2D (0x44523244)  /* ID of 2D drawing */
  68.  
  69.  
  70. The DR2D chunks are broken up into three groups: the global drawing
  71. attribute chunks, the object attribute chunks, and the object chunks.
  72. The global drawing attribute chunks describe elements of a 2D drawing
  73. that are common to many objects in the drawing.  Document preferences,
  74. palette information, and custom fill patterns are typical
  75. document-wide settings defined in global drawing attribute chunks.
  76. The object attribute chunks are used to set certain properties of the
  77. object chunk(s) that follows the object attribute chunk.  The current
  78. fill pattern, dash pattern, and line color are all set using an object
  79. attribute chunk.  Object chunks describe the actual DR2D drawing.
  80. Polygons, text, and bitmaps are found in these chunks.
  81.  
  82.  
  83.  
  84. The Global Drawing Attribute Chunks
  85.  
  86. The following chunks describe global attributes of a DR2D document.
  87.  
  88. DRHD (0x44524844)     /* Drawing header */
  89.  
  90. The DRHD chunk contains the upper left and lower right extremes of the
  91. document in (X, Y) coordinates.  This chunk is required and should
  92. only appear once in a document in the outermost layer of the DR2D file
  93. (DR2Ds can be nested).
  94.  
  95.     struct DRHDstruct {
  96.         ULONG    ID;
  97.         ULONG    Size;            /* Always 16 */
  98.         IEEE    XLeft, YTop,
  99.             XRight, YBot;
  100.     };
  101.  
  102.  
  103. The point (XLeft,YTop) is the upper left corner of the project and the
  104. point (XRight,YBot) is its lower right corner.  These coordinates not
  105. only supply the size and position of the document in a coordinate
  106. system, they also supply the project's orientation.  If XLeft <
  107. XRight, the X-axis increases toward the right.  If YTop < YBot, the
  108. Y-axis increases toward the bottom.  Other combinations are possible;
  109. for example in Cartesian coordinates, XLeft would be less than XRight
  110. but YTop would be greater than YBot.
  111.  
  112.  
  113.  
  114.  
  115.  
  116. PPRF (0x50505249)       /* Page preferences */
  117.  
  118. The PPRF chunk contains preference settings for ProVector.  Although
  119. this chunk is not required, its use is encouraged because it contains
  120. some important environment information.
  121.  
  122.     struct PPRFstruct {
  123.         ULONG    ID;
  124.         ULONG    Size;
  125.         char    Prefs[Size];
  126.     };
  127.  
  128. DR2D stores preferences as a concatenation of several null-terminated
  129. strings, in the Prefs[] array.  The strings can appear in any order.
  130. The currently supported strings are:
  131.  
  132.         Units=<unit-type>
  133.         Portrait=<boolean>
  134.         PageType=<page-type>
  135.         GridSize=<number>
  136.  
  137. where:
  138.         <unit-type>     is either Inch, Cm, or Pica
  139.         <boolean>       is either True or False
  140.         <page-type>     is either Standard, Legal, B4, B5, A3,
  141.                   A4, A5, or Custom 
  142.         <number>        is a floating-point number
  143.  
  144. The DR2D FORM does not require this chunk to explicitly state all the
  145. possible preferences.  In the absence of any particular preference
  146. string, a DR2D reader should fall back on the default value.  The
  147. defaults are:
  148.  
  149.         Units=Inch
  150.         Portrait=True
  151.         PageType=Standard
  152.         GridSize=1.0
  153.  
  154.  
  155. CMAP (0x434D4150)       /* Color map (Same as ILBM CMAP) */
  156.  
  157. This chunk is identical to the ILBM CMAP chunk as described in the IFF
  158. ILBM documentation.
  159.  
  160.     struct CMAPstruct {
  161.         ULONG    ID;
  162.         ULONG    Size;
  163.         UBYTE    ColorMap[Size];
  164.     };
  165.  
  166. ColorMap is an array of 24-bit RGB color values.  The 24-bit value is
  167. spread across three bytes, the first of which contains the red
  168. intensity, the next contains the green intensity, and the third
  169. contains the blue intensity.  Because DR2D stores its colors with
  170. 24-bit accuracy, DR2D readers must not make the mistake that some ILBM
  171. readers do in assuming the CMAP chunk colors correspond directly to
  172. Amiga color registers.
  173.  
  174.  
  175.  
  176. FONS (0x464F4E53)       /* Font chunk (Same as FTXT FONS chunk) */
  177.  
  178. The FONS chunk contains information about a font used in the DR2D
  179. FORM.  ProVector does not include support for Amiga fonts.  Instead,
  180. ProVector uses fonts defined in the OFNT FORM which is documented
  181. later in this article.
  182.  
  183.     struct FONSstruct {
  184.         ULONG    ID;
  185.         ULONG    Size;
  186.         UBYTE    FontID;        /* ID the font is referenced by */
  187.         UBYTE    Pad1;              /* Always 0 */
  188.         UBYTE    Proportional;    /* Is it proportional? */
  189.         UBYTE    Serif;        /* does it have serifs? */
  190.         CHAR    Name[Size-4];    /* The name of the font */
  191.     };
  192.  
  193. The UBYTE FontID field is the number DR2D assigns to this font.
  194. References to this font by other DR2D chunks are made using this
  195. number.    
  196.  
  197. The Proportional and Serif fields indicate properties of this font.
  198. Specifically, Proportional indicates if this font is proportional, and
  199. Serif indicates if this font has serifs.  These two options were
  200. created to allow for font substitution in case the specified font is
  201. not available.  They are set according to these values:
  202.  
  203.     0    The DR2D writer didn't know if this font is
  204.           proportional/has serifs. 
  205.     1    No, this font is not proportional/does not have
  206.           serifs. 
  207.     2    Yes, this font is proportional/does have serifs.
  208.  
  209. The last field, Name[], is a NULL terminated string containing the
  210. name of the font. 
  211.  
  212.  
  213. DASH (0x44415348)       /* Line dash pattern for edges */
  214.  
  215. This chunk describes the on-off dash pattern associated with a line.
  216.  
  217.     struct DASHstruct {
  218.         ULONG    ID;
  219.         ULONG    Size;
  220.         USHORT    DashID;            /* ID of the dash pattern */
  221.         USHORT    NumDashes;         /* Should always be even */
  222.         IEEE    Dashes[NumDashes];      /* On-off pattern */
  223.     };
  224.  
  225. DashID is the number assigned to this specific dash pattern.
  226. References to this dash pattern by other DR2D chunks are made using
  227. this number.
  228.  
  229. The Dashes[] array contains the actual dash pattern.  The first number
  230. in the array (element 0) is the length of the ``on'' portion of the
  231. pattern.  The second number (element 1) specifies the ``off'' portion
  232. of the pattern.  If there are more entries in the Dashes array, the
  233. pattern will continue.  Even-index elements specify the length of an
  234. ``on'' span, while odd-index elements specify the length of an ``off''
  235. span.  There must be an even number of entries.  These lengths are not
  236. in the same units as specified in the PPRF chunk, but are multiples of
  237. the line width, so a line of width 2.5 and a dash pattern of 1.0, 2.0
  238. would have an ``on'' span of length 1.0 x 2.5 = 2.5 followed by an
  239. ``off'' span of length 2.0 x 2.5 = 5.  The following figure shows
  240. several dash pattern examples.  Notice that for lines longer than the
  241. dash pattern, the pattern repeats.
  242.  
  243.  
  244. [figure 1 - dash patterns]
  245.  
  246. By convention, DashID 0 is reserved to mean `No line pattern at all',
  247. i.e. the edges are invisible.  This DASH pattern should not be defined
  248. by a DR2D DASH chunk.  Again by convention, a NumDashes of 0 means
  249. that the line is solid.
  250.  
  251.  
  252. AROW (0x41524F57)       /* An arrow-head pattern */
  253.  
  254. The AROW chunk describes an arrowhead pattern.  DR2D open polygons
  255. (OPLY) can have arrowheads attached to their endpoints.  See the
  256. description of the OPLY chunk later in this article for more
  257. information on the OPLY chunk.
  258.  
  259.  
  260.     #define ARROW_FIRST  0x01 /* Draw an arrow on the OPLY's first point */
  261.     #define ARROW_LAST   0x02 /* Draw an arrow on the OPLY's last point */
  262.  
  263.     struct AROWstruct {
  264.         ULONG    ID;
  265.         ULONG    Size;
  266.         UBYTE    Flags;        /* Flags, from ARROW_*, above */
  267.         UBYTE    Pad0;        /* Should always 0 */
  268.         USHORT    ArrowID;    /* Name of the arrow head */
  269.         USHORT    NumPoints;
  270.         IEEE    ArrowPoints[NumPoints*2];
  271.     };
  272.  
  273.  
  274. The Flags field specifies which end(s) of an OPLY to place an
  275. arrowhead based on the #defines above.  ArrowID is the number by which
  276. an OPLY will reference this arrowhead pattern.
  277.  
  278. The coordinates in the array ArrowPoints[] define the arrowhead's
  279. shape.  These points form a closed polygon.  See the section on the
  280. OPLY/CPLY object chunks for a descriptionof how DR2D defines shapes.
  281. The arrowhead is drawn in the same coordinate system relative to the
  282. endpoint of the OPLY the arrowhead is attached to.  The arrowhead's
  283. origin (0,0) coincides with the OPLY's endpoint.  DR2D assumes that
  284. the arrowhead represented in the AROW chunk is pointing to the right
  285. so the proper rotation can be applied to the arrowhead.  The arrow is
  286. filled according to the current fill pattern set in the ATTR object
  287. attribute chunk.
  288.  
  289.  
  290.  
  291. FILL (0x46494C4C)       /* Object-oriented fill pattern */
  292.  
  293. The FILL chunk defines a fill pattern.  This chunk is only valid
  294. inside nested DR2D FORMs.  The GRUP object chunk section of this
  295. article contans an example of the FILL chunk.
  296.  
  297.     struct FILLstruct {
  298.         ULONG    ID;
  299.         ULONG    Size;
  300.         USHORT    FillID;          /* ID of the fill */
  301.     };
  302.  
  303. FillID is the number by which the ATTR object attribute chunk
  304. references fill patterns.  The FILL chunk must be the first chunk
  305. inside a nested DR2D FORM.  A FILL is followed by one DR2D object plus
  306. any of the object attribute chunks (ATTR, BBOX) associated with the
  307. object.
  308.  
  309. [Figure 2 - fill patterns]
  310.  
  311.  
  312. DR2D makes a ``tile'' out of the fill pattern, giving it a virtual
  313. bounding box based on the extreme X and Y values of the FILL's object
  314. (Fig. A).  The bounding box shown in Fig. A surrounding the pattern
  315. (the two ellipses) is invisible to the user.  In concept, this
  316. rectangle is pasted on the page left to right, top to bottom like
  317. floor tiles (Fig. B).  Again, the bounding boxes are not visible.  The
  318. only portion of this tiled pattern that is visible is the part that
  319. overlaps the object (Fig. C) being filled.  The object's path is
  320. called a clipping path, as it ``clips'' its shape from the tiled
  321. pattern (Fig. D).  Note that the fill is only masked on top of
  322. underlying objects, so any ``holes'' in the pattern will act as a
  323. window, leaving visible underlying objects.
  324.  
  325.  
  326. LAYR (0x4C415952)       /* Define a layer */
  327.  
  328. A DR2D project is broken up into one or more layers.  Each DR2D object
  329. is in one of these layers.  Layers provide several useful features.
  330. Any particular layer can be ``turned off'', so that the objects in the
  331. layer are not displayed.  This eliminates the unnecessary display of
  332. objects not currently needed on the screen.  Also, the user can lock a
  333. layer to protect the layer's objects from accidental changes.
  334.     
  335.     struct LAYRstruct {
  336.         ULONG    ID;
  337.         ULONG    Size;
  338.         USHORT   LayerID;           /* ID of the layer */
  339.         char     LayerName[16];       /* Null terminated and padded */
  340.         UBYTE    Flags;           /* Flags, from LF_*, below */
  341.         UBYTE    Pad0;           /* Always 0 */
  342.     };    
  343.  
  344. LayerID is the number assigned to this layer.  As the field's name
  345. indicates, LayerName[] is the NULL terminated name of the layer.
  346. Flags is a bit field who's bits are set according to the #defines
  347. below:
  348.  
  349.     #define LF_ACTIVE         0x01      /* Active for editing */
  350.     #define LF_DISPLAYED      0x02      /* Displayed on the screen */
  351.  
  352. If the LF_ACTIVE bit is set, this layer is unlocked.  A set
  353. LF_DISPLAYED bit indicates that this layer is currently visible on the
  354. screen.  A cleared LF_DISPLAYED bit implies that LF_ACTIVE is not set.
  355. The reason for this is to keep the user from accidentally editing
  356. layers that are invisible.
  357.  
  358.  
  359. The Object Attribute Chunks
  360.  
  361.  
  362. ATTR (0x41545452)       /* Object attributes */
  363.  
  364. The ATTR chunk sets various attributes for the objects that follow it.
  365. The attributes stay in effect until the next ATTR changes the
  366. attributes, or the enclosing FORM ends, whichever comes first.
  367.  
  368.  
  369.     /* Various fill types */
  370.     #define FT_NONE        0    /* No fill            */
  371.     #define FT_COLOR        1    /* Fill with color from palette */
  372.     #define FT_OBJECTS    2    /* Fill with tiled objects    */
  373.  
  374.     
  375.     struct ATTRstruct {
  376.         ULONG    ID;
  377.         ULONG    Size;
  378.         UBYTE    FillType;    /* One of FT_*, above    */
  379.         UBYTE    JoinType;    /* One of JT_*, below    */
  380.         UBYTE    DashPattern; /* ID of edge dash pattern */
  381.         UBYTE    ArrowHead;   /* ID of arrowhead to use  */
  382.         USHORT    FillValue;   /* Color or object with which to fill */
  383.         USHORT    EdgeValue;   /* Edge color index    */
  384.         USHORT    WhichLayer;  /* ID of layer it's in    */
  385.         IEEE    EdgeThick;   /* Line width        */
  386.     };
  387.  
  388.  
  389.  
  390. FillType specifies what kind of fill to use on this ATTR chunk's
  391. objects.  A value of FT_NONE means that this ATTR chunk's objects are
  392. not filled.  FT_COLOR indicates that the objects should be filled in
  393. with a color.  That color's ID (from the CMAP chunk) is stored in the
  394. FillValue field.  If FillType is equal to FT_OBJECTS, FillValue
  395. contains the ID of a fill pattern defined in a FILL chunk.
  396.  
  397. JoinType determines which style of line join to use when connecting
  398. the edges of line segments.  The field contains one of these four
  399. values:
  400.  
  401.     /* Join types */
  402.     #define JT_NONE       0        /* Don't do line joins */
  403.     #define JT_MITER      1        /* Mitered join */
  404.     #define JT_BEVEL      2        /* Beveled join */
  405.     #define JT_ROUND      3        /* Round join */
  406.  
  407. DashPattern and ArrowHead contain the ID of the dash pattern and arrow
  408. head for this ATTR's objects.  A DashPattern of zero means that there
  409. is no dash pattern so lines will be invisible.  If ArrowHead is 0,
  410. OPLYs have no arrow head.  EdgeValue is the color of the line
  411. segments.  WhichLayer contains the ID of the layer this ATTR's objects
  412. are in.  EdgeThick is the width of this ATTR's line segments.
  413.  
  414.  
  415.  
  416.  
  417. BBOX (0x42424F48)       /* Bounding box of next object in FORM */
  418.  
  419.  
  420. The BBOX chunk supplies the dimensions and position of a bounding box
  421. surrounding the DR2D object that follows this chunk in the FORM.  A
  422. BBOX chunk can apply to a FILL or AROW as well as a DR2D object.  The
  423. BBOX chunk appears just before its DR2D object, FILL, or AROW chunk.
  424.  
  425.     struct BBOXstruct {
  426.         ULONG    ID;
  427.         ULONG    Size;
  428.         IEEE        XMin, YMin,      /* Bounding box of obj. */
  429.                 XMax, YMax;      /* including line width    */
  430.     };
  431.  
  432. In a Cartesian coordinate system, the point (XMin, YMin) is the
  433. coordinate of the lower left hand corner of the bounding box and
  434. (XMax, YMax) is the upper right.  These coordinates take into
  435. consideration the width of the lines making up the bounding box.
  436.  
  437.  
  438. XTRN (0x5854524E)       /* Externally controlled object */
  439.  
  440.  
  441. The XTRN chunk was created primarily to allow ProVector to link DR2D
  442. objects to ARexx functions. 
  443.  
  444.     struct XTRNstruct {
  445.         ULONG   ID;
  446.         ULONG   Size;
  447.         short   ApplCallBacks;             /* From #defines, below */
  448.         short   ApplNameLength;
  449.         char    ApplName[ApplNameLength];  /* Name of ARexx func to call */
  450.     };
  451.  
  452. ApplName[] contains the name of the ARexx script ProVector calls when
  453. the user manipulates the object in some way.  The ApplCallBacks field
  454. specifies the particular action that triggers calling the ARexx script
  455. according to the #defines listed below.
  456.  
  457.     /* Flags for ARexx script callbacks */
  458.     #define    X_CLONE     0x0001    /* The object has been cloned */
  459.     #define    X_MOVE      0x0002    /* The object has been moved */
  460.     #define    X_ROTATE    0x0004    /* The object has been rotated */
  461.     #define    X_RESIZE    0x0008    /* The object has been resized */
  462.     #define    X_CHANGE    0x0010    /* An attribute (see ATTR) of the 
  463.                                         object has changed */
  464.     #define    X_DELETE    0x0020    /* The object has been deleted */
  465.     #define    X_CUT       0x0040    /* The object has been deleted, but
  466.                                         stored in the clipboard */
  467.     #define    X_COPY      0x0080    /* The object has been copied to the
  468.                                         clipboard */
  469.     #define    X_UNGROUP   0x0100    /* The object has been ungrouped */
  470.  
  471.  
  472.  
  473.  
  474.  
  475. For example, given the XTRN object:
  476.  
  477.     FORM xxxx DR2D {
  478.         XTRN xxxx { X_RESIZE | X_MOVE, 10, "Dimension" }
  479.         ATTR xxxx { 0, 0, 1, 0, 0, 0, 0.0 }
  480.         FORM xxxx DR2D {
  481.             GRUP xxxx { 2 }
  482.             STXT xxxx { 0, 0.5, 1.0, 6.0, 5.0, 0.0, 4, "3.0" }
  483.             OPLY xxxx { 2, { 5.5, 5.5, 8.5, 5.5 } }
  484.         }
  485.     }
  486.  
  487. ProVector would call the ARexx script named Dimension if the user
  488. resized or moved this object.  What exactly ProVector sends depends
  489. upon what the user does to the object.  The following list shows what
  490. string(s) ProVector sends according to which flag(s) are set.  The
  491. parameters are described below.
  492.  
  493.     X_CLONE     ``appl CLONE objID dx dy''
  494.     X_MOVE      ``appl MOVE objID dx dy''
  495.     X_ROTATE    ``appl ROTATE objID cx cy angle''
  496.     X_RESIZE    ``appl RESIZE objID cx cy sx sy''
  497.     X_CHANGE    ``appl CHANGE objID et ev ft fv ew jt fn''
  498.     X_DELETE    ``appl DELETE objID''
  499.     X_CUT       ``appl CUT objID''
  500.     X_COPY      ``appl COPY objID''
  501.     X_UNGROUP   ``appl UNGROUP objID''
  502.  
  503. where:
  504.     appl is the name of the ARexx script
  505.     CLONE, MOVE, ROTATE, RESIZE, etc. are literal strings
  506.     objID is the object ID that ProVector assigns to this object
  507.     (dx, dy) is the position offset of the CLONE or MOVE
  508.     (cx, cy) is the point around which the object is rotated or resized
  509.     angle is the angle (in degrees) the object is rotated
  510.     sx and sy are the scaling factors in the horizontal and
  511.       vertical directions, respectively. 
  512.     et is the edge type (the dash pattern index)
  513.     ev is the edge value (the edge color index)
  514.     ft is the fill type
  515.     fv is the fill index
  516.     ew is the edge weight
  517.     jt is the join type
  518.     fn is the font name
  519.  
  520. The X_CHANGE message reflects changes to the attributes found in the
  521. ATTR chunk. 
  522.  
  523. If the user resized the XTRN object shown above by factor of 2,
  524. ProVector would call the ARexx script Dimension like this: 
  525.  
  526.     Dimension RESIZE 1985427 7.0 4.75 2.0 2.0
  527.  
  528.  
  529.  
  530. The Object Chunks
  531.  
  532.  
  533. The following chunks define the objects available in the DR2D FORM.
  534.  
  535.  
  536. VBM  (0x56424D20)       /* Virtual BitMap */
  537.  
  538. The VBM chunk contains the position, dimensions, and file name of an
  539. ILBM image. 
  540.  
  541.  
  542. struct VBMstruct {
  543.     IEEE    XPos, YPos,       /* Virtual coords */
  544.         XSize, YSize,     /* Virtual size */
  545.         Rotation;       /* in degrees */
  546.     USHORT    PathLen;        /* Length of dir path */
  547.     char    Path[PathLen];  /* Null-terminated path of file */
  548. };
  549.  
  550.  
  551. The coordinate (XPos, YPos) is the position of the upper left hand
  552. corner of the bitmap and the XSize and YSize fields supply the x and y
  553. dimensions to which the image should be scaled.  Rotation tells how
  554. many degrees to rotate the ILBM around its upper left hand corner.
  555. ProVector does not currently support rotation of bitmaps and will
  556. ignore this value.  Path contains the name of the ILBM file and may
  557. also contain a partial or full path to the file.  DR2D readers should
  558. not assume the path is correct.  The full path to an ILBM on one
  559. system may not match the path to the same ILBM on another system.  If
  560. a DR2D reader cannot locate an ILBM file based on the full path name
  561. or the file name itself (looking in the current directory), it should
  562. ask the user where to find the image.
  563.  
  564.  
  565.  
  566. CPLY (0x43504C59)       /* Closed polygon */
  567. OPLY (0x4F504C59)       /* Open polygon */
  568.  
  569. Polygons are the basic components of almost all 2D objects in the DR2D
  570. FORM.  Lines, squares, circles, and arcs are all examples of DR2D
  571. polygons.  There are two types of DR2D polygons, the open polygon
  572. (OPLY) and the closed polygon (CPLY).  The difference between a closed
  573. and open polygon is that the computer adds a line segment connecting
  574. the endpoints of a closed polygon so that it is a continuous path.  An
  575. open polygon's endpoints do not have to meet, like the endpoints of a
  576. line segment.
  577.  
  578.     struct POLYstruct {
  579.         ULONG    ID;
  580.         ULONG    Size;
  581.         USHORT    NumPoints;
  582.         IEEE    PolyPoints[2*NumPoints];
  583.     };
  584.  
  585. The NumPoints field contains the number of points in the polygon and
  586. the PolyPoints array contains the (X, Y) coordinates of the points of
  587. the non-curved parts of polygons.  The even index elements are X
  588. coordinates and the odd index elements are Y coordinates.
  589.  
  590. [Figure 3 - Bezier curves]
  591.  
  592. DR2D uses Bezier cubic sections, or cubic splines, to describe curves
  593. in polygons.  A set of four coordinates (P1 through P4) defines the
  594. shape of a cubic spline.  The first coordinate (P1) is the point where
  595. the curve begins.  The line from the first to the second coordinate
  596. (P1 to P2) is tangent to the curve at the first point.  The line from
  597. P3 to P4 is tangent to the cubic section, where it ends at P4.
  598.  
  599. The coordinates describing the cubic section are stored in the
  600. PolyPoints[] array with the coordinates of the normal points.  DR2D
  601. inserts an indicator point before a set of cubic section points to
  602. differentiate a normal point from the points that describe a curve.
  603. An indicator point has an X value of 0xFFFFFFFF.  The indicator
  604. point's Y value is a bit field.  If this bit field's low-order bit is
  605. set, the points that follow the indicator point make up a cubic
  606. section.
  607.  
  608. The second lowest order bit in the indicator point's bit field is the
  609. MOVETO flag.  If this bit is set, the point (or set of cubic section
  610. points) starts a new polygon, or subpolygon.  This subpolygon will
  611. appear to be completely separate from other polygons but there is an
  612. important connection between a polygon and its subpolygon.
  613. Subpolygons make it possible to create holes in polygons.  An example
  614. of a polygon with a hole is the letter ``O''.  The ``O'' is a filled
  615. circular polygon with a smaller circular polygon within it.  The
  616. reason the inner polygon isn't covered up when the outer polygon is
  617. filled is that DR2D fills are done using the even-odd rule.
  618.  
  619. The even-odd rule determines if a point is ``inside'' a polygon by
  620. drawing a ray outward from that point and counting the number of path
  621. segments the ray crosses.  If the number is even, the point is outside
  622. the object and shouldn't be filled.  Conversely, an odd number of
  623. crossings means the point is inside and should be filled.  DR2D only
  624. applies the even-odd rule to a polygon and its subpolygons, so no
  625. other objects are considered in the calculations.
  626.  
  627. Taliesin, Inc. supplied the following algorithm to illustrate the
  628. format of DR2D polygons.  OPLYs, CPLYs, AROWs, and ProVector's outline
  629. fonts all use the same format:
  630.  
  631.  
  632.         typedef union {
  633.             IEEE num;
  634.             LONG bits;
  635.         } Coord;
  636.  
  637.         #define INDICATOR       0xFFFFFFFF
  638.         #define IND_SPLINE      0x00000001
  639.         #define IND_MOVETO      0x00000002
  640.  
  641.         /* A common pitfall in attempts to support DR2D has
  642.                 been to fail to recognize the case when an
  643.                 INDICATOR point indicates the following
  644.                 coordinate to be the first point of BOTH a
  645.                 Bezier cubic and a sub-polygon, ie. the
  646.                 value of the flag = (IND_CURVE | IND_MOVETO) */
  647.  
  648.         Coord   Temp0, Temp1;
  649.         int     FirstPoint, i, Increment;
  650.  
  651.         /* Initialize the path */
  652.         NewPath();
  653.         FirstPoint = 1;
  654.  
  655.         /* Draw the path */
  656.         i = 0;
  657.         while( i < NumPoints ) {
  658.             Temp0.num = PolyPoints[2*i];    Temp1.num = PolyPoints[2*i + 1];
  659.             if( Temp0.bits == INDICATOR ) {
  660.                 /* Increment past the indicator */
  661.                 Increment = 1;
  662.                 if( Temp1.bits & IND_MOVETO ) {
  663.                     /* Close and fill, if appropriate */
  664.                     if( ID == CPLY ) {
  665.                         FillPath();
  666.                     }
  667.                     else {
  668.                         StrokePath();
  669.                     }
  670.  
  671.                     /* Set up the new path */
  672.                     NewPath();
  673.                     FirstPoint = 1;
  674.                 }
  675.                 if( Temp1.bits & IND_CURVE ) {
  676.                     /* The next 4 points are Bezier cubic control points */
  677.                     if( FirstPoint )
  678.                         MoveTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
  679.                     else
  680.                         LineTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
  681.                     CurveTo(    PolyPoints[2*i + 4], PolyPoints[2*i + 5],
  682.                                 PolyPoints[2*i + 6], PolyPoints[2*i + 7],
  683.                                 PolyPoints[2*i + 8], PolyPoints[2*i + 9] );
  684.                     FirstPoint = 0;
  685.                     /* Increment past the control points */
  686.                     Increment += 4;
  687.                 }
  688.             }
  689.             else {
  690.                 if( FirstPoint )
  691.                     MoveTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
  692.                 else
  693.                     LineTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
  694.                 FirstPoint = 0;
  695.  
  696.                 /* Increment past the last endpoint */
  697.                 Increment = 1;
  698.             }
  699.  
  700.             /* Add the increment */
  701.             i += Increment;
  702.         }
  703.  
  704.         /* Close the last path */
  705.         if( ID == CPLY ) {
  706.             FillPath();
  707.         }
  708.         else {
  709.             StrokePath();
  710.         }
  711.  
  712.  
  713.  
  714. GRUP (0x47525550)       /* Group */
  715.  
  716. The GRUP chunk combines several DR2D objects into one.  This chunk is
  717. only valid inside nested DR2D FORMs, and must be the first chunk in
  718. the FORM.
  719.  
  720.     struct GROUPstruct {
  721.         ULONG    ID;
  722.         ULONG    Size;
  723.         USHORT    NumObjs;
  724.     };
  725.  
  726. The NumObjs field contains the number of objects contained in this
  727. group.  Note that the layer of the GRUP FORM overrides the layer of
  728. objects within the GRUP.  The following example illustrates the layout
  729. of the GRUP (and FILL) chunk.
  730.  
  731.        FORM { DR2D              /* Top-level drawing... */
  732.                 DRHD { ... }    /* Confirmed by presence of DRHD chunk */
  733.                 CMAP { ... }    /* Various other things... */
  734.                 FONS { ... }
  735.                 FORM { DR2D             /* A nested form... */
  736.                         FILL { 1 }      /* Ah!  The fill-pattern table */
  737.                         CPLY { ... }    /* with only 1 object */
  738.                 }
  739.                 FORM { DR2D             /* Yet another nested form */
  740.                         GRUP { ..., 3 } /* Ah! A group of 3 objects */
  741.                         TEXT { ... }
  742.                         CPLY { ... }
  743.                         OPLY { ... }
  744.                 }
  745.                 FORM { DR2D             /* Still another nested form */
  746.                         GRUP { ..., 2 } /* A GRUP with 2 objects */
  747.                         OPLY { ... }
  748.                         TEXT { ... }
  749.                 }
  750.         }
  751.  
  752.  
  753.  
  754. STXT (0x53545854)           /* Simple text */
  755.  
  756. The STXT chunk contains a text string along with some information on
  757. how and where to render the text. 
  758.  
  759.     struct STXTstruct {
  760.         ULONG    ID;
  761.         ULONG    Size;
  762.         UBYTE    Pad0;        /* Always 0 (for future expansion) */
  763.         UBYTE    WhichFont;      /* Which font to use */
  764.         IEEE    CharW, CharH,      /* W/H of an individual char */
  765.             BaseX, BaseY,      /* Start of baseline */
  766.             Rotation;          /* Angle of text (in degrees) */
  767.         USHORT    NumChars;
  768.         char    TextChars[NumChars];
  769.     };
  770.  
  771. The text string is in the character array, TextChars[].  The ID of the
  772. font used to render the text is WhichFont.  The font's ID is set in a
  773. FONS chunk.  The starting point of the baseline of the text is (BaseX,
  774. BaseY).  This is the point around which the text is rotated.  If the
  775. Rotation field is zero (degrees), the text's baseline will originate
  776. at (BaseX, BaseY) and move to the right.  CharW and CharH are used to
  777. scale the text after rotation.  CharW is the average character width
  778. and CharH is the average character height.  The CharW/H fields are
  779. comparable to an X and Y font size.  
  780.  
  781.  
  782.  
  783. TPTH (0x54505448)         /* A text string along a path */
  784.  
  785. This chunk defines a path (polygon) and supplies a string to render
  786. along the edge of the path.
  787.  
  788.     struct TPTHstruct {
  789.         ULONG   ID;
  790.         ULONG   Size;
  791.         UBYTE   Justification;    /* see defines, below */
  792.         UBYTE   WhichFont;        /* Which font to use */
  793.         IEEE    CharW, CharH;    /* W/H of an individual char    */
  794.         USHORT  NumChars;       /* Number of chars in the string */
  795.         USHORT  NumPoints;      /* Number of points in the path */
  796.         char    TextChars[NumChars];/* PAD TO EVEN #! */
  797.         IEEE    Path[2*NumPoints];  /* The path on which the text lies */
  798.     };
  799.  
  800. WhichFont contains the ID of the font used to render the text.
  801. Justification controls how the text is justified on the line.
  802. Justification can be one of the following values:
  803.  
  804.     #define J_LEFT         0x00    /* Left justified */
  805.     #define J_RIGHT        0x01       /* Right justified */
  806.     #define J_CENTER      0x02    /* Center text */
  807.     #define J_SPREAD      0x03    /* Spread text across path */
  808.  
  809. CharW and CharH are the average width and height of the font
  810. characters and are akin to X and Y font sizes, respectively.  A
  811. negative FontH implies that the font is upsidedown.  Note that CharW
  812. must not be negative.  NumChars is the number of characters in the
  813. TextChars[] string, the string containing the text to be rendered.
  814. NumPoints is the number of points in the Path[] array.  Path[] is the
  815. path along which the text is rendered.  The path itself is not
  816. rendered.  The points of Path[] are in the same format as the points
  817. of a DR2D polygon.
  818.  
  819.  
  820.  
  821. A Simple DR2D Example
  822.  
  823. Here is a (symbolic) DR2D FORM:
  824.  
  825.     FORM { DR2D
  826.             DRHD 16 { 0.0, 0.0, 10.0, 8.0 }
  827.             CMAP  6 { 0,0,0, 255,255,255 }
  828.             FONS  9 { 1, 0, 1, 0, "Roman" } 0
  829.             DASH 12 { 1, 2, {1.0, 1.0} }
  830.             ATTR 14 { 0, 0, 1, 0, 0, 0, 0, 0.0 }
  831.             BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
  832.             FORM { DR2D
  833.                   GRUP  2 { 2 }
  834.                   BBOX 16 { 3.0, 4.0, 7.0, 5.0 }
  835.                   STXT 36 { 0,1, 0.5, 1.0, 3.0, 5.0, 0.0, 12, "Hello, World" }
  836.                   BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
  837.                   OPLY 42 { 5, {2.0,2.0, 8.0,2.0, 8.0,6.0, 2.0,6.0, 2.0,2.0 }
  838.             }
  839.     }
  840.  
  841.  
  842. [Figure 4 - Simple DR2D drawing]
  843.  
  844.  
  845. The OFNT FORM
  846.  
  847.  
  848. OFNT    (0x4F464E54)       /* ID of outline font file */
  849.  
  850. ProVector's outline fonts are stored in an IFF FORM called OFNT.  This
  851. IFF is a separate file from a DR2D.  DR2D's FONS chunk refers only to
  852. fonts defined in the OFNT form.
  853.  
  854.  
  855. OFHD    (0x4F464844)       /* ID of OutlineFontHeaDer */
  856.  
  857. This chunk contains some basic information on the font.
  858.  
  859.     struct OFHDstruct {
  860.         char   FontName[32];   /* Font name, null padded */
  861.         short  FontAttrs;       /* See FA_*, below */
  862.         IEEE   FontTop,       /* Typical height above baseline */
  863.            FontBot,        /* Typical descent below baseline */
  864.            FontWidth;      /* Typical width, i.e. of the letter O */
  865.     };
  866.  
  867.     #define FA_BOLD          0x0001
  868.     #define FA_OBLIQUE       0x0002
  869.     #define FA_SERIF    0x0004
  870.  
  871. The FontName field is a NULL terminated string containing the name of
  872. this font.  FontAttrs is a bit field with flags for several font
  873. attributes.  The flags, as defined above, are bold, oblique, and
  874. serif.  The unused higher order bits are reserved for later use.  The
  875. other fields describe the average dimensions of the characters in this
  876. font.  FontTop is the average height above the baseline, FontBot is
  877. the average descent below the baseline, and FontWidth is the average
  878. character width.
  879.  
  880.  
  881. KERN    (0x4B45524C)       /* Kerning pair */
  882.  
  883. The KERN chunk describes a kerning pair.  A kerning pair sets the
  884. distance between a specific pair of characters.  
  885.  
  886. struct KERNstruct {
  887.     short   Ch1, Ch2;         /* The pair to kern (allows for 16 bits...) */
  888.     IEEE    XDisplace,      /* Amount to displace -left +right */
  889.         YDisplace;      /* Amount to displace -down +up */
  890. };
  891.  
  892. The Ch1 and Ch2 fields contain the pair of characters to kern.  These
  893. characters are typically stored as ASCII codes.  Notice that OFNT
  894. stores the characters as a 16-bit value.  Normally, characters are
  895. stored as 8-bit values.  The wary programmer will be sure to cast
  896. assigns properly to avoid problems with assigning an 8-bit value to a
  897. 16-bit variable.  The remaining fields, XDisplace and YDisplace,
  898. supply the baseline shift from Ch1 to Ch2.
  899.  
  900.  
  901.  
  902.  
  903. CHDF    (0x43484446)      /* Character definition */
  904.  
  905. This chunk defines the shape of ProVector's outline fonts.  
  906.  
  907. struct CHDFstruct {
  908.     short   Ch;        /* The character we're defining (ASCII) */
  909.     short   NumPoints;  /* The number of points in the definition */
  910.     IEEE    XWidth,     /* Position for next char on baseline - X */
  911.             YWidth;    /* Position for next char on baseline - Y */
  912.  /* IEEE    Points[2*NumPoints]*/        /* The actual points */
  913. };
  914.  
  915.  
  916. #define    INDICATOR       0xFFFFFFFF       /* If X == INDICATOR, Y is an action */
  917. #define    IND_SPLINE      0x00000001       /* Next 4 pts are spline control pts */
  918. #define    IND_MOVETO      0x00000002       /* Start new subpoly */
  919. #define IND_STROKE      0x00000004       /* Stroke previous path */
  920. #define IND_FILL        0x00000008       /* Fill previous path */
  921.  
  922. Ch is the value (normally ASCII) of the character outline this chunk
  923. defines.  Like Ch1 and Ch2 in the KERN chunk, Ch is stored as a 16-bit
  924. value.  (XWidth,YWidth) is the offset to the baseline for the
  925. following character.  OFNT outlines are defined using the same method
  926. used to define DR2D's polygons (see the description of OPLY/CPLY for
  927. details).
  928.  
  929. Because the OFNT FORM does not have an ATTR chunk, it needed an
  930. alternative to make fills and strokes possible.  There are two extra
  931. bits used in font indicator points not found in polygon indicator
  932. points, the IND_STROKE and IND_FILL bits (see defines above).  These
  933. two defines describe how to render the current path when rendering
  934. fonts.
  935.  
  936. The current path remains invisible until the path is either filled
  937. and/or stroked.  When the IND_FILL bit is set, the currently defined
  938. path is filled in with the current fill pattern (as specified in the
  939. current ATTR chunk).  A set IND_STROKE bit indicates that the
  940. currently defined path itself should be rendered.  The current ATTR's
  941. chunk dictates the width of the line, as well as several other
  942. attributes of the line.  These two bits apply only to the OFNT FORM
  943. and should not be used in describing DR2D polygons.
  944.  
  945.  
  946.