[comp.sys.amiga.tech] IFF form for 2D drawings

cunniff@hpfcdc.HP.COM (Ross Cunniff) (08/06/88)

OK, here it comes again...
This is a revised proposal for a standard IFF two-dimensional drawing
format (named DR2D).  The things that have changed include:

	1. Objects now have their points relative to an
	   X,Y position; they also have bounding information.
	   stored with them (for efficient clipping/rendering).

	2. Each object now has a 16-bit layer ID in it.

	3. The original 16 cross-hatch patterns have been replaced
	   with a more generalized object-oriented fill.
	
	4. Probably some other details I've forgotten.

Things I have NOT changed include:

	1. I still use single-precision IEEE floating point
	   numbers for coordinates instead of scaled integers.
	
	2. It is not a full-blown programming language like
	   PostScript.
	
	3. Rectangles may still be rotated.

	4. I haven't added a dimension object; my program doesn't
	   yet support such beasties.  If you have a definition
	   that fits in the general structure of DR2D, feel free
	   to post a description of it and I'll consider including
	   it.

Comments and critiques specifically about the format are welcome
but I would prefer that discussion about the relative merits of
PostScript, NALPS, GKS, etc. happen under a different title/notes-string.
This format is SPECIFICALLY intended to be the save-file format of
a 2-D drawing program that I intend to have on the market by December;
in addition, I think that it is powerful enough to become a standard
for the emerging CAD and desktop publishing markets.

				Ross Cunniff
				Hewlett-Packard Colorado Language Lab
				...{ucbvax,hplabs}!hpda!cunniff
				cunniff%hpda@hplabs.ARPA

---cut here------------------cut here----------------------cut here---
/* SCCS ID @(#)dr2d	1.5 88/08/05 */
The following is a proposed format of the DR2D IFF FORM file designed for
use with 2-dimensional CAD programs.  Each chunk is described by
first giving the chunk ID (both in ASCII and in hex) and then giving
the structure associated with the chunk, as well as any extra
definitions that make sense.  Coordinates are specified in IEEE
format (see note 1 for a description of the IEEE format).  Note
that most chunks have both a chunk Size and an object Count.  I
know this is redundant; however, this allows the data structures
to be extended in a compatible manner if it should become necessary
in the far future.  Please address questions and comments to:

			Ross Cunniff
			...{ucbvax,hplabs}!hpda!cunniff
			cunniff%hpda@hplabs.ARPA
			(303)-229-4644 -or- (303)-223-7569



FORM (0x464F524D)	/* All drawings are a FORM */

	struct FORMstruct {
	    LONG	ID;
	    LONG	Size;		/* Total size of the file	*/
	};


DR2D (0x44523244)	/* ID of 2D drawing */

DRHD (0x44524844)	/* Drawing header */

	struct DRHDstruct {
	    LONG	ID;
	    LONG	Size;		/* Always 16 */
	    IEEE	p_xmin, p_ymin,	/* Minimum and maximum */
			p_xmax, p_ymax;	/*   coordinates of the drawing area */
	};

CMAP (0x434D4150)	/* Color map */

	struct CMAPstruct {
	    LONG	ID;
	    LONG	Size;		/* 2 + 3*NumColor + NumColor%2 */
	    SHORT	NumColor;	/* Typically 256 */
	    UBYTE	ColorMap[NumColor][3];
	    UBYTE	PAD[NumColor%1];/* Padding to make Size even */
	};

PATT (0x50415454)	/* Fill Patterns */

	struct PATTstruct {
	    LONG	ID;
	    LONG	Size;		/* 2 + 64*NumPatts */
	    SHORT	NumPatts;	/* Typically 16 */
	    UBYTE	Patterns[NumPatts][8][8];
	};

	/* Each pixel in the 8x8 pattern may be a different color
	   from the palette.  Note that these colors may be
	   approximated by any given output device. */

FONT (0x464F4E54)	/* Font table */

	struct FONTstruct {
	    LONG	ID;
	    LONG	Size;		/* 2 + 128*NumFonts */
	    SHORT	NumFonts;
	    CHAR	FontNames[NumFonts][128];
	};
	/* FontNames is an array containing the names of all the fonts
	   used in this drawing. */

FILL (0x46494C4C)	/* Line fill pattern table */

	typedef struct {
	    SHORT	NumLines;
	    IEEE	Width, Height;
	    IEEE	XMag, YMag;
	    IEEE	EndPoints[4*NumLines];
	} LineFillPat;

	struct FILLstruct {
	    LONG	ID;
	    LONG	Size;		/* 2 + sum(sizeof(Patterns)) */
	    SHORT	NumPatts;	/* Typically 16 */
	    LineFillPat	Patterns[NumPatts];
	};

	/* A line fill pattern consists of an arbitrary number
	   of line segments.  The segments have coordinates
	   ranging from (0.0,0.0) to (Width,Height), and the
	   pattern is tiled by first multiplying the coordinates
	   by (XMag, YMag) and then repeating the pattern across
	   the filled object every (XMag*Width,YMag*Height) interval. */


DSYM (0x4453594D)	/* Define a symbol */

	struct DSYMstruct {
	    LONG	ID;
	    LONG	Size;
	    SHORT	SymbID;			/* Unique ID for this symbol */
	    SHORT	NumObjs;
	    UBYTE	SymbChunk[Size-4];	/* See note 5 */
	};

SYMB (0x53594D42)	/* Use a symbol */
	struct SYMBstruct {
	    LONG	ID;
	    LONG	Size;			/* Always 22	*/
	    SHORT	SymbID;			/* Which symbol	*/
	    USHORT	WhichLayer;		/* Which layer it's in */
	    IEEE	XPos, YPos,		/* Where to put it */
			XMag, YMag,		/* How big should it be? */
			Rotation;		/* Angle of rotation */
	};

CPLY (0x43504C59)	/* Closed polygon */
OPLY (0x4F504C59)	/* Open polygon, i.e. line segments */
CSPL (0x4353504C)	/* Closed interpolating B-Spline */
OSPL (0x4353504C)	/* Open interpolating B-Spline */
RECT (0x52454354)	/* Rectangle (should have 4 vertices, so that they */
			/* can be rotated) */
ELLP (0x454C4C50)	/* Ellipse (should have 3 vertices [see note 2]) */
CBEZ (0x4340455A)	/* Closed bezier splines (see note 3) */
OBEZ (0x4F40455A)	/* Open bezier splines (see note 3) */

	/* Various fill types */
	#define F_NONE		0	/* No fill			*/
	#define F_COLOR		1	/* Fill with color from palette */
	#define F_BITMAP	2	/* Fill with bitmap pattern	*/
	#define F_LINES		3	/* Fill with lines [see note 4]) */

	/* Various edge types */
	#define E_NONE		0	/* No edges		*/
	#define E_SOLID		1	/* Solid (thin) lines	*/
	#define E_DASH		2	/* Dashed lines		*/
	#define E_DOT		3	/* Dotted lines		*/
	#define E_DOT_DASH	4	/* dot-dash-dot-dash	*/
	#define E_THICK		5	/* Thick line		*/

	typedef struct {
	    UBYTE	FillType;	/* One of F_*, above	*/
	    UBYTE	FillValue;	/* See note 4		*/
	    UBYTE	EdgeType;	/* One of E_*, above	*/
	    UBYTE	EdgeValue;	/* Edge color index	*/
	    USHORT	WhichLayer;	/* Which layer it's in	*/
	    IEEE	EdgeThick;	/* Line width, if E_THICK */
	    IEEE	XPos, YPos,	/* Where to place the obj. */
			Width, Height;	/* Bounding box of obj.	*/
	} ObjHdr;	/* Size == 26 */

	struct POLYstruct {
	    LONG	ID;
	    LONG	Size;		/* 28 + 4*NumCoords */
	    ObjHdr	Styles;
	    SHORT	NumCoords;
	    IEEE	PolyPoints[NumCoords]; /* XY coords of vertices */
	};



SGRP (0x53475250)	/* Strong group; all objects in group have same color */
WGRP (0x57475250)	/* Weak group; objects retain individual color */

	struct GROUPstruct {
	    LONG	ID;
	    LONG	Size;
	    ObjHdr	Styles;		/* Styles for strong group */
	    SHORT	NumObjs;
	    UBYTE	GroupChunk[Size-14];	/* See note 5 */
	};


TEXT (0x54455854)	/* A text string */

	struct TEXTstruct {
	    LONG	ID;
	    LONG	Size;		/* 34 + NumChars + NumChars%2 */
	    ObjHdr	Styles;
	    SHORT	WhichFont;	/* Index into font table */
	    IEEE	CharW, CharH,	/* W/H of an individual char	*/
			Rotation;	/* Angle of text (in radians) */
	    SHORT	NumChars;
	    char	TextChars[NumChars];
	    UBYTE	PAD[NumChars%2];/* Padding to make Size even */
	};

The following is a hexdump of a sample DR2D file, giving you some idea of
how this is all put together:

00000000:  46 4f 52 4d 00 00 01 bc 44 52 32 44 44 52 48 44    FORM....DR2DDRHD
00000010:  00 00 00 10 00 00 00 00 00 00 00 00 41 20 00 00    ............A ..
00000020:  41 00 00 00 43 4d 41 50 00 00 00 1a 00 08 00 00    A...CMAP........
00000030:  00 00 00 ff 00 ff 00 00 ff ff ff 00 00 ff 00 ff    ................
00000040:  ff ff 00 ff ff ff 50 41 54 54 00 00 00 42 00 01    ......PATT...B..
00000050:  00 01 00 01 00 01 00 01 01 00 01 00 01 00 01 00    ................
00000060:  00 01 00 01 00 01 00 01 01 00 01 00 01 00 01 00    ................
00000070:  00 01 00 01 00 01 00 01 01 00 01 00 01 00 01 00    ................
00000080:  00 01 00 01 00 01 00 01 01 00 01 00 01 00 01 00    ................
00000090:  46 4f 4e 54 00 00 00 82 00 01 73 69 6d 70 6c 65    FONT......simple
000000a0:  78 20 72 6f 6d 61 6e 00 00 00 00 00 00 00 00 00    x roman.........
000000b0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
000000c0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
000000d0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
000000e0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
000000f0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
00000100:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
00000110:  00 00 00 00 00 00 00 00 00 00 46 49 4c 4c 00 00    ..........FILL..
00000120:  00 24 00 01 00 01 3f 80 00 00 3f 80 00 00 3f 80    .$....?...?...?.
00000130:  00 00 3f 80 00 00 00 00 00 00 3f 00 00 00 3f 80    ..?.......?...?.
00000140:  00 00 3f 00 00 00 54 45 58 54 00 00 00 32 00 00    ..?...TEXT...2..
00000150:  01 01 00 00 00 00 00 00 40 40 00 00 40 00 00 00    ........@@..@...
00000160:  40 c0 00 00 40 00 00 00 00 00 3f 80 00 00 40 00    @...@.....?...@.
00000170:  00 00 00 00 00 00 00 07 66 6f 6f 62 61 72 00 00    ........foobar..
00000180:  52 45 43 54 00 00 00 3c 00 00 03 01 00 00 00 00    RECT...<........
00000190:  00 00 40 00 00 00 3f 80 00 00 41 00 00 00 40 80    ..@...?...A...@.
000001a0:  00 00 00 04 40 00 00 00 3f 80 00 00 40 00 00 00    ....@...?...@...
000001b0:  41 10 00 00 40 c0 00 00 41 10 00 00 40 c0 00 00    A...@...A...@...
000001c0:  3f 80 00 00                                        ?...

The picture should look something like this:


			.................
			.		.
			.    foobar	.
			.		.
			.................

NOTE 1:	IEEE represents a single-precision IEEE floating point number.
	These numbers consist of 32 bits, arranged as follows:

	+---------------+---------------+---------------+---------------+
	|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|
	+---------------+---------------+---------------+---------------+
	 31	      24 23           16 15            8 7             0
	
	where
		s	is the sign bit of the entire number.  If this
			bit is '1', the number is negative.  If '0',
			the number is positive.
		e	is the 8-bit exponent, in excess-127 form.
			This is the power of two to which the mantissa
			should be raised before using the number
			in calculations.  Excess-127 means that
			127 is added to the exponent before packing
			it into the number. An exponent of 0 here means
			the real exponent is actually -127.  A value
			of 127 means the exponent is actually 0.
			A value of 255 means the exponenent is actually
			128.
		m	is the 23-bit mantissa.  A leading binary
			1 is assumed.  This means that the mantissa
			may vary from 1.0000000 to 1.999999...
	
	The value 0.0000000 is represented by all bits being cleared
	to zero.  Note that on many computers, the natural format
	of single-precision floating point numbers *IS* IEEE.  This
	is true of the Amiga.  There are system calls to transform
	IEEE numbers to and from Motorola FFP numbers, should your
	application require them.

NOTE 2: For an Ellipse, the 3 vertices are as follows:

	XPos+CX, YPos+CY	The center of the ellipse
	XPos+AX, YPos+AY	A point at the intersection
				of the major axis and the ellipse
	XPos+BX, YPos+BY	A point at the intersection of
				the minor axis and the ellipse

NOTE 3: For a Bezier spline, the vertices are defined as follows:

	typedef union {
	    IEEE num;
	    LONG bits;
	} Marker;

	#define LINETO		0xFFFFFFFF
	#define SPLINETO	0xFFFFFFFE

	Marker Temp;

	MoveTo( XPos + PolyPoints[0], YPos + PolyPoints[1] );
	for( i = 2; i < NumCoords; ) {
	    Temp.num = PolyPoints[i];
	    switch( Temp.bits ) {
		case LINETO :
		    DrawTo( XPos + PolyPoints[i+1], YPos + PolyPoints[i+2] );
		    i += 3;
		    break;
		case SPLINETO :
		    SplineTo(	XPos+PolyPoints[i+1], YPos+PolyPoints[i+2],
				XPos+PolyPoints[i+3], YPos+PolyPoints[i+4],
				XPos+PolyPoints[i+5], YPos+PolyPoints[i+6] );
		    i += 7;
		    break;
	    }
	}
	if( ID == CBEZ ) {
	    LineTo( XPos+PolyPoints[0], YPos+PolyPoints[1] );
	    FillPath();
	}
	else {
	    TracePath();
	}


NOTE 4: The actual fill of one of these objects is done as follows:

	switch( FillType ) {
	    case F_NONE :
		SetNoFill();
		break;
	    case F_COLOR :
		SetSolidFill( Palette[FillValue] );
		break;
	    case F_BITMAP :
		SetSolidFill( Bitmaps[FillValue] );
		break;
	    case F_LINES :
		SetLineFill( FillPats[FillValue] );
		break;
	   }

	Note also that on most pen plotters, F_LINES and F_NONE
	are the only meaningful fills.

NOTE 5: The data in a DSYM, SGRP or WGRP chunk is a series of nested object
	chunks.  All object chunks except DSYM, CMAP, PATT, FILL, and FONT are
	allowed in a DSYM, SGRP or WGRP.

peter@sugar.uu.net (Peter da Silva) (08/08/88)

In article ... cunniff@hpfcdc.HP.COM (Ross Cunniff) writes:
> 	3. Rectangles may still be rotated.

I don't see why you're specifically singling out rectangles here. If course
rectangles should be rotatable... in fact *any* object should have a rotation
angle as part of its definition. A rectangle should be two points and an
angle. An ellipse should be a major and minor axis, a center point, and a
rotation angle. And so on...
-- 
		Peter da Silva  `-_-'  peter@sugar.uu.net
		 Have you hugged  U  your wolf today?

cunniff@hpfcdc.HP.COM (Ross Cunniff) (08/08/88)

In article <2412@sugar.uu.net> peter@sugar.uu.net (Peter da Silva) writes:
>> 	3. Rectangles may still be rotated.
>I don't see why you're specifically singling out rectangles here. 

It was a (feeble) attempt at a joke.  The last time we went through
this, 50% of the discussion was about PostScript, and 50% about whether
rectangles should be rotatable...

>Of course
>rectangles should be rotatable... in fact *any* object should have a rotation
>angle as part of its definition. A rectangle should be two points and an
>angle. An ellipse should be a major and minor axis, a center point, and a
>rotation angle. And so on...

Actually, every object *is* rotatable; simply rotate the actual points
of the data.  Exceptions include text and symbols, which have explicit
rotation angles in their definitions since their data is not manipulable
in such a fashion.  My rationale for precomputing the rotation is that
it is faster to render objects whose position and rotation are precomputed
rather than rotating and traslating them on the fly (although I am
open to a convicing argument in favor of including a rotation angle
for the objects...)


>		Peter da Silva  `-_-'  peter@sugar.uu.net
>		 Have you hugged  U  your wolf today?

					Ross Cunniff
					Hewlett-Packard Colorado Language Lab
					...{ucbvax,hplabs}!hpda!cunniff
					cunniff%hpda@hplabs.ARPA

bmacintyre@tiger.waterloo.edu (Blair MacIntyre) (08/09/88)

Quite often, rotations are implemented as modifiers to existing shapes.
That is, a rectangle rotated by 45 degrees becomes something like:
<45 deg rotation><data structure for rectangle>.  Quite often, other
transformations, such as scaling, shearing and translations are also
included as modifiers.  The advantage of doing things this way is that
it generalizes better if you have composite objects (ie an object
consisting of a 3 rectangles and an ellipse).

I realize that this is probably not completely relevant, however, I
just thought I'd add my two cents.

ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (08/09/88)

In article <11640003@hpfcdc.HP.COM> cunniff@hpfcdc.HP.COM (Ross Cunniff) writes:
>CMAP (0x434D4150)	/* Color map */
>
>	struct CMAPstruct {
>	    LONG	ID;
>	    LONG	Size;		/* 2 + 3*NumColor + NumColor%2 */
>>>>	    SHORT	NumColor;	/* Typically 256 */
>	    UBYTE	ColorMap[NumColor][3];
>	    UBYTE	PAD[NumColor%1];/* Padding to make Size even */
>	};
>
	I object to this, largely on principle.  Although this flavor of
CMAP chunk will only appear in a DR2D FORM, we already have a well-known and
-advertised (and -coded-for) CMAP chunk for ILBM FORMs.  I would suggest
using the ILBM CMAP chuck format instead, since using your own could very
well lead to some degree of confusion, particularly if you ever decide to
import ILBMs into your drawings in some way (perhaps as a fill pattern?).

	Also, I think you have the semantics of IFF a bit wrong.  "Size" is
the size of the chunk, sans pad byte.  IFF will enforce the pad byte for
you.  Therefore, it's unnecessary to specify it in your chunk specification.

	Also, IFF enforces the ID and ChunkSize stuff, so that needn't be in
your chunk specification, either.

	Stu Ferguson and I have been studying IFF for some time now (which
is why I'm picking at your semantics), in an effort to beat it into
submission.  I think we're winning....

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape	INET: well!ewhac@ucbvax.Berkeley.EDU
 \_ -_		Recumbent Bikes:	UUCP: pacbell > !{well,unicom}!ewhac
O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
"Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

cmcmanis%pepper@Sun.COM (Chuck McManis) (08/10/88)

In article <6778@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>	I object to this, largely on principle.  Although this flavor of
>CMAP chunk will only appear in a DR2D FORM, we already have a well-known and
>-advertised (and -coded-for) CMAP chunk for ILBM FORMs.  

Leo, let us be serious here. RULE #1 for ILBM is :
	If you don't understand the FORM then don't look inside it.

The simple reason being, that like any modular programming language the
scope of a chunk is limited to the FORM it is contained in. By forcing
_this_ CMAP chunk to look like an ILBM chunk you imply that all chunks
with the same name are the same chunk. And this must not be true for IFF
to work. The beauty of this standard is that when you define your form
(or a LIST if you want to screw around with FORM's) what is contained within
that LIST or FORM you can change to your heart's content and still be 
compatibile with all well behaved IFF readers in the world.

--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.

charles@hpcvca.HP.COM (Charles Brown) (08/10/88)

> Quite often, rotations are implemented as modifiers to existing shapes.
> That is, a rectangle rotated by 45 degrees becomes something like:
> <45 deg rotation><data structure for rectangle>.

Interesting...  This would affect how much space that would be
required for storage and archival.  That is, I assume the data
<structure for rectangle with rotation always included> would be larger
that the <structure for rotation> + the <structure for rectangle> but
smaller that the <structure for rectangle>.  Thus this proposal would
result in smaller data bases if most rectangles are not rotated.
Conversely, this proposal would result in larger data bases if most
rectangles are rotated.  So the application would determine the best
choice here.  Isn't that usually the case?
	Charles Brown		charles%hpcvca@hplabs.hp.com

shf@well.UUCP (Stuart H. Ferguson) (08/11/88)

+--- Ross Cunniff writes about a possible IFF standard for drawings
| OK, here it comes again...

I guess I missed the first one...

| This is a revised proposal for a standard IFF two-dimensional drawing
| format (named DR2D).  The things that have changed include:

How about R2D2 ? :-)

| Comments and critiques specifically about the format are welcome
[...]
| This format is SPECIFICALLY intended to be the save-file format of
| a 2-D drawing program that I intend to have on the market by December;
| in addition, I think that it is powerful enough to become a standard
| for the emerging CAD and desktop publishing markets.

These are two very different problems.  A format for your own purposes 
is one matter, a standard format is another entirely.  I can't say 
what's appropriate to your application, so I'll just address the concept 
of this being an IFF standard.

IFF has a kind of underlying philosophy that many would-be standards
ignore.  The basic thing is that the format is to be used for data 
"Interchange," which means that lots of different programs with lots of 
different purposes may read or write this data.  An IFF format must be
carefully designed so that the data is stored in a way that is as
independent of the application and as close to its pure abstract form as
possible.  The goals of programmer for a specific application program
may conflict with this philosophy since the programmer wants the file
format to closely match the internal design of his program.  Whereas
this makes things easy for him, it often makes for a poor standard. 

If you just want this as just format for your own files, fine, but don't
make any pretenses about this being a "standard."  If you want this to
be a good standard, expect to do some extra work. 

Specific comments:

|         1. Objects now have their points relative to an
|            X,Y position; they also have bounding information.
|            stored with them (for efficient clipping/rendering).
             ^^^^^^^^^^^^^^^^
Lousy idea.  One of the main reasons the Draw Plus format is so klunky
and bulky is that the definition for each object explicitly states its
bounding rectangle.  If you need this info, you can derive it -- don't
include it in the file. 

|         2. Each object now has a 16-bit layer ID in it.

This sounds wrong for IFF.  How about providing a LYID property chunk
with the layer ID in it and storing the different layers in your program
as a CAT of FORM DR2D's each with a different LYID chunk?  This would
make it so that those people who want a drawing and don't want to fuss
with layers don't have to deal with a layer ID word in every chunk.  
This is really what you want in some sense, since each separate FORM
DR2D is a different layer, rather than having all the different layers
interspersed throughout one FORM. 

| Things I have NOT changed include:
|         1. I still use single-precision IEEE floating point
|            numbers for coordinates instead of scaled integers.

Like I said, I missed the first part of the discussion, but let me lodge 
a strong vote AGAINST using floating point in IFF files.  For some 
applications, floating point is essential, but not for drawings.  Since 
your format already specifies maximum and minimum X and Y for the drawing 
area, why not just leave these out and use numbers scaled from -2^31 to 
2^31?  Makes things more IFF-like (you know, _Interchange_ File Format), 
and also gives you more (albeit fixed) precision with the same number of 
bits.

| [...] Note
| that most chunks have both a chunk Size and an object Count.  I
| know this is redundant; however, this allows the data structures
| to be extended in a compatible manner if it should become necessary
| in the far future.

IFF already provides for upward compatibility.  All you need to do is
add new chunk types with the new information and they will be ignored by
programs that only understand the old chunks.  Once defined, a given
chunk should be considered SET IN STONE and NOT subject to change.  The
format should be enhanced by adding chunks, not by changing the already
defined chunks.  Redundant information of this type is therefore
unnecessary. 

| CMAP (0x434D4150)       /* Color map */

Like Leo, I strongly recommend you use the ILBM CMAP chunk definition for
several reasons: people already know how to read it, you're using the
same chunk ID, and your definition really adds no new information
(NumColors is just Size/3 (like Leo said, you don't have to add the pad
byte to the Size field)).

| PATT (0x50415454)       /* Fill Patterns */
|         struct PATTstruct {
|             LONG        ID;
|             LONG        Size;           /* 2 + 64*NumPatts */
|             SHORT       NumPatts;       /* Typically 16 */
|             UBYTE       Patterns[NumPatts][8][8];
|         };
|         /* Each pixel in the 8x8 pattern may be a different color
|            from the palette.  Note that these colors may be
|            approximated by any given output device. */

Why not use nested ILBM FORM's here?  Something like:

	LIST { PATT
		FORM { ILBM
			...
			BODY
		}
	... as many ILBM FORM's as you have patterns
	}

This gives you more flexibility in the size and shape of the fill 
pattern, as well as making it simple to import IFF brushes to use as 
patterns.

Question:  What's a pixel-based fill pattern doing in a floating-point,
scaled lines drawing format?  How do you do the conversion from pixels
to your floating-point coordinates?  Perhaps this conversion factor
(i.e. the pixel size in world coordinates) should be included in the 
PATT chunk or LIST in some way.

| FONT (0x464F4E54)       /* Font table */

Isn't there a standard FONT chunk defined for FORM FTXT?  You should
probably use it, like using ILBM CMAP chunks.

| TEXT (0x54455854)       /* A text string */

Same with TEXT.  Use the FTXT CHRS chunk instead.

| FILL (0x46494C4C)       /* Line fill pattern table */

Could a line fill pattern be stored as a nested FORM DR2D, or a symbol?


The next comments relate to the concept of "symbols" and "groups" as 
described for this proposed format.  

| NOTE 5: The data in a DSYM, SGRP or WGRP chunk is a series of nested object
|         chunks.  All object chunks except DSYM, CMAP, PATT, FILL, and FONT are
|         allowed in a DSYM, SGRP or WGRP.

The supported way of doing this with IFF files is to use nested generic 
chunks, such as CATs, FORMs and LISTs.  So instead of a DSYM chunk 
looking like this:

|         struct DSYMstruct {
|             LONG        ID;
|             LONG        Size;
|             SHORT       SymbID;                 /* Unique ID for this symbol */
|             SHORT       NumObjs;
|             UBYTE       SymbChunk[Size-4];      /* See note 5 */
|         };

the file would contain a LIST DSYM, for example, like this:

	LIST { DSYM
		PROP { DR2D
			SYID	- symbol ID chunk
		}
		FORM { DR2D
			...	- definition of the symbol
		}
	}

Or, as another example (which I don't like as much but which might also
work), something like this: 

	FORM { DSYM
		SYID		- symbol ID chunk
		....		- more stuff for this symbol
		FORM { DR2D
			....	- symbol data chunks
		}
	}

There are several reasons to do it this way, not the least of which is
that this approach or some variation is the correct way to do recursion
under IFF.  Also, readers which understand how to parse the generic
chunks can already parse this format, whereas with the proposed
mechanism, the parser would have to know how to parse the special DYSM
chunk as a series of nested chunks.  This means that someone trying to
read this type of file will need to write their own custom reader
instead of using generic tools for reading IFF files.  One of the best
reasons to use this approach is that it's more general; a symbol could
be stored in a file by itself. 

The concept of "weak groups" and "strong groups" are *EXACTLY* what
generic CAT and LIST chunks are for, so there's no excuse for not using
these to define groups.  Do not re-invent the wheel.


There are a number of properties that occur in group and symbol 
definitions, to wit:

|             UBYTE       FillType;       /* One of F_*, above    */
|             UBYTE       FillValue;      /* See note 4           */
|             UBYTE       EdgeType;       /* One of E_*, above    */
|             UBYTE       EdgeValue;      /* Edge color index     */
|             USHORT      WhichLayer;     /* Which layer it's in  */
|             IEEE        EdgeThick;      /* Line width, if E_THICK */
|             IEEE        XPos, YPos,             /* Where to put it */
|                         XMag, YMag,             /* How big should it be? */
|                         Rotation;               /* Angle of rotation */

These are more or less general properties that could apply to any
object, so why not make each one a property chunk?  A given property
would apply to any objects within its scope, and nested properties would
apply in a nested way.  It would actually be required to define
properties this way to allow for using LIST chunks as strong groups.  In
fact, I've already mentioned putting the WhichLayer property into its
own chunk for another reason.  In addition, the nesting of properties
would be much more general.  For example, you could have the following
DR2D file: 

	FORM DR2D
		(header)
		RECT		- rectangle #1
		ROTA		- rotation property, 45 degrees
		FORM DR2D	- nested drawing
			ROTA	- rotation, 45 degrees
			RECT	- rectangle #2
		RECT		- rectangle #3

Rectangle #1 would be unaffected by any rotations.  Rectangle #3 is in 
the scope of the first ROTAtion property and would therefore be rotated 
45 degrees.  Rectangle #2 is in the scope of two 45 degree rotations and 
would be rotated 90 degrees.


I understand, Ross, that all this is very different than you originally
had in mind; however, if you honestly expect this to become a de-facto
standard, I would hope that you would be willing to make it more
powerful and general than simply a dump of your program's internal
variables.  Also, since you're designing an IFF format, you should adopt
an IFF philosophy as well. 

It would not be a bad thing to design a format more complex than your 
program can handle.  In that case, just do the best you can with 
whatever file you're handed.  Files produced by your program might not
use the full capability of the format, and files with a very complex
structure might need to be simplified by your program while being read.
This is how IFF files are intended, and is a pretty common practice.
Just think about all the information in ILBMs that most programs ignore.

Thanx for being willing to share your design concept with the Net.  I 
hope you find my comments useful.
-- 
		Stuart Ferguson		(shf@well.UUCP)
		Action by HAVOC		(shf@Solar.Stanford.EDU)

peter@sugar.uu.net (Peter da Silva) (08/11/88)

In article ... cunniff@hpfcdc.HP.COM (Ross Cunniff) writes:
> Actually, every object *is* rotatable; simply rotate the actual points
> of the data. ...  My rationale for precomputing the rotation is that
> it is faster to render objects whose position and rotation are precomputed
> rather than rotating and traslating them on the fly...

That's fine for a rendering standard. I thought, though, that you were working
on a data transmission standard. For that, the rotation angle is important.

Why? Floating point operations are not commutative. The rotated points for the
rectangle will be off by a small amount, whereas the unrotated rectangle may
be exact. If it's stored and transmitted in an exact format, then errors will
not accumulate as the iterations progress.
-- 
		Peter da Silva  `-_-'  peter@sugar.uu.net
		 Have you hugged  U  your wolf today?

ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (08/11/88)

In article <63566@sun.uucp> cmcmanis@sun.UUCP (Chuck McManis) writes:
>Leo, let us be serious here. RULE #1 for ILBM is :
>	If you don't understand the FORM then don't look inside it.
>
>The simple reason being, that like any modular programming language the
>scope of a chunk is limited to the FORM it is contained in.  [ ... ]

	Woah!  I thought I had said:

>In article <6778@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>>	Although this flavor of CMAP chunk will only appear in a DR2D FORM,
>>	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>we already have a well-known and -advertised (and -coded-for) CMAP chunk
>>for ILBM FORMs.  

	I'm well aware of the scope rules for IFF.  It's perfectly all right
to define a hunk type with the same name as something else, but different
contents, so long as it appears in the correct context (namely, a DR2D
FORM).  However, since his CMAP hunk is functionally identical to an ILBM
CMAP, it just seemed wasteful (and possibly confusing to new IFF programmers)
to define a whole new one, and write new code for it.

	But of course, he's perfectly free to do whatever he feels is right.

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape	INET: well!ewhac@ucbvax.Berkeley.EDU
 \_ -_		Recumbent Bikes:	UUCP: pacbell > !{well,unicom}!ewhac
O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
"Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

peter@sugar.uu.net (Peter da Silva) (08/19/88)

In article <63566@sun.uucp>, cmcmanis%pepper@Sun.COM (Chuck McManis)
explains that:

> The simple reason being, that like any modular programming language the
> scope of a chunk is limited to the FORM it is contained in. By forcing
> _this_ CMAP chunk to look like an ILBM chunk you imply that all chunks
> with the same name are the same chunk.

He's not forcing it. He's recommending that, since the two chunks serve the
same purpose and since they're both likely to be used by the same program,
it would be a good idea to make the structures match. After all, the existing
IFF standard has chunks that look the same in more than one FORM: look at
the 'NAME', '(c) ', 'AUTH', and 'ANNO' chunks in 8SVX and SMUS.

	
> And this must not be true for IFF to work.

No, but if you can coalesce two chunks, why not? It's a net gain.
-- 
		Peter da Silva  `-_-'  peter@sugar.uu.net
		 Have you hugged  U  your wolf today?