Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site uw-beaver
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!ihnp4!houxm!vax135!cornell!uw-beaver!info-mac
From: info-mac@uw-beaver
Newsgroups: fa.info-mac
Subject: Quickdraw Regions Explained (Full message)
Message-ID: <425@uw-beaver>
Date: Mon, 14-Jan-85 12:37:31 EST
Article-I.D.: uw-beave.425
Posted: Mon Jan 14 12:37:31 1985
Date-Received: Tue, 15-Jan-85 02:35:22 EST
Sender: daemon@uw-beaver
Organization: U of Washington Computer Science
Lines: 97

From: Hackerjack 

	An Explanation of QuickDraw's Region's Internal Representation

One of Quickdraw's nicest features is the ability to construct a
region of arbitrary shape, then force graphics to be drawn only inside
that region.  This ability is one of the key reasons that the
Macintosh window system is so pretty.

Long time Info-Mac readers might remember that I asked about Regions a
while back.  The consensus was that they were some kind of run-length
encoded pixel map, but the exact representation was un-documented.

Using MacPascal and a couple of spare hours, I think I have figured
out the internal format for regions.  This information is of use to
people attempting to construct, manipulate, or render QuickDraw-
compatable graphics on other machines.  It's also useful to know how
regions are stored because it gives the Macintosh application
programmer some idea as to the storage cost of various region shapes.
As with any hobbiest probing of an undocumented feature of a complex
system, this information may not be completly accurate.

Regions are represented as a byte string.  From the QuickDraw manual,
we know that regions are stored as follows:
0,1 : length of region's data, in bytes (at least 10)
2,9 : bounding rectangle of the region (0,0,0,0 means empty region)
10..length-1 : mask-data (empty if region is simply the boundry rectangle.)

If memory usage were not an issue, the region could be represented as
a mask-bitmap, with 1 bits implying that it was OK to write data in
the corresponding pixel, and 0 bits implying that the corresponding
pixel should not be changed.  Regions are, in fact, encoded in such a
way that they can be easily decoded into such a mask-bitmap.

The mask-data is a run-length-encoded description of the changes in the
mask-bitmap as it is traversed from top to bottom.  The general format is:

  ::= {}* 
  ::=  {}* 
 ::=  
     ::= $7fff

Marker, line-data, start-of-run, and end-of-run are all 2-byte signed
integers.  The line-number data are in ascending order, as are the
start-of-run and end-of-run data.  Here is an example:

Let's assume the region looks like this:

                                  x
	19 20 21 22 23 24 25 26 27 28 29 30 31 32
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     19|  |  |  |  |  |  |  |  |  |  |  |  |  |  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     20|  |[]|[]|  |  |  |  |  |  |  |  |[]|[]|  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
y    21|  |  |[]|[]|  |  |  |  |  |  |  |[]|[]|  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     22|  |  |[]|[]|  |  |  |  |  |  |  |[]|[]|  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     23|  |  |[]|[]|  |  |  |  |  |  |  |[]|[]|  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     24|  |  |  |  |  |  |  |  |  |  |  |  |  |  |
       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+

The cells filled with [] are those which are inside the region.  This region
is so small that it is unlikely that it would actually be used, but it makes
a good example.

The data representation of this region would be, in decimal words:

48			; the length of the region, in bytes
20,20,32,24		; the bounding rectangle
20			; the first line of changes
20,22			; the first change (pixel collumn 20-21 turn on)
30,32			; the second change (pixel collumn 30-31 turn on)
$7fff			; the end-of-line marker
21			; the second line of changes
20,21			; the first change (pixel collumn 20 turns off)
22,23			; the second change (pixel collumn 22 turns on)
$7fff			; the end-of-line marker
24			; the third line of changes
21,23			; the first change (pixel collumns 21-22 turn off)
30,32			; the second change (pixel collumns 30-31 turn off)
$7fff			; end-of-line
$7fff			; end-of-region

Pretty nifty, huh?  This data compression scheme is very good for dealing
with the intersection-of-rectangles kinds of shapes that come up so often
in an overlapping-window environment.  It's also pretty cheap to decode it
at the lowest level of a bit-blt routine.  I would create a scan-line
buffer and xor the runs to determine what the current line's mask is.
Finally, notice that it is possible, with some extra effort, to use this
list in reverse-scan-line order, which might be useful for the occasional
reverse-scan-line-order blt.

				Jack Palevich
-------