From: stay@icon.com (Steve Taylor)
Subject: SeedCFill
Organization: Icon International, Inc., Orem, Utah
Date: Sat, 22 Aug 1992 22:17:21 GMT

Gentlebeings,
 
I've spent a week on SeedCFill and I'm having a great deal of
trouble with it.  Included in this message is a sample program
to illustrate only one of the many weird things I can't figure
out from Inside Macintosh.  I also have "Programming Quickdraw"
and that doesn't help much, either.
 
(1) Am I allowed to interchange pixmaps and bitmaps for either of
the first two arguments?  I thought so, but the following code
doesn't work at all if I change the destination bitmap to a
1-bit pixmap.
(2) What does Think Reference mean by telling me to pass in
an address INSIDE a bitmap?
(3) In the example below, I'm just trying to offset the
destination rect before doing a SeedCFill.  What's wrong?
 
---------------------------------------------------------
#include <QDOffscreen.h>
#include <QuickDraw.h>
 
//
//	Build a GWorld and return a pointer to it
//
 
static GWorldPtr
BuildAGWorld(short width, short height, short bitDepth) {
	Rect		boundsRect;
	GWorldPtr	tempGWorld;
	QDErr		qErr;
	
	boundsRect.top = boundsRect.left = 0;
	boundsRect.right = width;
	boundsRect.bottom = height;
		
	qErr = NewGWorld(&tempGWorld, bitDepth, &boundsRect, NULL, NULL, 0L);
	return tempGWorld;
}
 
//
//	Create an offscreen bit map, taken from the
//	Dev. CD CalcMask example (by Edgar Lee),
//	which got it from someone else:
//
 
/* Originally written by Forrest Tanaka. */
GrafPtr CreateGrafPort( bounds )
Rect *bounds;
{
	GrafPtr	savedPort;		/* Saved GrafPtr for later restore. */
	GrafPtr	newPort;		/* New GrafPort. */
	Rect	localBounds;	/* Local copy of bounds. */
 
	GetPort( &savedPort );
 
	/* Set the top-left corner of bounds to (0,0). */
	localBounds = *bounds;
	OffsetRect( &localBounds, -bounds->left, -bounds->top );
 
	/* Allocate a new GrafPort. */
	newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
	
	if (newPort != nil)
	{
		/* Initialize the new port and make the current port. */
		OpenPort( newPort );
 
		/* Initialize and allocate the bitmap. */
		newPort->portBits.bounds = localBounds;
  		newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
		newPort->portBits.baseAddr =
				NewPtrClear( newPort->portBits.rowBytes *
				(long)localBounds.bottom );
		if (newPort->portBits.baseAddr != nil)
		{
			/* Clean up the new port. */
			newPort->portRect = localBounds;
			ClipRect( &localBounds );
			RectRgn( newPort->visRgn, &localBounds );
			EraseRect( &localBounds );
		}
		else
		{
			/* Allocation failed; deallocate the port. */
			ClosePort( newPort );
			DisposPtr( (Ptr)newPort );
			newPort = nil;
		}
	}
	
	SetPort( savedPort );
	return newPort;
}
 
/* Originally written by Forrest Tanaka. */
void DisposeGrafPort( doomedPort )
GrafPtr doomedPort;
{
	ClosePort( doomedPort );
	DisposPtr( doomedPort->portBits.baseAddr );
	DisposPtr( (Ptr)doomedPort );
}
 
//	My stuff:
 
static void
DoStuff() {
	WindowPtr		theWindow;
	Rect			rBounds = {50, 50, 450, 500};
	Rect			tempRect, destRect;
	PixMapHandle	sourcePM;
	QDErr			qErr;
	GWorldPtr		sourceWorld;
	GrafPtr			destMap, oldPort;
	CGrafPtr		tempGrafPtr;
	GDHandle		tempGDHandle;
	
	GetPort(&oldPort);
	//	New window to view results
	theWindow = NewWindow(NULL, &rBounds, "\p", true
			, plainDBox, (WindowPtr)(-1L), false, 0L);
	SetPort(theWindow);
	
	//	4 bit pixmap for source
	sourceWorld = BuildAGWorld(100, 100, 4);
	
	//	bitmap for mask
	SetRect(&tempRect, 0, 0, 100, 100);
	destMap = CreateGrafPort(&tempRect);
	
	//	save the port
	GetGWorld(&tempGrafPtr, &tempGDHandle);
	qErr = QDError();
	
	//	Clean up the pixmap
	SetGWorld(sourceWorld, NULL);
	qErr = QDError();
	EraseRect(&thePort->portRect);
	
	//	Draw a sample drawing on the pixmap
	SetRect(&tempRect, 10, 10, 20, 20);
	ForeColor(blueColor);
	FillRect(&tempRect, black);
	ForeColor(blackColor);
	
	//	restore the port
	SetGWorld(tempGrafPtr, tempGDHandle);
	qErr = QDError();
	
	//	Now perform the seed fill.  Here's the weird part.
	//	If I leave destRect where it is, the following
	//	SeedCFill works fine.  If I offset destRect
	//	vertically down 29 pixels, it still works fine.
	//	If I offset it down 30 pixels, SeedCFill fails.
	//	(It just fills the destRect with white.)
	//	Why?
	
	SetRect(&tempRect, 0, 0, 30, 30);
	destRect = tempRect;
	//	OffsetRect(&destRect, 0, 29);	//	works
	//	OffsetRect(&destRect, 0, 30);	//	doesn't work
	
	sourcePM = GetGWorldPixMap(sourceWorld);
	LockPixels(sourcePM);
	
	SeedCFill(*sourcePM, &destMap->portBits
			, &tempRect, &destRect, 0, 0, NULL, 0L);
	
	UnlockPixels(sourcePM);
	
	//	Show source
	SetRect(&tempRect, 0, 0, 100, 100);
	destRect = tempRect;
	OffsetRect(&destRect, 10, 10);
	sourcePM = GetGWorldPixMap(sourceWorld);
	LockPixels(sourcePM);
	CopyBits((BitMap *)*sourcePM, &thePort->portBits
			, &tempRect, &destRect, srcCopy, NULL);
	UnlockPixels(sourcePM);
	
	//	Show destination
	SetRect(&tempRect, 0, 0, 100, 100);
	destRect = tempRect;
	OffsetRect(&destRect, 120, 10);
	CopyBits(&destMap->portBits, &thePort->portBits
			, &tempRect, &destRect, srcCopy, NULL);
	
	SetPort(&oldPort);	//	restore original port
	
	DisposeGWorld(sourceWorld);
	DisposeGrafPort(destMap);
	DisposeWindow(theWindow);
}
 
static
InitThings(void) {
	InitGraf(&thePort);
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs(NULL);
	InitCursor();
}
 
 
main() {
	InitThings();
	DoStuff();
}
 
---------------------------------------------------------------

This code runs in Think C. 5.0.2 on a IIci and a grayscale monitor.
 
Thanks.
 
-- Steve Taylor (stay@icon.com)
trACE Development