1 line
16 KiB
C
1 line
16 KiB
C
/*********************************************************/
|
|
/* This source code copyright (c) 1991-2001, Aaron Giles */
|
|
/* See the Read Me file for licensing information. */
|
|
/* Contact email: mac@aarongiles.com */
|
|
/*********************************************************/
|
|
|
|
#define SystemSevenOrLater 1
|
|
|
|
#include <Aliases.h>
|
|
#include <Components.h>
|
|
#include <Errors.h>
|
|
#include <ImageCompression.h>
|
|
#include <QuickTimeComponents.h>
|
|
#include <Memory.h>
|
|
#include <MixedMode.h>
|
|
#include <QuickDraw.h>
|
|
|
|
/*
|
|
* Macros and typedefs
|
|
*
|
|
*/
|
|
|
|
#define JFIFPreviewVersion 0x00010001
|
|
|
|
#define kBufferSize 20
|
|
#define Height(r) ((r)->bottom - (r)->top)
|
|
#define Width(r) ((r)->right - (r)->left)
|
|
|
|
#define pnotDisplayPreview 1
|
|
|
|
typedef unsigned char uchar;
|
|
typedef unsigned short ushort;
|
|
typedef unsigned long ulong;
|
|
|
|
enum {
|
|
uppPreviewOpenProcInfo = kPascalStackBased
|
|
| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
|
|
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))),
|
|
uppPreviewCloseProcInfo = kPascalStackBased
|
|
| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
|
|
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
|
|
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance))),
|
|
uppPreviewCanDoProcInfo = kPascalStackBased
|
|
| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
|
|
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))),
|
|
uppPreviewDisplayProcInfo = kPascalStackBased
|
|
| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
|
|
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
|
|
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(OSType)))
|
|
| STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Handle)))
|
|
| STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(const Rect *)))
|
|
};
|
|
|
|
/*
|
|
* Function prototypes
|
|
*
|
|
*/
|
|
|
|
extern pascal ComponentResult EntryPoint(ComponentParameters *params, Handle storage);
|
|
pascal ComponentResult JFIFPreviewOpen(ComponentInstance self);
|
|
pascal ComponentResult JFIFPreviewClose(Handle theBuffer, ComponentInstance self);
|
|
pascal ComponentResult JFIFPreviewCanDo(short selector);
|
|
pascal ComponentResult JFIFPreviewShow(Handle theBuffer, OSType dataType, Handle data,
|
|
const Rect *inHere);
|
|
OSErr LoadPreview(Handle *theData, short theFile, uchar *buffer, short width, short height);
|
|
OSErr LoadPreviewExtension(Handle *theData, short theFile, long theSize);
|
|
OSErr MakePreviewGWorld(GWorldPtr *theGWorld, const Rect *inHere, short width, short height);
|
|
OSErr DrawPreview(Handle previewData, const Rect *inHere, short width, short height);
|
|
uchar *ParseJPEG(uchar *theAdr, long theLen, uchar theCode);
|
|
OSErr MakeImageDescription(ImageDescriptionHandle *theDesc, Handle previewData);
|
|
OSErr DrawJPEGPreview(Handle previewData, const Rect *inHere);
|
|
OSErr Draw1CompPreview(Handle previewData, const Rect *inHere);
|
|
OSErr Draw3CompPreview(Handle previewData, const Rect *inHere);
|
|
|
|
#if defined(powerc) || defined(__powerc)
|
|
enum {
|
|
uppMainProcInfo = kPascalStackBased
|
|
| RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
|
|
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *)))
|
|
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
|
|
};
|
|
RoutineDescriptor EntryPointRD = BUILD_ROUTINE_DESCRIPTOR(uppMainProcInfo, EntryPoint);
|
|
#endif
|
|
|
|
/*
|
|
* This is the entry point where we dispatch the request to the appropriate function
|
|
*
|
|
*/
|
|
|
|
extern pascal ComponentResult EntryPoint(ComponentParameters *params, Handle storage)
|
|
{
|
|
ComponentFunctionUPP theRoutine = nil;
|
|
ComponentResult theResult = noErr;
|
|
|
|
switch (params->what) {
|
|
case kComponentOpenSelect:
|
|
if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewOpen,
|
|
uppPreviewOpenProcInfo, GetCurrentISA()))
|
|
theResult = CallComponentFunction(params, theRoutine);
|
|
break;
|
|
case kComponentCloseSelect:
|
|
if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewClose,
|
|
uppPreviewCloseProcInfo, GetCurrentISA()))
|
|
theResult = CallComponentFunctionWithStorage(storage, params, theRoutine);
|
|
break;
|
|
case kComponentCanDoSelect:
|
|
if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewCanDo,
|
|
uppPreviewCanDoProcInfo, GetCurrentISA()))
|
|
theResult = CallComponentFunction(params, theRoutine);
|
|
break;
|
|
case kComponentVersionSelect:
|
|
return JFIFPreviewVersion;
|
|
case pnotDisplayPreview:
|
|
if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewShow,
|
|
uppPreviewDisplayProcInfo, GetCurrentISA()))
|
|
theResult = CallComponentFunctionWithStorage(storage, params, theRoutine);
|
|
break;
|
|
default:
|
|
theResult = badComponentSelector;
|
|
break;
|
|
}
|
|
if (theRoutine) DisposeRoutineDescriptor(theRoutine);
|
|
return theResult;
|
|
}
|
|
|
|
/*
|
|
* Open Component function: Allocate our global storage
|
|
*
|
|
*/
|
|
|
|
pascal ComponentResult JFIFPreviewOpen(ComponentInstance self)
|
|
{
|
|
Handle theBuffer;
|
|
|
|
if (!(theBuffer = NewHandle(kBufferSize))) return MemError();
|
|
SetComponentInstanceStorage(self, theBuffer);
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* Close Component function: Dispose of our global storage
|
|
*
|
|
*/
|
|
|
|
pascal ComponentResult JFIFPreviewClose(Handle theBuffer, ComponentInstance self)
|
|
{
|
|
#if applec
|
|
#pragma unused(self)
|
|
#endif
|
|
if (theBuffer) DisposeHandle(theBuffer);
|
|
return noErr;
|
|
}
|
|
|
|
/*
|
|
* Can Do function: return 1 for any selector we can handle
|
|
*
|
|
*/
|
|
|
|
pascal ComponentResult JFIFPreviewCanDo(short selector)
|
|
{
|
|
switch (selector) {
|
|
case kComponentOpenSelect:
|
|
case kComponentCloseSelect:
|
|
case kComponentCanDoSelect:
|
|
case kComponentVersionSelect:
|
|
case pnotDisplayPreview:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Show preview function: accept an alias and extract a preview from it
|
|
*
|
|
* INTERESTING FACT:
|
|
*
|
|
* If we return an error, QuickTime will go ahead and use any custom icon as the preview,
|
|
* so we return an error if there is no JFIF preview, in order to preserve this
|
|
* functionality
|
|
*
|
|
*/
|
|
|
|
pascal ComponentResult JFIFPreviewShow(Handle theBuffer, OSType dataType, Handle data,
|
|
const Rect *inHere)
|
|
{
|
|
long theLength = kBufferSize;
|
|
short fileRef, width, height;
|
|
Handle previewData;
|
|
Boolean isFolder;
|
|
FSSpec theFile;
|
|
OSErr theErr;
|
|
uchar *buf;
|
|
|
|
if (dataType != rAliasType) return paramErr;
|
|
HLock(theBuffer);
|
|
buf = (uchar *)*theBuffer;
|
|
theErr = ResolveAlias(nil, (AliasHandle)data, &theFile, &isFolder);
|
|
if (theErr == noErr) {
|
|
theErr = FSpOpenDF(&theFile, fsRdPerm, &fileRef);
|
|
if (theErr == noErr) {
|
|
theErr = FSRead(fileRef, &theLength, buf);
|
|
if (theErr == noErr &&
|
|
buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff &&
|
|
buf[3] == 0xe0 && buf[6] == 'J' && buf[7] == 'F' &&
|
|
buf[8] == 'I' && buf[9] == 'F' && buf[10] == 0) {
|
|
width = buf[18];
|
|
height = buf[19];
|
|
if (width && height) {
|
|
theErr = LoadPreview(&previewData, fileRef, buf, width, height);
|
|
if (theErr == noErr) {
|
|
theErr = DrawPreview(previewData, inHere, width, height);
|
|
DisposeHandle(previewData);
|
|
}
|
|
} else {
|
|
SetFPos(fileRef, fsFromStart, 4 + (buf[4] << 8) + buf[5]);
|
|
theLength = 10;
|
|
theErr = FSRead(fileRef, &theLength, buf);
|
|
if (theErr == noErr &&
|
|
buf[0] == 0xff && buf[1] == 0xe0 && buf[4] == 'J' &&
|
|
buf[5] == 'F' && buf[6] == 'X' && buf[7] == 'X' && buf[8] == 0) {
|
|
theErr = LoadPreviewExtension(&previewData, fileRef,
|
|
(buf[2] << 8) + buf[3] - 8);
|
|
if (theErr == noErr) {
|
|
switch (buf[9]) {
|
|
case 0x10:
|
|
theErr = DrawJPEGPreview(previewData, inHere);
|
|
break;
|
|
case 0x11:
|
|
theErr = Draw1CompPreview(previewData, inHere);
|
|
break;
|
|
case 0x13:
|
|
theErr = Draw3CompPreview(previewData, inHere);
|
|
break;
|
|
}
|
|
DisposeHandle(previewData);
|
|
}
|
|
} else theErr = memFullErr; // fake an error if no preview around
|
|
}
|
|
}
|
|
FSClose(fileRef);
|
|
}
|
|
}
|
|
HUnlock(theBuffer);
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* LoadPreview: Allocate a new handle and read the preview data into it
|
|
*
|
|
*/
|
|
|
|
OSErr LoadPreview(Handle *theData, short theFile, uchar *buffer, short width, short height)
|
|
{
|
|
#if applec
|
|
#pragma unused(buffer)
|
|
#endif
|
|
long theSize = (long)width * (long)height * 3L;
|
|
OSErr theErr = noErr;
|
|
|
|
if (!(*theData = NewHandle(theSize))) {
|
|
*theData = TempNewHandle(theSize, &theErr);
|
|
if (theErr != noErr) return theErr;
|
|
}
|
|
HLock(*theData);
|
|
theErr = FSRead(theFile, &theSize, **theData);
|
|
HUnlock(*theData);
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* LoadPreviewExtension: Allocate a new handle and read the preview extension data into it
|
|
*
|
|
*/
|
|
|
|
OSErr LoadPreviewExtension(Handle *theData, short theFile, long theSize)
|
|
{
|
|
OSErr theErr = noErr;
|
|
|
|
if (!(*theData = NewHandle(theSize))) {
|
|
*theData = TempNewHandle(theSize, &theErr);
|
|
if (theErr != noErr) return theErr;
|
|
}
|
|
HLock(*theData);
|
|
theErr = FSRead(theFile, &theSize, **theData);
|
|
HUnlock(*theData);
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* MakePreviewGWorld: Create a GWorld the proper size for the given preview width and
|
|
* height
|
|
*
|
|
*/
|
|
|
|
OSErr MakePreviewGWorld(GWorldPtr *theGWorld, const Rect *inHere, short width, short height)
|
|
{
|
|
Rect GWBounds;
|
|
OSErr theErr;
|
|
|
|
GWBounds.left = GWBounds.top = 0;
|
|
GWBounds.bottom = (height > Height(inHere)) ? Height(inHere) : height;
|
|
GWBounds.right = (width > Width(inHere)) ? Width(inHere) : width;
|
|
theErr = NewGWorld(theGWorld, 32, &GWBounds, nil, nil, 0);
|
|
if (theErr != noErr)
|
|
theErr = NewGWorld(theGWorld, 32, &GWBounds, nil, nil, useTempMem);
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* DrawPreview: Make a GWorld and copy the preview data into it; then do a CopyBits into
|
|
* the requested area
|
|
*
|
|
*/
|
|
|
|
OSErr DrawPreview(Handle previewData, const Rect *inHere, short width, short height)
|
|
{
|
|
PixMapHandle thePixMap, dstPixMap;
|
|
uchar *bufPtr, *pixPtr, *pixBase;
|
|
Rect GWBounds, dstRect = *inHere;
|
|
short rowBytes, r, c, oldWidth;
|
|
GWorldPtr theGWorld, curGWorld;
|
|
char mmuMode = true32b;
|
|
OSErr theErr = noErr;
|
|
GDHandle curDevice;
|
|
|
|
if (!(oldWidth = width)) {
|
|
width = *(uchar *)*previewData;
|
|
height = *((uchar *)*previewData + 1);
|
|
}
|
|
theErr = MakePreviewGWorld(&theGWorld, inHere, width, height);
|
|
if (theErr == noErr) {
|
|
GWBounds = theGWorld->portRect;
|
|
LockPixels(thePixMap = GetGWorldPixMap(theGWorld));
|
|
pixBase = (uchar *)GetPixBaseAddr(thePixMap);
|
|
rowBytes = (*thePixMap)->rowBytes & 0x3fff;
|
|
bufPtr = (uchar *)StripAddress(*previewData);
|
|
if (!oldWidth) bufPtr++;
|
|
SwapMMUMode(&mmuMode);
|
|
for (r = 0; r < GWBounds.bottom; r++) {
|
|
pixPtr = pixBase;
|
|
for (c = 0; c < GWBounds.right; c++) {
|
|
pixPtr++;
|
|
*pixPtr++ = *bufPtr++;
|
|
*pixPtr++ = *bufPtr++;
|
|
*pixPtr++ = *bufPtr++;
|
|
}
|
|
bufPtr += 3L * (long)(width - GWBounds.right);
|
|
pixBase += rowBytes;
|
|
}
|
|
SwapMMUMode(&mmuMode);
|
|
dstRect.left += (Width(inHere) - GWBounds.right) >> 1;
|
|
dstRect.top += (Height(inHere) - GWBounds.bottom) >> 1;
|
|
dstRect.right = dstRect.left + GWBounds.right;
|
|
dstRect.bottom = dstRect.top + GWBounds.bottom;
|
|
GetGWorld(&curGWorld, &curDevice);
|
|
dstPixMap = GetGWorldPixMap(curGWorld);
|
|
CopyBits((BitMap *)*thePixMap, (BitMap *)*dstPixMap, &GWBounds, &dstRect,
|
|
srcCopy + ditherCopy, nil);
|
|
DisposeGWorld(theGWorld);
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* ParseJPEG: returns a pointer to the first instance of the specified code in the
|
|
* given JPEG stream
|
|
*
|
|
*/
|
|
|
|
uchar *ParseJPEG(uchar *theAdr, long theLen, uchar theCode)
|
|
{
|
|
uchar *theEnd = theAdr + theLen;
|
|
long theSize;
|
|
|
|
while (true) {
|
|
while ((*theAdr++ != 0xff) && (theAdr < theEnd));
|
|
if (theAdr >= theEnd) return nil;
|
|
while (*theAdr == 0xff) theAdr++;
|
|
if (theAdr >= theEnd) return nil;
|
|
if (*theAdr == theCode) break;
|
|
else if (*theAdr == 0xd9) return nil;
|
|
else if ((*theAdr <= 0x01) || ((*theAdr >= 0xd0) && (*theAdr <= 0xd8))) {
|
|
theAdr++;
|
|
continue;
|
|
}
|
|
theAdr++;
|
|
if ((theSize = (*theAdr << 8) + *(theAdr + 1)) < 0) return nil;
|
|
if ((theAdr + theSize) >= theEnd) {
|
|
*(theAdr - 1) = 0xd9;
|
|
return nil;
|
|
} else theAdr += theSize;
|
|
}
|
|
theAdr += 3;
|
|
return theAdr;
|
|
}
|
|
|
|
/*
|
|
* MakeImageDescription: create an image description record for the given JPEG image
|
|
*
|
|
*/
|
|
|
|
OSErr MakeImageDescription(ImageDescriptionHandle *theDesc, Handle previewData)
|
|
{
|
|
long theLen = GetHandleSize(previewData);
|
|
CodecInfo theInfo;
|
|
uchar *theData;
|
|
short theCode;
|
|
OSErr theErr;
|
|
|
|
theErr = GetCodecInfo(&theInfo, 'jpeg', 0);
|
|
if (theErr == noErr) {
|
|
*theDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
|
|
if (!*theDesc) {
|
|
*theDesc = (ImageDescriptionHandle)TempNewHandle(sizeof(ImageDescription), &theErr);
|
|
if (theErr != noErr) return theErr;
|
|
}
|
|
for (theCode = 0xc0; theCode < 0xd0; theCode++)
|
|
if (theData = ParseJPEG((uchar *)*previewData, theLen, theCode)) break;
|
|
if (theCode != 0xd0) {
|
|
(**theDesc)->idSize = sizeof(ImageDescription);
|
|
(**theDesc)->cType = 'jpeg';
|
|
(**theDesc)->resvd1 = (**theDesc)->resvd2 = (**theDesc)->dataRefIndex = 0;
|
|
BlockMove(theInfo.typeName, (**theDesc)->name, 32);
|
|
(**theDesc)->version = theInfo.version;
|
|
(**theDesc)->revisionLevel = theInfo.revisionLevel;
|
|
(**theDesc)->vendor = theInfo.vendor;
|
|
(**theDesc)->temporalQuality = 0;
|
|
(**theDesc)->spatialQuality = 0x200L;
|
|
(**theDesc)->width = (theData[3] << 8) + theData[4];
|
|
(**theDesc)->height = (theData[1] << 8) + theData[2];
|
|
(**theDesc)->hRes = (**theDesc)->vRes = 0x480000L;
|
|
(**theDesc)->dataSize = theLen;
|
|
(**theDesc)->frameCount = 1;
|
|
(**theDesc)->depth = 32;
|
|
(**theDesc)->clutID = -1;
|
|
} else theErr = memFullErr;
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* DrawJPEGPreview: draws a preview image in JPEG format
|
|
*
|
|
*/
|
|
|
|
OSErr DrawJPEGPreview(Handle previewData, const Rect *inHere)
|
|
{
|
|
Rect srcRect, dstRect = *inHere;
|
|
ImageDescriptionHandle theDesc;
|
|
PixMapHandle thePixMap;
|
|
MatrixRecord theMatrix;
|
|
OSErr theErr = noErr;
|
|
GWorldPtr curGWorld;
|
|
short width, height;
|
|
GDHandle curDevice;
|
|
|
|
theErr = MakeImageDescription(&theDesc, previewData);
|
|
if (theErr == noErr) {
|
|
width = (*theDesc)->width;
|
|
height = (*theDesc)->height;
|
|
srcRect.left = srcRect.top = 0;
|
|
srcRect.bottom = (height > Height(inHere)) ? Height(inHere) : height;
|
|
srcRect.right = (width > Width(inHere)) ? Width(inHere) : width;
|
|
dstRect.left += (Width(inHere) - srcRect.right) >> 1;
|
|
dstRect.top += (Height(inHere) - srcRect.bottom) >> 1;
|
|
dstRect.right = dstRect.left + srcRect.right;
|
|
dstRect.bottom = dstRect.top + srcRect.bottom;
|
|
GetGWorld(&curGWorld, &curDevice);
|
|
thePixMap = GetGWorldPixMap(curGWorld);
|
|
RectMatrix(&theMatrix, &srcRect, &dstRect);
|
|
HLock(previewData);
|
|
theErr = FDecompressImage(StripAddress(*previewData), theDesc, thePixMap, &srcRect,
|
|
&theMatrix, srcCopy + ditherCopy, nil, nil, nil, codecHighQuality, anyCodec,
|
|
GetHandleSize(previewData), nil, nil);
|
|
HUnlock(previewData);
|
|
DisposeHandle((Handle)theDesc);
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* Draw1CompPreview: draws a preview image 256-color palette format
|
|
*
|
|
*/
|
|
|
|
OSErr Draw1CompPreview(Handle previewData, const Rect *inHere)
|
|
{
|
|
short rowBytes, r, c, width, height;
|
|
ulong *pixPtr, *pixBase, *theColor;
|
|
PixMapHandle thePixMap, dstPixMap;
|
|
Rect GWBounds, dstRect = *inHere;
|
|
GWorldPtr theGWorld, curGWorld;
|
|
uchar *bufPtr, *colPtr;
|
|
char mmuMode = true32b;
|
|
OSErr theErr = noErr;
|
|
Handle colorsHandle;
|
|
GDHandle curDevice;
|
|
|
|
colorsHandle = NewHandle(256 * sizeof(long));
|
|
if (!colorsHandle) {
|
|
colorsHandle = TempNewHandle(256 * sizeof(long), &theErr);
|
|
if (theErr != noErr) return theErr;
|
|
}
|
|
width = *(uchar *)*previewData;
|
|
height = *((uchar *)*previewData + 1);
|
|
theErr = MakePreviewGWorld(&theGWorld, inHere, width, height);
|
|
if (theErr == noErr) {
|
|
GWBounds = theGWorld->portRect;
|
|
LockPixels(thePixMap = GetGWorldPixMap(theGWorld));
|
|
pixBase = (ulong *)GetPixBaseAddr(thePixMap);
|
|
rowBytes = (*thePixMap)->rowBytes & 0x3fff;
|
|
bufPtr = (uchar *)StripAddress(*previewData) + 2;
|
|
theColor = (ulong *)(colPtr = (uchar *)StripAddress(*colorsHandle));
|
|
for (c = 0; c < 256; c++) {
|
|
*colPtr++ = 0;
|
|
*colPtr++ = *bufPtr++;
|
|
*colPtr++ = *bufPtr++;
|
|
*colPtr++ = *bufPtr++;
|
|
}
|
|
SwapMMUMode(&mmuMode);
|
|
for (r = 0; r < GWBounds.bottom; r++) {
|
|
pixPtr = pixBase;
|
|
for (c = 0; c < GWBounds.right; c++) *pixPtr++ = theColor[*bufPtr++];
|
|
bufPtr += 3L * (long)(width - GWBounds.right);
|
|
pixBase += rowBytes >> 2;
|
|
}
|
|
SwapMMUMode(&mmuMode);
|
|
dstRect.left += (Width(inHere) - GWBounds.right) >> 1;
|
|
dstRect.top += (Height(inHere) - GWBounds.bottom) >> 1;
|
|
dstRect.right = dstRect.left + GWBounds.right;
|
|
dstRect.bottom = dstRect.top + GWBounds.bottom;
|
|
GetGWorld(&curGWorld, &curDevice);
|
|
dstPixMap = GetGWorldPixMap(curGWorld);
|
|
CopyBits((BitMap *)*thePixMap, (BitMap *)*dstPixMap, &GWBounds, &dstRect,
|
|
srcCopy + ditherCopy, nil);
|
|
DisposeGWorld(theGWorld);
|
|
}
|
|
return theErr;
|
|
}
|
|
|
|
/*
|
|
* Draw3CompPreview: draws a preview image 24-bit color format
|
|
*
|
|
*/
|
|
|
|
OSErr Draw3CompPreview(Handle previewData, const Rect *inHere)
|
|
{
|
|
return DrawPreview(previewData, inHere, 0, 0);
|
|
}
|