Path: utzoo!utgpu!attcan!uunet!husc6!psuvax1!rutgers!ucsd!ames!lll-lcc!well!shf
From: shf@well.UUCP (Stuart H. Ferguson)
Newsgroups: comp.sys.amiga.tech
Subject: Re: IFF form for 2D drawings (again)
Summary: Zen and the Art of IFF Design
Keywords: IFF, standard, drawing, 2D
Message-ID: <6793@well.UUCP>
Date: 10 Aug 88 21:55:45 GMT
References: <11640003@hpfcdc.HP.COM>
Reply-To: shf@well.UUCP (Stuart H. Ferguson)
Organization: The Blue Planet
Lines: 255


+--- 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)