JPEGView/Source/C/Bottlenecks.c
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

1 line
49 KiB
C

/*********************************************************/
/* This source code copyright (c) 1991-2001, Aaron Giles */
/* See the Read Me file for licensing information. */
/* Contact email: mac@aarongiles.com */
/*********************************************************/
//=====================================================================================
// Generic includes for Macintosh headers
//=====================================================================================
#if THINK_C
#include "THINK.Header"
#include <stddef.h>
#elif applec
#pragma load ":Headers:MPW.Header"
#elif __MWERKS__
//#include "MW.Header"
#else
#include "JPEGView.h"
#endif
//=====================================================================================
// Includes specific to this module
//=====================================================================================
#include "Bottlenecks.h"
//=====================================================================================
// FixedPort: Holds old StdBits procedure information for when we fix up a port's
// StdBits function to fix the QuickTime 1.5 bug.
//=====================================================================================
typedef struct FixedPort
{
struct FixedPort *next;
CGrafPtr port;
CQDProcs *oldprocs;
CQDProcs newprocs;
QDBitsUPP oldbits;
} FixedPort, *FixedPortPtr, **FixedPortHandle;
//=====================================================================================
// Global variables local to this module
//=====================================================================================
static JVDrawParamsHandle gDrawParamsRoot = nil;
static FixedPortPtr gFixedPortRoot = nil;
static CQDProcs gBottlenecks;
static QDBitsUPP gJVFixedBitsProc;
static DeviceLoopDrawingUPP gDeviceCopy;
//=====================================================================================
// Prototypes for functions local to this module
//=====================================================================================
static OSErr DitherTableInit(void);
static JVDrawParamsHandle FindParams(CGrafPtr thePort);
static pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect,
short mode, RgnHandle mask);
static pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode,
RgnHandle mask);
static void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams);
static void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams);
static void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams);
static pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice,
void *tempParams);
static void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither,
RgnHandle mask, short quality);
static Boolean IsGrayDevice(GDHandle theGDevice);
static void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect,
Rect *dstRect, Boolean dither, RgnHandle mask);
static void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect,
Rect *dstRect, Boolean dither, RgnHandle mask);
static void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state,
JVDrawParamsHandle theParams);
static void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect);
static Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2);
static pascal void JVTextProc(short count, Ptr textAddr, Point numer, Point denom);
static pascal void JVLineProc(Point newPt);
static pascal void JVRectProc(GrafVerb verb, Rect *r);
static pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight);
static pascal void JVOvalProc(GrafVerb verb, Rect *r);
static pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle);
static pascal void JVPolyProc(GrafVerb verb, PolyHandle poly);
static pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn);
//=====================================================================================
// OSErr DrawingInit(void)
//=====================================================================================
// Initializes the bottlenecks record and the dithering table.
//=====================================================================================
extern OSErr DrawingInit(void)
{
KeepSpinning();
SetStdCProcs(&gBottlenecks);
gBottlenecks.textProc = NewQDTextProc((ProcPtr)JVTextProc);
gBottlenecks.lineProc = NewQDLineProc((ProcPtr)JVLineProc);
gBottlenecks.rectProc = NewQDRectProc((ProcPtr)JVRectProc);
gBottlenecks.rRectProc = NewQDRRectProc((ProcPtr)JVRRectProc);
gBottlenecks.ovalProc = NewQDOvalProc((ProcPtr)JVOvalProc);
gBottlenecks.arcProc = NewQDArcProc((ProcPtr)JVArcProc);
gBottlenecks.polyProc = NewQDPolyProc((ProcPtr)JVPolyProc);
gBottlenecks.rgnProc = NewQDRgnProc((ProcPtr)JVRgnProc);
gBottlenecks.bitsProc = NewQDBitsProc((ProcPtr)JVBitsProc);
gJVFixedBitsProc = NewQDBitsProc((ProcPtr)JVFixedBitsProc);
gDeviceCopy = NewDeviceLoopDrawingProc((ProcPtr)DeviceCopy);
KeepSpinning();
return DitherTableInit();
}
//=====================================================================================
// OSErr DitherTableInit(void)
//=====================================================================================
// Initializes the dithering and scaling tables.
//=====================================================================================
static OSErr DitherTableInit(void)
{
Handle tempHandle;
uchar *theTable;
short *table;
short i, j, k;
KeepSpinning();
if (!(tempHandle = NewHandleClear((3 + 4 + 5 + 6 + 7 + 8) * 256)))
FatalError(errNoMemory);
HLockHi(tempHandle);
theTable = gScaleTable = (uchar *)StripAddress(*tempHandle);
for (i = 3; i <= 8; i++)
for (j = 0; j < 256; j++)
for (k = 0; k < i; k++) *theTable++ = j;
KeepSpinning();
if (!(tempHandle = NewHandleClear(sizeof(short) * 512))) FatalError(errNoMemory);
HLockHi(tempHandle);
table = gErrTable = (short *)StripAddress(*tempHandle) + 256;
for (i = j = 1; i < 0x08; i++, j++) table[i] = j, table[-i] = -j;
for (i = 0x08; i < 0x18; i++, j += !(i & 1) ? 1 : 0) table[i] = j, table[-i] = -j;
for (i = 0x18; i < 0x38; i++, j += !(i & 3) ? 1 : 0) table[i] = j, table[-i] = -j;
for (i = 0x38; i < 0x78; i++, j += !(i & 7) ? 1 : 0) table[i] = j, table[-i] = -j;
for ( ; i <= 0x100; i++) {
if (i != 0x100) table[i] = j;
table[-i] = -j;
}
KeepSpinning();
return noErr;
}
//=====================================================================================
// JVDrawParamsHandle NewDrawParams(Rect *bounds, short quality, Boolean quantize,
// NestedProgressPtr progress, Handle privateData)
//=====================================================================================
// Creates and begins initializing a JVDrawParamsHandle in preparation for drawing.
//=====================================================================================
extern JVDrawParamsHandle NewDrawParams(Rect *bounds, short quality, Boolean quantize,
NestedProgressPtr progress, Handle privateData)
{
JVDrawParamsHandle theParams;
if (theParams = (JVDrawParamsHandle)NewHandleClear(sizeof(JVDrawParams))) {
(*theParams)->bounds = *bounds;
(*theParams)->quality = quality;
(*theParams)->quantize = quantize;
if (progress) {
(*theParams)->progress = *progress;
(*theParams)->progress.prog.progressRefCon = (long)theParams;
}
(*theParams)->privateData = privateData;
}
return theParams;
}
//=====================================================================================
// SetUpDrawPort(JVDrawParamsHandle theParams, short whichPort, CGrafPtr thePort,
// Rect *srcRect, Rect *dstRect, Boolean dither)
//=====================================================================================
// Initialize one of the three drawing ports in the JVDrawParamsHandle.
//=====================================================================================
extern void SetUpDrawPort(JVDrawParamsHandle theParams, short whichPort, CGrafPtr thePort,
Rect *srcRect, Rect *dstRect, Boolean dither)
{
JVPortParams port;
port.port = thePort;
port.outer = (*theParams)->bounds;
MapRect(&port.outer, srcRect, dstRect);
port.dither = dither;
switch (whichPort) {
case kOnscreenPort:
(*theParams)->on = port;
break;
case kOffscreenPort1:
(*theParams)->off = port;
break;
case kOffscreenPort2:
(*theParams)->extra = port;
break;
}
}
//=====================================================================================
// OSErr PreflightDrawing(JVDrawParamsHandle theParams)
//=====================================================================================
// Inserts theParams into the local linked list of current drawing environments, and
// creates a new destination port with the bottleneck procedures installed.
//=====================================================================================
extern OSErr PreflightDrawing(JVDrawParamsHandle theParams)
{
Rect bounds = (*theParams)->bounds, dbounds = { 0, 0, 1, 32 }, outer;
GWorldPtr theGWorld;
RgnHandle tempRgn;
Rect theRect;
(*theParams)->next = gDrawParamsRoot;
(*theParams)->progress.aborted = false;
gDrawParamsRoot = theParams;
dbounds.right = Width(&(*theParams)->bounds);
if (theGWorld = MyNewGWorld(&dbounds, 32, nil, nil, false, false)) {
(*GetGWorldPixMap(theGWorld))->rowBytes &= 0xc000;
if (tempRgn = NewRgn()) {
SetEmptyRgn(theGWorld->visRgn);
if ((*theParams)->on.port) {
CopyRgn((*theParams)->on.port->visRgn, tempRgn);
InsetRgn(tempRgn, -1, -1);
outer = (*theParams)->on.outer;
MapRgn(tempRgn, &outer, &bounds);
UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn);
}
if ((*theParams)->off.port) {
CopyRgn((*theParams)->off.port->visRgn, tempRgn);
InsetRgn(tempRgn, -1, -1);
outer = (*theParams)->off.outer;
MapRgn(tempRgn, &outer, &bounds);
UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn);
if ((*theParams)->extra.port) {
CopyRgn((*theParams)->extra.port->visRgn, tempRgn);
InsetRgn(tempRgn, -1, -1);
outer = (*theParams)->extra.outer;
MapRgn(tempRgn, &outer, &bounds);
UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn);
}
}
theRect = (*theParams)->bounds;
RectRgn(theGWorld->clipRgn, &theRect);
if (!(*theParams)->off.port && !(*theParams)->on.port)
CopyRgn(theGWorld->clipRgn, theGWorld->visRgn);
DisposeRgn(tempRgn);
theGWorld->grafProcs = &gBottlenecks;
(*theParams)->dummy = theGWorld;
return noErr;
}
DisposeGWorld(theGWorld);
}
return memFullErr;
}
//=====================================================================================
// OSErr PostflightDrawing(JVDrawParamsHandle theParams)
//=====================================================================================
// Removes theParams from the local linked list of current drawing environments,
// disposing of the temporary destination port.
//=====================================================================================
extern OSErr PostflightDrawing(JVDrawParamsHandle theParams)
{
JVDrawParamsHandle params;
OSErr theErr = noErr;
if ((*theParams)->progress.aborted) theErr = codecAbortErr;
if ((*theParams)->dummy) DisposeGWorld((*theParams)->dummy);
if (theParams == gDrawParamsRoot) gDrawParamsRoot = (*theParams)->next;
else for (params = gDrawParamsRoot; params; params = (*params)->next)
if ((*params)->next == theParams) {
(*params)->next = (*theParams)->next;
break;
}
return theErr;
}
//=====================================================================================
// JVDrawParamsHandle FindParams(CGrafPtr thePort)
//=====================================================================================
// Locates the parameter set associated with the given port.
//=====================================================================================
static JVDrawParamsHandle FindParams(CGrafPtr thePort)
{
JVDrawParamsHandle theParams;
for (theParams = gDrawParamsRoot; theParams; theParams = (*theParams)->next)
if ((*theParams)->dummy == thePort) return theParams;
return nil;
}
//=====================================================================================
// OSErr FixBits(CGrafPtr, Boolean on)
//=====================================================================================
// Turns on/off the QuickTime 1.5 image bug fix for a given port.
//=====================================================================================
extern OSErr FixBits(CGrafPtr thePort, Boolean on)
{
FixedPortPtr theFixedPort;
if (gQTVersion != 0x0150) return noErr;
if (on) {
if (theFixedPort = (FixedPortPtr)NewPtrClear(sizeof(FixedPort))) {
theFixedPort->next = gFixedPortRoot;
gFixedPortRoot = theFixedPort;
theFixedPort->port = thePort;
if (theFixedPort->oldprocs = thePort->grafProcs)
theFixedPort->newprocs = *thePort->grafProcs;
else SetStdCProcs(&theFixedPort->newprocs);
theFixedPort->oldbits = theFixedPort->newprocs.bitsProc;
theFixedPort->newprocs.bitsProc = gJVFixedBitsProc;
thePort->grafProcs = &theFixedPort->newprocs;
} else return memFullErr;
} else {
for (theFixedPort = gFixedPortRoot; theFixedPort; theFixedPort = theFixedPort->next)
if (theFixedPort->port == thePort) break;
if (!theFixedPort) return paramErr;
thePort->grafProcs = theFixedPort->oldprocs;
if (theFixedPort == gFixedPortRoot) gFixedPortRoot = theFixedPort->next;
else {
for (theFixedPort = theFixedPort; theFixedPort->next;
theFixedPort = theFixedPort->next)
if (theFixedPort->next->port == thePort) break;
if (theFixedPort) theFixedPort->next = theFixedPort->next->next;
theFixedPort = theFixedPort->next;
}
DisposePtr((Ptr)theFixedPort);
}
return noErr;
}
//=====================================================================================
// pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode,
// RgnHandle mask)
//=====================================================================================
// Bottleneck routine to fix things under QuickTime 1.5 so that drawing cropped
// images works correctly. Thanks for Mark Krueger for the bugfix!
//=====================================================================================
static pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect,
short mode, RgnHandle mask)
{
long offsetH = srcRect->left, offsetV = srcRect->top, rb = src->rowBytes;
Rect saveSrcBounds = src->bounds, tmpSrcRect = *srcRect;
FixedPortPtr theFixedPort;
Ptr saveBaseAddr = nil;
for (theFixedPort = gFixedPortRoot; theFixedPort; theFixedPort = theFixedPort->next)
if (theFixedPort->port == (CGrafPtr)qd.thePort) break;
if (!theFixedPort) return;
if (offsetH || offsetV) {
if (rb & 0xc000) {
rb &= 0x3fff;
saveBaseAddr = src->baseAddr;
if (src->pmVersion == 2) LockPixels(&src);
if (src->pmVersion == 4)
src->baseAddr += offsetV * rb + ((offsetH * src->pixelSize) >> 3);
else if (src->pmVersion == 1)
src->baseAddr = StripAddress(src->baseAddr) + offsetV * rb +
((offsetH * src->pixelSize) >> 3);
OffsetRect(&tmpSrcRect, -offsetH, -offsetV);
} else {
BitMap *srcB = (BitMap *)src;
saveBaseAddr = srcB->baseAddr;
srcB->baseAddr += offsetH + (offsetV * rb);
OffsetRect(&tmpSrcRect, -offsetH, -offsetV);
}
}
src->bounds = tmpSrcRect;
CallQDBitsProc(theFixedPort->oldbits, (BitMap *)src, &tmpSrcRect, dstRect, mode, mask);
src->bounds = saveSrcBounds;
if (saveBaseAddr) src->baseAddr = saveBaseAddr;
}
//=====================================================================================
// pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode,
// RgnHandle mask)
//=====================================================================================
// Bottleneck routine for CopyBits.
//=====================================================================================
static pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode,
RgnHandle mask)
{
#if applec
#pragma unused(mode, mask)
#endif
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
PixMapHandle onPixMap = nil, offPixMap = nil;
Boolean scaling = false;
char offState;
if (!theParams || (*theParams)->progress.aborted ||
((*theParams)->progress.aborted = CheckAbort(theParams))) return;
PushPort();
(*theParams)->src = src;
(*theParams)->srcrect = *srcRect;
(*theParams)->dstrect = *dstRect;
if ((*theParams)->off.port) {
offPixMap = GetGWorldPixMap((*theParams)->off.port);
offState = GetPixelsState(offPixMap);
LockPixels(offPixMap);
scaling = !EqualSizeRect(&(*theParams)->bounds, &(*theParams)->off.outer);
}
if ((*theParams)->on.port) {
onPixMap = GetGWorldPixMap((*theParams)->on.port);
if (!scaling) scaling = !EqualSizeRect(&(*theParams)->bounds, &(*theParams)->on.outer);
}
if (Height(dstRect) > 8)
ShowScaleDither(scaling, (*theParams)->on.dither, true, theParams);
if ((*theParams)->quantize) FillHistogram(src);
if ((*theParams)->on.port && (*theParams)->off.port)
DrawOnAndOffscreen(src, srcRect, dstRect, theParams);
else if ((*theParams)->on.port) DrawOnscreen(src, srcRect, dstRect, theParams);
else if ((*theParams)->off.port) DrawOffscreen(src, srcRect, dstRect, theParams);
if (Height(dstRect) > 8)
ShowScaleDither(scaling, (*theParams)->on.dither, false, theParams);
if ((*theParams)->off.port) SetPixelsState(offPixMap, offState);
if (gSlideShow && !(*theParams)->progress.aborted)
(*theParams)->progress.aborted = CheckAbort(theParams);
PopPort();
}
//=====================================================================================
// void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
// JVDrawParamsHandle theParams)
//=====================================================================================
// Do CopyBits drawing for both onscreen and offscreen.
//=====================================================================================
static void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams)
{
PixMapHandle offPixMap = GetGWorldPixMap((*theParams)->off.port);
Rect onDstRect = *dstRect, offDstRect = *dstRect;
char hState = HGetState((Handle)offPixMap);
RgnHandle tempRgn;
PushPort();
MapRect(&onDstRect, &(*theParams)->bounds, &(*theParams)->on.outer);
MapRect(&offDstRect, &(*theParams)->bounds, &(*theParams)->off.outer);
MySetPort((*theParams)->off.port);
(*theParams)->dstrect = offDstRect;
CustomCopy(src, srcRect, &offDstRect, (*theParams)->off.dither, nil,
(*theParams)->quality);
if ((*theParams)->extra.port) {
Rect extraDstRect = *dstRect;
MapRect(&extraDstRect, &(*theParams)->bounds, &(*theParams)->extra.outer);
MySetPort((*theParams)->extra.port);
(*theParams)->dstrect = extraDstRect;
CustomCopy(src, srcRect, &extraDstRect, (*theParams)->extra.dither, nil,
(*theParams)->quality);
}
HLock((Handle)offPixMap);
(*theParams)->src = *offPixMap;
(*theParams)->srcrect = offDstRect;
(*theParams)->dstrect = onDstRect;
MySetPort((*theParams)->on.port);
DeviceLoop((*theParams)->on.port->visRgn, gDeviceCopy, (long)theParams, singleDevices);
if ((*theParams)->newupdates && (tempRgn = NewRgn())) {
RectRgn(tempRgn, &onDstRect);
DiffRgn((*theParams)->newupdates, tempRgn, (*theParams)->newupdates);
DisposeRgn(tempRgn);
}
HSetState((Handle)offPixMap, hState);
PopPort();
if (onDstRect.bottom >= (*theParams)->endprogress) (*theParams)->endprogress = 0;
}
//=====================================================================================
// void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
// JVDrawParamsHandle theParams)
//=====================================================================================
// Do CopyBits drawing for onscreen.
//=====================================================================================
static void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams)
{
#if applec
#pragma unused(src, srcRect)
#endif
Rect onDstRect = *dstRect;
RgnHandle tempRgn;
PushPort();
MapRect(&onDstRect, &(*theParams)->bounds, &(*theParams)->on.outer);
(*theParams)->dstrect = onDstRect;
MySetPort((*theParams)->on.port);
DeviceLoop((*theParams)->on.port->visRgn, gDeviceCopy, (long)theParams, singleDevices);
if ((*theParams)->newupdates && (tempRgn = NewRgn())) {
RectRgn(tempRgn, &onDstRect);
DiffRgn((*theParams)->newupdates, tempRgn, (*theParams)->newupdates);
DisposeRgn(tempRgn);
}
PopPort();
if (onDstRect.bottom >= (*theParams)->endprogress) (*theParams)->endprogress = 0;
}
//=====================================================================================
// void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
// JVDrawParamsHandle theParams)
//=====================================================================================
// Do CopyBits drawing for offscreen.
//=====================================================================================
static void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect,
JVDrawParamsHandle theParams)
{
Rect offDstRect = *dstRect;
PushPort();
MapRect(&offDstRect, &(*theParams)->bounds, &(*theParams)->off.outer);
(*theParams)->dstrect = offDstRect;
MySetPort((*theParams)->off.port);
CustomCopy(src, srcRect, &offDstRect, (*theParams)->off.dither, nil,
(*theParams)->quality);
if ((*theParams)->extra.port) {
Rect extraDstRect = *dstRect;
MapRect(&extraDstRect, &(*theParams)->bounds, &(*theParams)->extra.outer);
(*theParams)->dstrect = extraDstRect;
MySetPort((*theParams)->extra.port);
CustomCopy(src, srcRect, &extraDstRect, (*theParams)->extra.dither, nil,
(*theParams)->quality);
}
PopPort();
}
//=====================================================================================
// pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice,
// void *tempParams)
//=====================================================================================
// Stub for calling CustomCopy for each device in the device list.
//=====================================================================================
static pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice,
void *tempParams)
{
#if applec
#pragma unused(depth, deviceFlags)
#endif
JVDrawParamsHandle theParams = (JVDrawParamsHandle)tempParams;
Rect srcRect = (*theParams)->srcrect, dstRect = (*theParams)->dstrect;
GDHandle oldDevice = GetGDevice();
SetGDevice(targetDevice);
CustomCopy((*theParams)->src, &srcRect, &dstRect, (*theParams)->on.dither,
(*theParams)->on.port->visRgn, (*theParams)->quality);
SetGDevice(oldDevice);
}
//=====================================================================================
// Boolean IsGrayDevice(GDHandle theGDevice)
//=====================================================================================
// Checks an 8-bit device's color table and returns true if it's all grayscales.
//=====================================================================================
static Boolean IsGrayDevice(GDHandle theGDevice)
{
PixMapHandle thePixMap = (*theGDevice)->gdPMap;
ColorSpec *theSpec;
short i;
if ((*thePixMap)->pmTable && (*(*thePixMap)->pmTable)->ctSize == 255) {
theSpec = (*(*thePixMap)->pmTable)->ctTable;
for (i = 0; i < 256; i++) {
if (theSpec->rgb.red != theSpec->rgb.green ||
theSpec->rgb.red != theSpec->rgb.blue) return false;
theSpec++;
}
return true;
}
return false;
}
//=====================================================================================
// void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither,
// RgnHandle mask, short quality)
//=====================================================================================
// Do our custom copying.
//=====================================================================================
static void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither,
RgnHandle mask, short quality)
{
PixMapHandle dst = (*GetGDevice())->gdPMap;
Boolean oldState;
if ((*dst)->pixelType != RGBDirect) {
ITabHandle theITab = (*GetGDevice())->gdITable;
CTabHandle theCTab = (*dst)->pmTable;
if (theCTab && ((*dst)->pixelSize == 8))
if (!theITab || ((*theITab)->iTabRes != 5) ||
((*theITab)->iTabSeed != (*theCTab)->ctSeed))
MakeITable(nil, nil, 5);
}
ClipRect(dstRect);
RGBForeColor(&gBlack);
RGBBackColor(&gWhite);
SpinIndef();
switch (quality) {
case iqVHigh:
DrawVHighQuality(src, dst, srcRect, dstRect, dither, mask);
break;
case iqHigh:
DrawHighQuality(src, dst, srcRect, dstRect, dither, mask);
break;
case iqMedium:
oldState = GetQDxDispatchPatchState();
if (oldState) RemoveQDxDispatchPatch();
CallProperBitsProc((BitMap *)src, srcRect, dstRect,
dither ? srcCopy + ditherCopy : srcCopy, mask);
if (oldState) InstallQDxDispatchPatch(true);
break;
}
KeepSpinning();
return;
}
//=====================================================================================
// void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect,
// Boolean dither, RgnHandle mask)
//=====================================================================================
// Do very high-quality custom drawing.
//=====================================================================================
static void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect,
Rect *dstRect, Boolean dither, RgnHandle mask)
{
short srcDepth = (src->rowBytes & 0x8000) ? src->pixelSize : 1;
if (srcDepth == 32 && (dither || (*dst)->pixelSize == 32)) {
switch ((*dst)->pixelSize) {
case 8:
if (IsGrayDevice(GetGDevice())) break;
case 16:
case 32:
DoCustomCopy(src, *dst, srcRect, dstRect, false, (*dst)->pixelSize);
return;
}
}
CallProperBitsProc((BitMap *)src, srcRect, dstRect,
dither ? srcCopy + ditherCopy : srcCopy, mask);
}
//=====================================================================================
// void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect,
// Boolean dither, RgnHandle mask)
//=====================================================================================
// Do high-quality custom drawing.
//=====================================================================================
static void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect,
Rect *dstRect, Boolean dither, RgnHandle mask)
{
short srcDepth = (src->rowBytes & 0x8000) ? src->pixelSize : 1;
if ((srcDepth == 32) && (dither || (*dst)->pixelSize == 32)) {
switch ((*dst)->pixelSize) {
case 32:
break;
case 8:
if (IsGrayDevice(GetGDevice())) break;
case 16:
DoCustomCopy(src, *dst, srcRect, dstRect, true, (*dst)->pixelSize);
return;
}
}
CallProperBitsProc((BitMap *)src, srcRect, dstRect,
dither ? srcCopy + ditherCopy : srcCopy, mask);
}
//=====================================================================================
// void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state,
// JVDrawParamsHandle theParams)
//=====================================================================================
// Do high-quality custom drawing.
//=====================================================================================
static void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state,
JVDrawParamsHandle theParams)
{
if ((*theParams)->progress.prog.progressProc) {
if (scaling) CallICMProgressProc((*theParams)->progress.prog.progressProc,
codecProgressUpdateScaling, state,
(*theParams)->progress.prog.progressRefCon);
else if (dither) CallICMProgressProc((*theParams)->progress.prog.progressProc,
codecProgressUpdateDithering, state,
(*theParams)->progress.prog.progressRefCon);
}
}
//=====================================================================================
// void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect)
//=====================================================================================
// Sets the drawing parameters of the dst port to be indentical to those in the src
// port.
//=====================================================================================
static void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect)
{
Point thePoint;
long x, y;
MySetPort(dst);
CopyRgn(src->clipRgn, dst->clipRgn);
MapRgn(dst->clipRgn, srcRect, dstRect);
thePoint = src->pnLoc;
MapPt(&thePoint, srcRect, dstRect);
MoveTo(thePoint.h, thePoint.v);
x = (long)src->pnSize.h * (long)Width(dstRect) / (long)Width(srcRect);
y = (long)src->pnSize.v * (long)Height(dstRect) / (long)Height(srcRect);
PenSize(x ? x : 1, y ? y : 1);
PenMode(src->pnMode);
TextFont(src->txFont);
TextFace(src->txFace);
TextMode(src->txMode);
x = (long)src->txSize * (long)Height(dstRect) / (long)Height(srcRect);
TextSize(x ? x : 1);
y = (long)src->spExtra * (long)Width(dstRect) / (long)Width(srcRect);
SpaceExtra(y ? y : 1);
if (src->portVersion & 0x8000) {
PixPatHandle thePixPat;
if (DiffPixPat(src->pnPixPat, dst->pnPixPat) && (thePixPat = NewPixPat())) {
CopyPixPat(src->pnPixPat, thePixPat);
PenPixPat(thePixPat);
}
if (DiffPixPat(src->bkPixPat, dst->bkPixPat) && (thePixPat = NewPixPat())) {
CopyPixPat(src->bkPixPat, thePixPat);
BackPixPat(thePixPat);
}
RGBForeColor(&src->rgbFgColor);
RGBBackColor(&src->rgbBkColor);
} else {
PenPat(&((GrafPtr)src)->pnPat);
BackPat(&((GrafPtr)src)->bkPat);
ForeColor(src->fgColor);
BackColor(src->bkColor);
}
}
//=====================================================================================
// Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2)
//=====================================================================================
// Compares two PixPatHandles; returns true if they're different.
//=====================================================================================
static Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2)
{
Size size1, size2;
ulong *p1, *p2;
if (!pp1) return false;
if (!pp2) return true;
if ((*pp1)->patType != (*pp2)->patType) return true;
if (!(*pp1)->patData) return false;
if (!(*pp2)->patData) return true;
size1 = GetHandleSize((*pp1)->patData);
size2 = GetHandleSize((*pp2)->patData);
if (size1 != size2) return true;
p1 = (ulong *)*(*pp1)->patData;
p2 = (ulong *)*(*pp2)->patData;
size1 >>= 2;
while (size1--) if (*p1++ != *p2++) return true;
return false;
}
//=====================================================================================
// pascal void JVTextProc(short count, void *textAddr, Point numer, Point denom)
//=====================================================================================
// Bottleneck to handle text drawing.
//=====================================================================================
static pascal void JVTextProc(short count, Ptr textAddr, Point numer, Point denom)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect bounds, outer;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
CallProperTextProc(count, textAddr, numer, denom);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
CallProperTextProc(count, textAddr, numer, denom);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
CallProperTextProc(count, textAddr, numer, denom);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVLineProc(Point newPt)
//=====================================================================================
// Bottleneck to handle line drawing.
//=====================================================================================
static pascal void JVLineProc(Point newPt)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect bounds, outer;
Point thePoint;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
thePoint = newPt;
MapPt(&thePoint, &bounds, &outer);
CallProperLineProc(thePoint);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
thePoint = newPt;
MapPt(&thePoint, &bounds, &outer);
CallProperLineProc(thePoint);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
thePoint = newPt;
MapPt(&thePoint, &bounds, &outer);
CallProperLineProc(thePoint);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVRectProc(GrafVerb verb, Rect *r)
//=====================================================================================
// Bottleneck to handle rectangle drawing.
//=====================================================================================
static pascal void JVRectProc(GrafVerb verb, Rect *r)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect theRect, bounds, outer;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRectProc(verb, &theRect);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRectProc(verb, &theRect);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRectProc(verb, &theRect);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight)
//=====================================================================================
// Bottleneck to handle rounded rectangle drawing.
//=====================================================================================
static pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect theRect, bounds, outer;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVOvalProc(GrafVerb verb, Rect *r)
//=====================================================================================
// Bottleneck to handle oval drawing.
//=====================================================================================
static pascal void JVOvalProc(GrafVerb verb, Rect *r)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect theRect, bounds, outer;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperOvalProc(verb, &theRect);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperOvalProc(verb, &theRect);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperOvalProc(verb, &theRect);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle)
//=====================================================================================
// Bottleneck to handle arc drawing.
//=====================================================================================
static pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect theRect, bounds, outer;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperArcProc(verb, &theRect, startAngle, arcAngle);
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperArcProc(verb, &theRect, startAngle, arcAngle);
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
theRect = *r;
MapRect(&theRect, &bounds, &outer);
CallProperArcProc(verb, &theRect, startAngle, arcAngle);
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVPolyProc(GrafVerb verb, PolyHandle poly)
//=====================================================================================
// Bottleneck to handle polygon drawing.
//=====================================================================================
static pascal void JVPolyProc(GrafVerb verb, PolyHandle poly)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect bounds, outer;
PolyHandle thePoly;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
thePoly = poly;
if (HandToHand((Handle *)&thePoly) == noErr) {
MapPoly(thePoly, &bounds, &outer);
CallProperPolyProc(verb, thePoly);
DisposeHandle((Handle)thePoly);
}
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
thePoly = poly;
if (HandToHand((Handle *)&thePoly) == noErr) {
MapPoly(thePoly, &bounds, &outer);
CallProperPolyProc(verb, thePoly);
DisposeHandle((Handle)thePoly);
}
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
thePoly = poly;
if (HandToHand((Handle *)&thePoly) == noErr) {
MapPoly(thePoly, &bounds, &outer);
CallProperPolyProc(verb, thePoly);
DisposeHandle((Handle)thePoly);
}
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn)
//=====================================================================================
// Bottleneck to handle polygon drawing.
//=====================================================================================
static pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn)
{
JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort);
Rect bounds, outer;
RgnHandle theRgn;
if (!theParams) return;
bounds = (*theParams)->bounds;
KeepSpinning();
if ((*theParams)->off.port) {
PushPort();
outer = (*theParams)->off.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer);
if (theRgn = NewRgn()) {
CopyRgn(rgn, theRgn);
MapRgn(theRgn, &bounds, &outer);
CallProperRgnProc(verb, theRgn);
DisposeHandle((Handle)theRgn);
}
PopPort();
if ((*theParams)->extra.port) {
PushPort();
outer = (*theParams)->extra.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer);
if (theRgn = NewRgn()) {
CopyRgn(rgn, theRgn);
MapRgn(theRgn, &bounds, &outer);
CallProperRgnProc(verb, theRgn);
DisposeHandle((Handle)theRgn);
}
PopPort();
}
}
KeepSpinning();
if ((*theParams)->on.port) {
PushPort();
outer = (*theParams)->on.outer;
CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer);
if (theRgn = NewRgn()) {
CopyRgn(rgn, theRgn);
MapRgn(theRgn, &bounds, &outer);
CallProperRgnProc(verb, theRgn);
DisposeHandle((Handle)theRgn);
}
PopPort();
}
KeepSpinning();
}
//=====================================================================================
// void CallProperBitsProc(BitMap *src, Rect *srcRect, Rect *dstRect, short mode,
// RgnHandle mask)
//=====================================================================================
// Call StdBits, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperBitsProc(BitMap *src, Rect *srcRect, Rect *dstRect, short mode,
RgnHandle mask)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->bitsProc)
CallQDBitsProc(((CGrafPtr)qd.thePort)->grafProcs->bitsProc, (BitMap *)src,
srcRect, dstRect, mode, mask);
else StdBits((BitMap *)src, srcRect, dstRect, mode, mask);
}
//=====================================================================================
// void CallProperTextProc(short count, const void *textAddr, Point numer, Point denom)
//=====================================================================================
// Call StdText, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperTextProc(short count, Ptr textAddr, Point numer, Point denom)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->textProc)
CallQDTextProc(((CGrafPtr)qd.thePort)->grafProcs->textProc, count, textAddr,
numer, denom);
else StdText(count, textAddr, numer, denom);
}
//=====================================================================================
// void CallProperLineProc(Point newPt)
//=====================================================================================
// Call StdLine, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperLineProc(Point newPt)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->lineProc)
CallQDLineProc(((CGrafPtr)qd.thePort)->grafProcs->lineProc, newPt);
else StdLine(newPt);
}
//=====================================================================================
// void CallProperRectProc(GrafVerb verb, Rect *r)
//=====================================================================================
// Call StdRect, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperRectProc(GrafVerb verb, Rect *r)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rectProc)
CallQDRectProc(((CGrafPtr)qd.thePort)->grafProcs->rectProc, verb, r);
else StdRect(verb, r);
}
//=====================================================================================
// void CallProperRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight)
//=====================================================================================
// Call StdRRect, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rRectProc)
CallQDRRectProc(((CGrafPtr)qd.thePort)->grafProcs->rRectProc, verb, r, ovalWidth,
ovalHeight);
else StdRRect(verb, r, ovalWidth, ovalHeight);
}
//=====================================================================================
// void CallProperOvalProc(GrafVerb verb, Rect *r)
//=====================================================================================
// Call StdOval, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperOvalProc(GrafVerb verb, Rect *r)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->ovalProc)
CallQDOvalProc(((CGrafPtr)qd.thePort)->grafProcs->ovalProc, verb, r);
else StdOval(verb, r);
}
//=====================================================================================
// void CallProperArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle)
//=====================================================================================
// Call StdArc, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->arcProc)
CallQDArcProc(((CGrafPtr)qd.thePort)->grafProcs->arcProc, verb, r, startAngle,
arcAngle);
else StdArc(verb, r, startAngle, arcAngle);
}
//=====================================================================================
// void CallProperPolyProc(GrafVerb verb, PolyHandle poly)
//=====================================================================================
// Call StdPoly, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperPolyProc(GrafVerb verb, PolyHandle poly)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->polyProc)
CallQDPolyProc(((CGrafPtr)qd.thePort)->grafProcs->polyProc, verb, poly);
else StdPoly(verb, poly);
}
//=====================================================================================
// void CallProperRgnProc(GrafVerb verb, RgnHandle rgn)
//=====================================================================================
// Call StdRgn, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperRgnProc(GrafVerb verb, RgnHandle rgn)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rgnProc)
CallQDRgnProc(((CGrafPtr)qd.thePort)->grafProcs->rgnProc, verb, rgn);
else StdRgn(verb, rgn);
}
//=====================================================================================
// void CallProperPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
// RgnHandle mask, PixMap *matte, Rect *matteRect, short flags)
//=====================================================================================
// Call StdRgn, or a bottleneck function, as appropriate for the current port.
//=====================================================================================
extern void CallProperPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode,
RgnHandle mask, PixMap *matte, Rect *matteRect, short flags)
{
if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->newProc1)
CallStdPixProc((StdPixUPP)((CGrafPtr)qd.thePort)->grafProcs->newProc1, src,
srcRect, matrix, mode, mask, matte, matteRect, flags);
else StdPix(src, srcRect, matrix, mode, mask, matte, matteRect, flags);
}