/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information.       */
/* Contact email: mac@aarongiles.com                     */
/*********************************************************/

#if THINK_C
#include "THINK.Header"
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif

typedef struct PICTPrivates {
	Rect qdRect;
	long totalLines;
} PICTPrivates, *PICTPrivatesPtr, **PICTPrivatesHandle;

/*
 * Local variables:
 *   lPICTImage = pointer to the image for use when extracting PICT information
 *   lPICTPreview = handle to the preview image, if one was requested for saving
 *
 */

static Handle gPICTComments;
static Rect gPICTSrcRect, gPICTDstRect;
static ImageHandle gPICTImage;
static JVDrawParamsHandle gPICTParams;
static long gTotalLines, gCurrentLines;
static Boolean gHasObjects;
static StdPixUPP gProgressPixProc = nil, gAddColorsPixProc, gInitPixProc;
static QDBitsUPP gDummyBitsProc, gInitBitsProc;
static QDTextUPP gDummyTextProc, gInitTextProc;
static QDLineUPP gDummyLineProc, gInitLineProc;
static QDRectUPP gDummyRectProc, gInitRectProc;
static QDRRectUPP gDummyRRectProc, gInitRRectProc;
static QDOvalUPP gDummyOvalProc, gInitOvalProc;
static QDArcUPP gDummyArcProc, gInitArcProc;
static QDPolyUPP gDummyPolyProc, gInitPolyProc;
static QDRgnUPP gDummyRgnProc, gInitRgnProc;

static void InitPICTUPPs(void);
static pascal void ProgressPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short flags);
static pascal void AddColorsPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short flags);
static pascal void InitPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits);
static pascal void InitBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, 
	RgnHandle mask);
static pascal void InitTextProc(short count, const void *textAddr, Point numer, Point denom);
static pascal void InitLineProc(Point newPt);
static pascal void InitRectProc(GrafVerb verb, const Rect *r);
static pascal void InitRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, 
	short ovalHeight);
static pascal void InitOvalProc(GrafVerb verb, const Rect *r);
static pascal void InitArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle);
static pascal void InitPolyProc(GrafVerb verb, PolyHandle poly);
static pascal void InitRgnProc(GrafVerb verb, RgnHandle rgn);
static pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, 
	RgnHandle mask);
static pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom);
static pascal void DummyLineProc(Point newPt);
static pascal void DummyRectProc(GrafVerb verb, const Rect *r);
static pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, 
	short ovalHeight);
static pascal void DummyOvalProc(GrafVerb verb, const Rect *r);
static pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle);
static pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly);
static pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn);

/*
 * idPICT(theData, theSize)
 *
 *     Purpose: Attempts to identify an image as a PICT
 *      Inputs: theData = pointer to the loaded data
 *				theSize = size of the loaded data
 *     Returns: true for a positive PICT ID
 *
 */
 
Boolean idPICT(uchar *theData, long theSize, short refNum, FSSpec *theSpec)
{
#if applec
#pragma unused(refNum, theSpec)
#endif
	ushort *theShort = (ushort *)(theData + kHeaderSize + 10);
	PicPtr thePicture = (PicPtr)(theData + kHeaderSize);
	
	if (theSize < kHeaderSize + 12) return false;
	if (Width(&thePicture->picFrame) > 0 && Height(&thePicture->picFrame) > 0) {
		while (!*theShort) theShort++;
		if (*theShort == 0x0011 || *theShort == 0x1101) return true;
	}
	return false;
}

/*
 * OpenPICT(theImage)
 *
 *     Purpose: Initializes the image record for a PICT image
 *      Inputs: theImage = image record for the PICT image
 *     Returns: nothing
 *
 */

OSErr OpenPICT(ImageHandle theImage)
{
	Fixed hRes = 0x480000L, vRes = 0x480000L;
	Rect *theRect, fullQRect;
	OSErr theErr = noErr;
	ushort *theShort;
	uchar *theData;
	Str63 theDesc;
	
	if (!((*theImage)->privateData = NewHandleClear(sizeof(PICTPrivates))))
		return memFullErr;
	theData = (uchar *)*(*theImage)->data;
	theShort = (ushort *)(theData + 10);
	theRect = (Rect *)(theData + 2);
	(*(PICTPrivatesHandle)(*theImage)->privateData)->qdRect = (*theImage)->qrect = *theRect;
	while (!*theShort) theShort++;
	if (*theShort == 0x0011 && theShort[2] == 0x0c00 && theShort[3] == 0xfffe) {
		theRect = (Rect *)(theShort + 9);
		hRes = *(long *)(theShort + 5);
		vRes = *(long *)(theShort + 7);
	}
	(*theImage)->grect = *theRect;
	if (Width(&(*theImage)->grect) <= 0 || Height(&(*theImage)->grect) <= 0 ||
				Width(&(*theImage)->qrect) <= 0 || Height(&(*theImage)->qrect) <= 0)
		return gIntError = errCorruptImage, codecBadDataErr;
	GetImageInfo(theImage);
	fullQRect = (*theImage)->grect;
	fullQRect.left = Fix2Long(FixMul(FixDiv(0x480000L, hRes), Long2Fix(fullQRect.left)));
	fullQRect.right = Fix2Long(FixMul(FixDiv(0x480000L, hRes), Long2Fix(fullQRect.right)));
	fullQRect.top = Fix2Long(FixMul(FixDiv(0x480000L, vRes), Long2Fix(fullQRect.top)));
	fullQRect.bottom = Fix2Long(FixMul(FixDiv(0x480000L, vRes), Long2Fix(fullQRect.bottom)));
	(*theImage)->crect = (*theImage)->qrect;
	MapRect(&(*theImage)->crect, &fullQRect, &(*theImage)->grect);
	(*theImage)->compression = (*theImage)->desc.cType;
	if ((*theImage)->desc.height)
		if (Height(&(*theImage)->crect) > (*theImage)->desc.height)
			(*theImage)->flags |= ifBanded;
	if ((*theImage)->crect.right < ((*theImage)->grect.right - 5) ||
				(*theImage)->crect.left > ((*theImage)->grect.left + 5) ||
				(*theImage)->crect.bottom < ((*theImage)->grect.bottom - 5) ||
				(*theImage)->crect.top > ((*theImage)->grect.top + 5))
		(*theImage)->flags |= ifCropped;
/*	if ((*theImage)->compression == kJPEGCompression && !gHasObjects) {
		if (Height(&(*theImage)->crect) > (*theImage)->desc.height) 
			(*theImage)->flags |= ifBanded;
		if ((Width(&(*theImage)->crect) < (*theImage)->desc.width) || 
			(Height(&(*theImage)->crect) < (*theImage)->desc.height)) 
			(*theImage)->flags |= ifCropped;
	}*/
/*
	Old mechanism for detecting cropping vs. scaled DPI
	
	//--- deal with cropped images??
	if ((*theData)->compressionType == 'jpeg' && !gHasObjects) {
		if (Height(&(*theImage)->crect) > (*theImage)->desc.height) 
			(*theImage)->flags |= ifBanded;
		if ((Width(&(*theImage)->crect) < (*theImage)->desc.width) || 
			(Height(&(*theImage)->crect) < (*theImage)->desc.height)) 
			(*theImage)->flags |= ifCropped;
		if (Cropped(theImage) && !Banded(theImage)) {
			Rect crect = (*theImage)->crect, grect;
			MySetRect(&grect, 0, 0, (*theImage)->desc.width, (*theImage)->desc.height);
			MapRect(&crect, &(*theImage)->grect, &(*theImage)->qrect);
			MapRect(&crect, &lPICTDstRect, &lPICTSrcRect);
			if (crect.right > grect.right) crect.right = grect.right;
			if (crect.left < grect.left) crect.left = grect.left;
			if (crect.bottom > grect.bottom) crect.bottom = grect.bottom;
			if (crect.top < grect.top) crect.top = grect.top;
			(*theImage)->grect = grect;
			theErr = DoSetImageBounds(theImage, &grect);
			(*theImage)->crect = crect;
			if (EqualSizeRect(&crect, &grect)) (*theImage)->flags &= ~ifCropped;
		}
	}
*/
	if (!(*theImage)->ipalette && 
		((*theImage)->depth == 36 || (*theImage)->depth == 40)) {
		(*theImage)->ipalette = NewPalette(1L << ((*theImage)->depth - 32), nil, pmTolerant, 0);
		if ((*theImage)->ipalette)
			CopyPalette(GreyPalette((*theImage)->depth - 32), (*theImage)->ipalette, 0, 0, 256);
	}
	if ((*theImage)->compression == 'raw ') (*theImage)->compression = 0L;
	if ((*theImage)->compression) {
		BlockMove((*theImage)->desc.name, theDesc, *(*theImage)->desc.name + 1);
		AddString(theDesc, gString[strQuality]);
		StuffNumber(theDesc, 1, (*theImage)->desc.spatialQuality >> 8);
		StuffNumber0(theDesc, 2, (((*theImage)->desc.spatialQuality & 0xff) * 100) >> 8, 2);
	} else BlockMove(gString[strUncompressed], theDesc, *gString[strUncompressed] + 1);
	BlockMove(theDesc, (*theImage)->compressionDesc, *theDesc + 1);
	return theErr;
}

/*
 * DrawPICT(theImage, theGWorld, srcRect, dstRect, dither, progProc)
 *
 *     Purpose: Draws the PICT image within its cropping rectange in the proper window
 *      Inputs: theImage = image record for the PICT image
 *				theGWorld = the destination GWorld to draw into
 *				srcRect = the source rectangle
 *				dstRect = the destination rectangle
 *				dstRgn = the destination clipping region
 *				dither = flag: true if we should dither this guy
 *				progProc = the progress procedure record to be used
 *     Returns: nothing
 *
 */

OSErr DrawPICT(Handle theHandle, JVDrawParamsHandle theParams)
{
	Rect globRect = (*theParams)->bounds;
	char hState = HGetState(theHandle);
	OSErr theErr;

	if (!gProgressPixProc) InitPICTUPPs();
	((CGrafPtr)qd.thePort)->grafProcs->newProc1 = (UniversalProcPtr)gProgressPixProc;
	gPICTParams = theParams;
	gTotalLines = (*(PICTPrivatesHandle)(*theParams)->privateData)->totalLines;
	gCurrentLines = 0;
	PushPort();
	ClipRect(&globRect);
	RGBForeColor(&gBlack);
	RGBBackColor(&gWhite);
	HLock(theHandle);
	KeepSpinning();
	if (gQTVersion) theErr = DrawTrimmedPicture((PicHandle)theHandle, &globRect,
				qd.thePort->visRgn, false, nil);
	else DrawPicture((PicHandle)theHandle, &globRect), theErr = noErr;
	if ((*theParams)->progress.aborted) theErr = codecAbortErr;
	KeepSpinning();
	HSetState(theHandle, hState);
	PopPort();
	return theErr;
}

/*
 * ProgressPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits)
 *
 *     Purpose: Routine called when a compressed PixMap is found in a PICT; we
 *					intercept it and call FDecompressImage, making the progress updates
 *					work to some extent....
 *      Inputs: src = the compressed PixMap
 *				srcRect = the rectangle of the image in the source coordinates
 *				matrix = the transformation matrix
 *				mode = the drawing mode
 *				mask = the output masking region
 *				matte = the output matte, described as a PixMap
 *				matteRect = the bounding rectangle for the output matte
 *				callOldBits = flag saying if we should call the old routine
 *     Returns: nothing
 *
 */
 
pascal void ProgressPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short flags) 
{
	PixMapHandle dst = GetGWorldPixMap((CGrafPtr)qd.thePort);
	NestedProgress theProc = (*gPICTParams)->progress;
	ImageDescriptionHandle theDesc;
	ICMProgressProcRecord progProc;
	ICMDataProcRecord dataProc;
	OSErr theErr;
	long bufSize;
	Ptr theData;
	
	if ((*gPICTParams)->progress.aborted || ((*gPICTParams)->progress.aborted = CheckAbort(gPICTParams))) 
		return;
	theErr = GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, 
			 &progProc);
	if (theErr == noErr) {
		KeepSpinning();
		(*gPICTParams)->progress.begin = FixRatio(gCurrentLines, gTotalLines);
		(*gPICTParams)->progress.begin = theProc.begin +
			FixMul((*gPICTParams)->progress.begin, theProc.end - theProc.begin);
		(*gPICTParams)->progress.end = FixRatio(gCurrentLines + Height(srcRect), gTotalLines);
		(*gPICTParams)->progress.end = theProc.begin +
			FixMul((*gPICTParams)->progress.end, theProc.end - theProc.begin);
		if ((*gPICTParams)->progress.prog.progressProc)
			CallICMProgressProc((*gPICTParams)->progress.prog.progressProc,
						codecProgressUpdatePercent, 0x00000000L, 
						(*gPICTParams)->progress.prog.progressRefCon);
		FixBits((CGrafPtr)qd.thePort, true);
		InstallQDxDispatchPatch(true);
		FDecompressImage(StripAddress(theData), theDesc, dst, srcRect, matrix, mode, 
			mask, &matte, matteRect, codecHighQuality, anyCodec, bufSize, &dataProc, 
			(ICMProgressProcRecordPtr)&theProc);
		RemoveQDxDispatchPatch();
		FixBits((CGrafPtr)qd.thePort, false);
		if ((*gPICTParams)->progress.prog.progressProc && !(*gPICTParams)->progress.aborted)
			CallICMProgressProc((*gPICTParams)->progress.prog.progressProc,
						codecProgressUpdatePercent, 0x00010000L, 
						(*gPICTParams)->progress.prog.progressRefCon);
		KeepSpinning();
		(*gPICTParams)->progress.begin = theProc.begin;
		(*gPICTParams)->progress.end = theProc.end;
		gCurrentLines += Height(srcRect);
	} else StdPix(src, srcRect, matrix, mode | 0x80, mask, matte, matteRect, flags);
	if (gSlideShow && !(*gPICTParams)->progress.aborted) 
		(*gPICTParams)->progress.aborted = CheckAbort(gPICTParams);
}

/*
 * LoadPICT(theFile, theImage)
 *
 *     Purpose: Allocates memory and loads the PICT image in
 *      Inputs: theFile = the input file
 *				theImage = image record
 *     Returns: nothing
 *
 */

OSErr LoadPICT(short theFile, ImageHandle theImage) 
{
	OSErr theErr = noErr;
	long theSize;
	
	KeepSpinning();
	GetEOF(theFile, &theSize);
	if ((theSize -= kHeaderSize) < 0) return errCorruptImage, codecBadDataErr;
	if (!MakeMemAvailable(theSize)) return gIntError = errNoLoadMemory, memFullErr;
	if ((*theImage)->data = NewHandle(theSize)) {
		SetFPos(theFile, fsFromStart, kHeaderSize);
		HLock((*theImage)->data);
		SpinIndef();
		theErr = FSRead(theFile, &theSize, *(*theImage)->data);
		KeepSpinning();
		HUnlock((*theImage)->data);
		if (theErr == noErr) return theErr;
		else DisposeHandle((*theImage)->data);
		gIntError = errCantReadFile;
	} else gIntError = errNoLoadMemory, theErr = memFullErr;
	return theErr;
}

static void InitPICTUPPs(void)
{
	gProgressPixProc = NewStdPixProc((ProcPtr)ProgressPixProc);
	gAddColorsPixProc = NewStdPixProc((ProcPtr)AddColorsPixProc);
	gInitPixProc = NewStdPixProc((ProcPtr)InitPixProc);
	gInitBitsProc = NewQDBitsProc((ProcPtr)InitBitsProc);
	gInitTextProc = NewQDTextProc((ProcPtr)InitTextProc);
	gInitLineProc = NewQDLineProc((ProcPtr)InitLineProc);
	gInitRectProc = NewQDRectProc((ProcPtr)InitRectProc);
	gInitRRectProc = NewQDRRectProc((ProcPtr)InitRRectProc);
	gInitOvalProc = NewQDOvalProc((ProcPtr)InitOvalProc);
	gInitArcProc = NewQDArcProc((ProcPtr)InitArcProc);
	gInitPolyProc = NewQDPolyProc((ProcPtr)InitPolyProc);
	gInitRgnProc = NewQDRgnProc((ProcPtr)InitRgnProc);
	gDummyBitsProc = NewQDBitsProc((ProcPtr)DummyBitsProc);
	gDummyTextProc = NewQDTextProc((ProcPtr)DummyTextProc);
	gDummyLineProc = NewQDLineProc((ProcPtr)DummyLineProc);
	gDummyRectProc = NewQDRectProc((ProcPtr)DummyRectProc);
	gDummyRRectProc = NewQDRRectProc((ProcPtr)DummyRRectProc);
	gDummyOvalProc = NewQDOvalProc((ProcPtr)DummyOvalProc);
	gDummyArcProc = NewQDArcProc((ProcPtr)DummyArcProc);
	gDummyPolyProc = NewQDPolyProc((ProcPtr)DummyPolyProc);
	gDummyRgnProc = NewQDRgnProc((ProcPtr)DummyRgnProc);
}

/*
 * GetImageInfo(theImage)
 *
 *     Purpose: Retrieves the image description and CLUT from a given PICT
 *      Inputs: theImage = image record for the PICT image
 *     Returns: nothing
 *
 */

void GetImageInfo(ImageHandle theImage) 
{
	char hState = HGetState((*theImage)->data);
	Rect theRect = (*theImage)->qrect;
	CQDProcs theProcs, *oldProcs;

	gPICTImage = theImage;
	gPICTComments = nil;
	gTotalLines = 0;
	gHasObjects = false;
	PushPort();
	MySetPort(gGenericGWorld);
	SetStdCProcs(&theProcs);
	if (!gProgressPixProc) InitPICTUPPs();
	theProcs.newProc1 = (UniversalProcPtr)gInitPixProc;
	theProcs.bitsProc = gInitBitsProc;
	theProcs.textProc = gInitTextProc;
	theProcs.lineProc = gInitLineProc;
	theProcs.rectProc = gInitRectProc;
	theProcs.rRectProc = gInitRRectProc;
	theProcs.ovalProc = gInitOvalProc;
	theProcs.arcProc = gInitArcProc;
	theProcs.polyProc = gInitPolyProc;
	theProcs.rgnProc = gInitRgnProc;
	oldProcs = gGenericGWorld->grafProcs;
	gGenericGWorld->grafProcs = &theProcs;
	HLock((*theImage)->data);
	KeepSpinning();
	if (gQTVersion) DrawTrimmedPicture((PicHandle)(*theImage)->data, &theRect, nil, false, nil);
	else DrawPicture((PicHandle)(*theImage)->data, &theRect);
	KeepSpinning();
	HSetState((*theImage)->data, hState);
	gGenericGWorld->grafProcs = oldProcs;
	PopPort();
	if (!(*theImage)->depth) (*theImage)->depth = 1;
	if (gHasObjects) (*theImage)->flags |= ifNeedsWhiteBG + ifNoOnscreenProg;
	(*theImage)->comments = gPICTComments;
	(*(PICTPrivatesHandle)(*theImage)->privateData)->totalLines = gTotalLines;
}

/*
 * SavePICTFile(theSpec, theHandle)
 *
 *     Purpose: Writes the PICT image out to the specified file
 *      Inputs: theSpec = a pointer to the output file spec
 *				theHandle = the handle of the data to be written
 *     Returns: an OSErr describing what went wrong
 *
 */

OSErr SavePICT(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates)
{
#if applec
#pragma unused(thePreview, theRect, privates)
#endif
	long theSize = GetHandleSize(theHandle);
	char hState = HGetState(theHandle);
	uchar *theHeader[kHeaderSize];
	short theFile;
	OSErr theErr;
	long i;

	for (i = 0; i < kHeaderSize; theHeader[i++] = 0);
	KeepSpinning();
	theErr = FSpCreate(theSpec, kCreator, kPICTType, 0);
	if (theErr == noErr) {
		KeepSpinning();
		theErr = FSpOpenDF(theSpec, fsWrPerm, &theFile);
		if (theErr == noErr) {
			KeepSpinning();
			theErr = FSWrite(theFile, &i, theHeader);
			if (theErr == noErr) {
				HLock(theHandle);
				SpinIndef();
				theErr = FSWrite(theFile, &theSize, *theHandle);
				KeepSpinning();
				if (theErr == noErr) {
					HSetState(theHandle, hState);
					FSClose(theFile);
					return theErr;
				} else gIntError = errCantWriteFile;
				HSetState(theHandle, hState);
			} else gIntError = errCantWriteFile;
			FSClose(theFile);
		} else gIntError = errCantOpenFile;
		FSpDelete(theSpec);
	} else gIntError = errCantCreateFile;
	return theErr;
}

/*
 * FixPICT(addPreview)
 *
 *     Purpose: Performs the JFIF->PICT conversion on the active image, add the color
 *					table, crops it, and creates a preview if requested
 *      Inputs: addPreview = flag: true if we should add a preview image
 *				theSize = pointer to a long where we will return the size
 *     Returns: an OSErr describing what went wrong
 *
 */

OSErr FixPICT(ImageHandle theImage, Handle *finalData, Boolean palette)
{
	OSErr theErr = noErr;
	Handle oldData;
	
	if ((*theImage)->format->inType != kPICTType && 
		(*theImage)->format->inType != kSCRNType &&
		(*theImage)->format->inType != kJPEGType) 
		return errAETypeError;
	oldData = *finalData = (*theImage)->data;
	if ((*theImage)->format->inType == kJPEGType) {
		KeepSpinning();
		*finalData = WrapJPEG(oldData, (*theImage)->depth);
		if ((*theImage)->data != oldData) DisposeHandle(oldData);
		if (!*finalData) return memFullErr;
		oldData = *finalData;
	}
	if (palette) {
		KeepSpinning();
		*finalData = AddColors(oldData, theImage);
		if ((*theImage)->data != oldData) DisposeHandle(oldData);
		if (!*finalData) return gIntError = errNoColorsMemory, memFullErr;
		oldData = *finalData;
	}
	return theErr;
}

/*
 * AddColors(theHandle, theImage)
 *
 *     Purpose: Adds the image's palette to the image description of the PICT
 *      Inputs: theHandle = handle to the image data
 *				theImage = handle to the associated image
 *     Returns: a handle to the cropped image
 *
 */

Handle AddColors(Handle theHandle, ImageHandle theImage)
{
	PixMapHandle thePixMap = GetGWorldPixMap(gGenericGWorld);
	CQDProcs theProcs, *oldProcs = gGenericGWorld->grafProcs;
	long theSize = GetHandleSize(theHandle);
	char hState = HGetState(theHandle);
	Rect theRect = (*theImage)->qrect;
	OpenCPicParams theParams;
	Handle dstHandle;
	OSErr theErr;
	
	if (!(*theImage)->qpalette) return theHandle;
	if (MakeMemAvailable(theSize + 16384L)) {
		theParams.srcRect = theRect;
		theParams.hRes = theParams.vRes = 0x480000L;
		theParams.version = -2;
		theParams.reserved1 = theParams.reserved2 = 0;
		SetStdCProcs(&theProcs);
		if (!gProgressPixProc) InitPICTUPPs();
		theProcs.newProc1 = (UniversalProcPtr)gAddColorsPixProc;
		theProcs.bitsProc = gDummyBitsProc;
		theProcs.textProc = gDummyTextProc;
		theProcs.lineProc = gDummyLineProc;
		theProcs.rectProc = gDummyRectProc;
		theProcs.rRectProc = gDummyRRectProc;
		theProcs.ovalProc = gDummyOvalProc;
		theProcs.arcProc = gDummyArcProc;
		theProcs.polyProc = gDummyPolyProc;
		theProcs.rgnProc = gDummyRgnProc;
		gGenericGWorld->grafProcs = &theProcs;
		PushPort();
		MySetPort(gGenericGWorld);
		ClipRect(&theParams.srcRect);
		if (dstHandle = (Handle)OpenCPicture(&theParams)) {
			LockPixels(thePixMap);
			HLock(theHandle);
			gPICTImage = theImage;
			KeepSpinning();
			theErr = DrawTrimmedPicture((PicHandle)theHandle, &theParams.srcRect, nil, 
										false, (ICMProgressProcRecordPtr)&gDummyProg);
			KeepSpinning();
			HSetState(theHandle, hState);
			UnlockPixels(thePixMap);
			ClosePicture();
			gGenericGWorld->grafProcs = oldProcs;
			if ((theErr == noErr) && !EmptyRect(&(*(PicHandle)dstHandle)->picFrame)) {
				PopPort();
				return dstHandle;
			}
			DisposeHandle(dstHandle);
		} else theErr = memFullErr;
		gGenericGWorld->grafProcs = oldProcs;
		PopPort();
	} else theErr = memFullErr;
	return nil;
}

/*
 * AddColorsPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits)
 *
 *     Purpose: Dummy routine called when a compressed PixMap is found in a PICT; we just
 *					add a color table to the ImageDescription
 *      Inputs: src = the compressed PixMap
 *				srcRect = the rectangle of the image in the source coordinates
 *				matrix = the transformation matrix
 *				mode = the drawing mode
 *				mask = the output masking region
 *				matte = the output matte, described as a PixMap
 *				matteRect = the bounding rectangle for the output matte
 *				callOldBits = flag saying if we should call the old routine
 *     Returns: nothing
 *
 */
 
pascal void AddColorsPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short flags)
{
#if applec
#pragma unused(flags)
#endif
	PixMapHandle dst = GetGWorldPixMap((CGrafPtr)qd.thePort);
	ImageDescriptionHandle theDesc;
	ICMProgressProcRecord progProc;
	CTabHandle theColors = nil;
	ICMDataProcRecord dataProc;
	OSErr theError;
	long bufSize;
	Ptr theData;

	KeepSpinning();
	if (GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc)
																		== noErr) {
		if (theColors = (CTabHandle)AnyNewHandle(sizeof(ColorTable))) {
			Palette2CTab((*gPICTImage)->qpalette, theColors);
			(*theColors)->ctSeed = GetCTSeed();
			SetImageDescriptionCTable(theDesc, theColors);
			DisposeHandle((Handle)theColors);
			theError = SetCompressedPixMapInfo(src, theDesc, theData, bufSize, 
											   &dataProc, &progProc);
		}
	}
	StdPix(src, srcRect, matrix, mode, mask, matte, matteRect, 0);
}

//=====================================================================================
// Dummy QuickDraw bottlenecks to filter out non-PixMaps within PICTs
//=====================================================================================

/*
 * InitPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits)
 *
 *     Purpose: Dummy routine called when a compressed PixMap is found in a PICT; we just
 *					copy the image description to a handle lPICTDesc
 *      Inputs: src = the compressed PixMap
 *				srcRect = the rectangle of the image in the source coordinates
 *				matrix = the transformation matrix
 *				mode = the drawing mode
 *				mask = the output masking region
 *				matte = the output matte, described as a PixMap
 *				matteRect = the bounding rectangle for the output matte
 *				callOldBits = flag saying if we should call the old routine
 *     Returns: nothing
 *
 */
 
pascal void InitPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
	RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits) 
{
#if applec
#pragma unused(mode, mask, matte, matteRect, callOldBits)
#endif
	ImageDescriptionHandle theDesc;
	ICMProgressProcRecord progProc;
	CTabHandle theColors = nil;
	ICMDataProcRecord dataProc;
	long bufSize;
	Ptr theData;

	gTotalLines += Height(srcRect);
	gPICTSrcRect = *srcRect;
	gPICTDstRect = *srcRect;
	TransformRect(matrix, &gPICTDstRect, nil);
	if (!GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc)) {
		if ((*theDesc)->cType == kJPEGCompression) {
			if (!VerifyJPEGData((uchar *)theData, bufSize)) gIntError = errBadJPEG;
			ExtractComments(theData, bufSize, &gPICTComments);
		}
		BlockMove(*theDesc, &(*gPICTImage)->desc, sizeof(ImageDescription));
		(*gPICTImage)->depth = (*theDesc)->depth;
		if ((*theDesc)->clutID != -1) {
			GetImageDescriptionCTable(theDesc, &theColors);
			if (theColors) {
				(*gPICTImage)->ipalette = NewPalette((*theColors)->ctSize + 1, theColors, 
					pmTolerant, 0);
				DisposeHandle((Handle)theColors);
			}
		}
	}
}

/*
 * InitBitsProc(src, srcRect, dstRect, mode, mask)
 *
 *     Purpose: Routine called in place of CopyBits for our images; here we check for a
 *					custom color table
 *      Inputs: src = the compressed PixMap
 *				srcRect = the rectangle of the image in the source coordinates
 *				dstRect = the destination rectangle
 *				mode = the drawing mode
 *				mask = the output masking region
 *     Returns: nothing
 *
 */
 
pascal void InitBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, 
	RgnHandle mask) 
{
#if applec
#pragma unused(srcRect, dstRect, mode, mask)
#endif
	if (!(*gPICTImage)->depth) {
		if (src->rowBytes & 0x8000) {
			(*gPICTImage)->depth = src->pixelSize;
			if ((src->pixelSize <= 8) && src->pmTable)
				(*gPICTImage)->ipalette = NewPalette((*src->pmTable)->ctSize + 1, 
										  src->pmTable, pmTolerant, 0);
		} else (*gPICTImage)->depth = 1;
	}
}

pascal void InitTextProc(short count, const void *textAddr, Point numer, Point denom) 
{
#if applec
#pragma unused(count, textAddr, numer, denom)
#endif
	gHasObjects = true;
}

pascal void InitLineProc(Point newPt)
{
#if applec
#pragma unused(newPt)
#endif
	gHasObjects = true;
}

pascal void InitRectProc(GrafVerb verb, const Rect *r)
{
#if applec
#pragma unused(verb, r)
#endif
	gHasObjects = true;
}

pascal void InitRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, 
	short ovalHeight)
{
#if applec
#pragma unused(verb, r, ovalWidth, ovalHeight)
#endif
	gHasObjects = true;
}

pascal void InitOvalProc(GrafVerb verb, const Rect *r)
{
#if applec
#pragma unused(verb, r)
#endif
	gHasObjects = true;
}

pascal void InitArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle)
{
#if applec
#pragma unused(verb, r, startAngle, arcAngle)
#endif
	gHasObjects = true;
}

pascal void InitPolyProc(GrafVerb verb, PolyHandle poly)
{
#if applec
#pragma unused(verb, poly)
#endif
	gHasObjects = true;
}

pascal void InitRgnProc(GrafVerb verb, RgnHandle rgn)
{
#if applec
#pragma unused(verb, rgn)
#endif
	gHasObjects = true;
}

//=====================================================================================
// Dummy QuickDraw bottlenecks to filter out non-PixMaps within PICTs
//=====================================================================================

pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, 
	RgnHandle mask) 
{
#if applec
#pragma unused(src, srcRect, dstRect, mode, mask)
#endif
}

pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom) 
{
#if applec
#pragma unused(count, textAddr, numer, denom)
#endif
}

pascal void DummyLineProc(Point newPt)
{
#if applec
#pragma unused(newPt)
#endif
}

pascal void DummyRectProc(GrafVerb verb, const Rect *r)
{
#if applec
#pragma unused(verb, r)
#endif
}

pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, 
	short ovalHeight)
{
#if applec
#pragma unused(verb, r, ovalWidth, ovalHeight)
#endif
}

pascal void DummyOvalProc(GrafVerb verb, const Rect *r)
{
#if applec
#pragma unused(verb, r)
#endif
}

pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle)
{
#if applec
#pragma unused(verb, r, startAngle, arcAngle)
#endif
}

pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly)
{
#if applec
#pragma unused(verb, poly)
#endif
}

pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn)
{
#if applec
#pragma unused(verb, rgn)
#endif
}
