home *** CD-ROM | disk | FTP | other *** search
- /*
- File: CodecLibrary.c
-
- Contains: Graphics library for QuickTime decompression of QuickDraw GX
- data.
-
- This library uses QuickTime compression and decompression to
- image QuickDraw GX data. The basic technique is to encapsulate
- the QuickDraw GX image in a compressed data format using the
- object flattening functions from QuickDraw GX. Once the
- compressed image data is created, it may be passed to the
- QuickDraw GX codec and drawn using the QuickTime image
- compression functions or embedded within a QuickDraw picture
- and drawn using the DrawPicture function. In either case, the
- compressed data is passed to the the low-level QuickDraw
- drawing routines through the StdPix bottleneck routine. StdPix
- decompresses the data using the QuickDraw GX codec and passes
- the decompressed data to the bitsProc bottleneck routine when
- rendering the image.
-
- Written by: Mike Reed
-
- Copyright: © 1995-1997 by Apple Computer, Inc., all rights reserved.
-
- Writers:
-
- (jtd) John Daggett
- (DH) David Hayward
- (IK) Ingrid Kelly
-
- Change History (most recent first):
-
- <5> 6/1/97 IK Modify printing routines for GXGraphics 1.1.6.
- <4> 4/8/97 DH Minor fix.
- <3> 2/6/97 DH Added ShapeToPICTWithShape.
- <2> 9/14/95 jtd Replaced boolean with Boolean.
- <1> 9/14/95 jtd First checked in.
- */
-
- #include <Drag.h>
- #include <Gestalt.h>
- #include <GXGraphics.h>
- #include <ImageCompression.h>
- #include <Scrap.h>
-
- #include "CodecLibrary.h"
- #include "StorageLibrary.h"
- #include "GetShapeLocalBounds.h"
-
- /* ---------------------------------------------------------------------------
- Constants
- --------------------------------------------------------------------------- */
-
- #define LONGALIGN(n) (((n) + 3) & ~3L)
- #define kAtomHeaderSize (sizeof(Size) + sizeof(OSType))
-
- #define gxForPrintingOnlyAtom 'fpto'
- #define gxEraseBackgroundAtom 'erbg'
-
- #define kQuickTimeGestalt 'qtim'
-
- /* ---------------------------------------------------------------------------
- Function prototypes
- --------------------------------------------------------------------------- */
-
- static gxRectangle *ShortRectToFixed(const Rect *shortRect, gxRectangle *fixedRect);
- static Rect *FixedRectToShort(const gxRectangle *fixedRect, Rect *shortRect);
- static long *AppendAtom(long stream[], Size size, OSType tag, const void* data);
- pascal OSErr GXCdSendDataProc(FlavorType theType, void *dragSendRefCon, ItemReference theItem, DragReference theDrag);
-
- /* ===========================================================================
- Public functions
- =========================================================================== */
-
- /* ---------------------------------------------------------------------------
- GXCdShapeToHandle
- This routine flattens a shape to a handle. For an explanation of the
- parameters, see the comment on GXCdShapeToPicture. This routine is used by
- both GXCdShapeToPicture for embedding shapes in QuickDraw pictures and by
- AddQDGXRecorderFrame for making QuickDraw GX movies.
- --------------------------------------------------------------------------- */
-
- Handle GXCdShapeToHandle(gxShape source, PicHandle proxie, Boolean forPrintingOnly, Boolean eraseBackground)
- {
- long atomCount, shapeSize, proxieSize, dataSize, fontListSize;
- Handle dataHdl, shapeHdl;
- gxFlatFontList* fontList;
- gxTag fontListTag;
-
- /* Flatten the shape into a handle and gather font database statistics. */
-
- shapeHdl = GXStShapeToHandleWithFlags(source, gxFontListFlatten | gxFontGlyphsFlatten |
- gxFontVariationsFlatten);
-
- if (shapeHdl == nil)
- return nil;
-
- if (proxie)
- {
- atomCount = 2;
- proxieSize = LONGALIGN(GetHandleSize((Handle)proxie));
- }
- else
- {
- atomCount = 1;
- proxieSize = 0;
- }
- shapeSize = LONGALIGN(GetHandleSize(shapeHdl));
-
- if (forPrintingOnly)
- ++atomCount;
- if (eraseBackground)
- ++atomCount;
-
- /* Retrieve the font database information. */
-
- fontListSize = 0;
- fontList = nil;
- GXIgnoreGraphicsWarning(count_out_of_range);
- if (GXGetShapeTags(source, gxFlatFontListItemTag, 1, 1, &fontListTag) > 0)
- {
- fontListSize = GXGetTag(fontListTag, nil, nil);
- if (fontListSize > 0)
- {
- fontList = (gxFlatFontList*)NewPtr(fontListSize);
- if (fontList != nil)
- {
- GXGetTag(fontListTag, nil, fontList);
- fontListSize = LONGALIGN(fontListSize);
- ++atomCount;
- }
- else
- fontListSize = 0;
- }
- }
- GXPopGraphicsWarning(); /* count_out_of_range */
-
- dataSize = atomCount * kAtomHeaderSize + shapeSize + proxieSize + fontListSize + sizeof(long);
- dataHdl = NewHandle(dataSize);
- if (dataHdl == nil)
- {
- DisposeHandle(shapeHdl);
- if (fontList)
- DisposePtr((Ptr)fontList);
- return nil;
- }
-
- {
- long* p = (long*)*dataHdl;
-
- if (forPrintingOnly)
- p = AppendAtom(p, 0, gxForPrintingOnlyAtom, nil);
- if (eraseBackground)
- p = AppendAtom(p, 0, gxEraseBackgroundAtom, nil);
- if (proxie)
- p = AppendAtom(p, proxieSize, 'PICT', *proxie);
- if (fontList)
- p = AppendAtom(p, fontListSize, gxFlatFontListItemTag, fontList);
- p = AppendAtom(p, shapeSize, 'qdgx', *shapeHdl);
- *p++ = 0; /* end of the atom-list */
-
- DisposeHandle(shapeHdl);
- if (fontList)
- DisposePtr((Ptr)fontList);
- }
- return dataHdl;
- }
-
- /* ---------------------------------------------------------------------------
- GXCdShapeToPicture
- This routine converts a shape to a QuickDraw picture containing flattened
- QuickDraw GX data encoded as QuickTime compressed data. An application may
- then call the DrawPicture function to display the image, which uses the
- StdPix bottleneck routine to decompress the data and the StdBits bottleneck
- routine to render the image. The routine may be used to create a QuickDraw
- picture prior to entering the printing loop or to convert a QuickDraw GX
- picture shape to the QuickDraw PICT file format. DecompressImage is
- described in detail in Inside Macintosh: QuickTime, pages 3-78 to 3-79.
-
- A proxie of the shape may be included in the compressed data to represent
- the shape when QuickDraw GX is not installed. This routine is called by
- GXCdShapeToScrap and GXCdDragAndDropShape.
-
- theShape • The shape to be embedded in the QuickDraw picture.
- proxie • The QuickDraw picture to be used when QuickDraw GX
- is not available.
- hScale • The horizontal scaling factor.
- vScale • The vertical scaling factor.
- forPrintingOnly • If TRUE, then the decompressor will always look for
- the proxie and theShape will only be used when
- printing. Use this setting if theShape might be too
- large or too slow when drawn from other applications.
- • If FALSE, then the decompressor will draw theShape
- unless it gets an error, in which case it will look
- for a proxie.
- eraseBackground • If TRUE, the decompressor will always erase the
- background to WHITE before drawing the shape. This is
- slower but needed if the shape does not fill its
- bounding rectangle.
- • If FALSE, the decompressor will just draw the shape.
- Use this setting if the shape entirely fills its
- bounding rectangle.
-
- The shape [and proxie] is embedded by constructing a stream of atoms. Each
- atom begins with a size (long) and a type (OSType), and the data for that
- type. After the last atom, there is a trailing zero (long) to mark the end
- of the stream. For embedded shapes, the type is 'qdgx', and for the proxie
- the type is 'PICT'. Note that the size fields are rounded up to a multiple
- of 4. To alert QuickTime that the data is in this parsable form with a
- possible PICT proxie, we add a 'prxy' extension to the QuickTime image
- description.
-
- Picture of this form will draw the embedded shape (or the proxie if
- QuickDraw GX is not available) when an application calls DrawPicture. This
- replaces the PicComment technique described in QuickDraw GX 1.0 for
- embedding shapes in pictures.
-
- If you want to include a flatFontList tag, be sure that theShape is a
- picture, otherwise QuickDraw GX will not return the tag after
- GXFlattenShape. The flatFontList tag makes certain printing conditions
- more efficient (i.e. font downloading to postscript printers).
- --------------------------------------------------------------------------- */
-
- PicHandle GXCdShapeToPicture(gxShape theShape, PicHandle proxie, Fixed hScale, Fixed vScale, Boolean forPrintingOnly, Boolean eraseBackground)
- {
- PicHandle picture;
- ImageDescriptionHandle descHdl;
- ImageDescriptionPtr descPtr;
- Handle dataHdl;
- gxRectangle bounds;
- long version;
- OSErr error;
-
- error = Gestalt(kQuickTimeGestalt, &version);
- if (error != noErr)
- return nil;
-
- /* Move the shape's topLeft to 0,0 so that it draws neatly inside the
- picture frame.
- */
- {
- gxShape tempShape = theShape;
-
- GetShapeLocalBounds(tempShape, &bounds);
- if (bounds.left != ff(0) || bounds.top != ff(0))
- {
- tempShape = GXCopyToShape(nil, theShape);
-
- GXSetShapeAttributes(tempShape, GXGetShapeAttributes(tempShape) | gxMapTransformShape);
- GXMoveShape(tempShape, -bounds.left, -bounds.top);
- GetShapeLocalBounds(tempShape, &bounds);
- }
- dataHdl = GXCdShapeToHandle(tempShape, proxie, forPrintingOnly, eraseBackground);
-
- if (tempShape != theShape)
- GXDisposeShape(tempShape);
- }
-
- if (dataHdl == nil)
- return nil;
-
- descHdl = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
-
- if (descHdl)
- {
- Rect srcRect;
- Rect dstRect;
- CodecInfo codecInfo;
- long width;
- long height;
- RgnHandle savedClipRgn;
-
- // GXGetShapeLocalBounds(theShape, &bounds);
- FixedRectToShort(&bounds, &srcRect);
-
- {
- OpenCPicParams openCPicParams;
-
- openCPicParams.srcRect = srcRect;
- openCPicParams.hRes = ff(72);
- openCPicParams.vRes = ff(72);
- openCPicParams.version = -2;
- openCPicParams.reserved1 = 0;
- openCPicParams.reserved2 = 0;
- picture = OpenCPicture(&openCPicParams);
- }
-
- if (picture == nil)
- {
- error = QDError();
- goto OpenCPictureFailed;
- }
-
- savedClipRgn = NewRgn();
- GetClip(savedClipRgn);
- ClipRect(&srcRect);
-
- /* Retrieve information about a specific compressor or about a
- compressor of a specific type. If you request information about a
- type of compressor, the Image Compression Manager returns
- information about the first compressor it finds of that type. This
- will only be used if the data is decompressed on the host instead
- of the printer.
- */
- error = GetCodecInfo(&codecInfo, 'qdgx', bestFidelityCodec);
- if (error != noErr)
- error = GetCodecInfo(&codecInfo, 'qdgx', anyCodec);
-
- if (error != noErr)
- goto GetCodecInfoFailed;
-
- width = srcRect.right - srcRect.left + 1;
- height = srcRect.bottom - srcRect.top + 1;
-
- if (width > 0 && height > 0)
- {
- descPtr = *descHdl;
- descPtr->idSize = sizeof(ImageDescription);
- descPtr->cType = 'qdgx';
- descPtr->resvd1 = 0;
- descPtr->resvd2 = 0;
- descPtr->version = codecInfo.version;
- descPtr->revisionLevel = codecInfo.revisionLevel;
- descPtr->vendor = codecInfo.vendor;
- descPtr->temporalQuality = codecLosslessQuality;
- descPtr->temporalQuality = codecLosslessQuality;
- descPtr->width = width;
- descPtr->height = height;
- descPtr->hRes = ff(72);
- descPtr->vRes = ff(72);
- descPtr->dataSize = GetHandleSize(dataHdl);
- descPtr->frameCount = 1;
- BlockMove(codecInfo.typeName, descPtr->name, 32);
- descPtr->depth = 32;
- descPtr->clutID = -1;
-
- /* If there is a PICT proxie, add an image description extension
- for use by QuickTime when QuickDraw GX is not installed.
- */
- if (proxie)
- {
- Handle prxyVersionHdl = NewHandle(sizeof(long));
-
- if (prxyVersionHdl != nil)
- {
- *(long*)*prxyVersionHdl = 0; /* version number for 'prxy' extension */
- AddImageDescriptionExtension(descHdl, prxyVersionHdl, 'prxy');
- }
- }
-
- /* The data in the compressed image handle needs to be locked
- during the call to the DecompressImage routine. We only unlock the
- data after we're done with the DecompressImage call.
- */
- HLock(dataHdl);
-
- {
- gxRectangle geometry;
- gxShape shape;
-
- shape = GXNewRectangle(&bounds);
-
- GXScaleShape(shape, hScale, vScale, bounds.left, bounds.top);
- GXGetShapeBounds(shape, 0, &geometry);
-
- FixedRectToShort(&geometry, &dstRect);
- GXDisposeShape(shape);
- }
-
- /* pascal OSErr DecompressImage(Ptr data,
- ImageDescriptionHandle desc,
- PixMapHandle dst, const Rect *srcRect,
- const Rect *dstRect, short mode,
- RgnHandle mask);
- */
- error = DecompressImage(*dataHdl,
- descHdl,
- ((CGrafPtr)qd.thePort)->portPixMap,
- &srcRect,
- &dstRect,
- ditherCopy,
- nil);
-
- HUnlock((Handle)dataHdl);
- }
-
- GetCodecInfoFailed:
- ClosePicture();
-
- SetClip(savedClipRgn);
- DisposeRgn(savedClipRgn);
-
- if (error != noErr && picture)
- {
- KillPicture(picture);
- picture = nil;
- }
-
- OpenCPictureFailed:
- if (descHdl)
- DisposeHandle((Handle)descHdl);
- }
- else
- picture = nil;
-
- if (dataHdl)
- DisposeHandle(dataHdl);
-
- return picture;
- }
-
- /* ---------------------------------------------------------------------------
- GXCdDrawShape
- This routine provides an alternative to the technique described in
- GXCdShapeToPicture to image QuickDraw GX data. It passes the QuickDraw GX
- data directly to the StdPix bottleneck as QuickTime compressed data
- encoded within a PixMap data structure. This may be used from within a
- printing loop as outlined in "Printing Images Faster With Data
- Compression," develop 24 (December 1995).
- --------------------------------------------------------------------------- */
-
- void GXCdDrawShape(gxShape theShape, PicHandle proxie, Fixed hScale, Fixed vScale, Boolean forPrintingOnly, Boolean eraseBackground)
- {
- ImageDescriptionHandle descHdl;
- ImageDescriptionPtr descPtr;
- Handle dataHdl;
- Ptr dataPtr;
- gxRectangle bounds;
- long version;
- OSErr error;
-
- error = Gestalt(kQuickTimeGestalt, &version);
- if (error != noErr)
- return;
-
- /* Move the shape's topLeft to 0,0 so that it draws neatly inside the
- picture frame.
- */
- {
- gxShape tempShape = theShape;
-
- GetShapeLocalBounds(tempShape, &bounds);
- if (bounds.left != ff(0) || bounds.top != ff(0))
- {
- tempShape = GXCopyToShape(nil, theShape);
-
- GXSetShapeAttributes(tempShape, GXGetShapeAttributes(tempShape) | gxMapTransformShape);
- GXMoveShape(tempShape, -bounds.left, -bounds.top);
- GetShapeLocalBounds(tempShape, &bounds);
- }
- dataHdl = GXCdShapeToHandle(tempShape, proxie, forPrintingOnly, eraseBackground);
-
- if (tempShape != theShape)
- GXDisposeShape(tempShape);
- }
-
- if (dataHdl == nil)
- return;
-
- descHdl = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
-
- if (descHdl)
- {
- Rect srcRect;
- Rect dstRect;
- CodecInfo codecInfo;
- long width;
- long height;
-
- // GXGetShapeLocalBounds(theShape, &bounds);
- FixedRectToShort(&bounds, &srcRect);
-
- /* Retrieve information about a specific compressor or about a
- compressor of a specific type. If you request information about a type
- of compressor, the Image Compression Manager returns information about
- the first compressor it finds of that type. This will only be used if
- the data is decompressed on the host instead of the printer.
- */
- error = GetCodecInfo(&codecInfo, 'qdgx', bestFidelityCodec);
- if (error != noErr)
- error = GetCodecInfo(&codecInfo, 'qdgx', anyCodec);
-
- if (error != noErr)
- goto GetCodecInfoFailed;
-
- width = srcRect.right - srcRect.left + 1;
- height = srcRect.bottom - srcRect.top + 1;
-
- if (width > 0 && height > 0)
- {
- descPtr = *descHdl;
- descPtr->idSize = sizeof(ImageDescription);
- descPtr->cType = 'qdgx';
- descPtr->resvd1 = 0;
- descPtr->resvd2 = 0;
- descPtr->version = codecInfo.version;
- descPtr->revisionLevel = codecInfo.revisionLevel;
- descPtr->vendor = codecInfo.vendor;
- descPtr->temporalQuality = codecLosslessQuality;
- descPtr->temporalQuality = codecLosslessQuality;
- descPtr->width = width;
- descPtr->height = height;
- descPtr->hRes = ff(72);
- descPtr->vRes = ff(72);
- descPtr->dataSize = GetHandleSize(dataHdl);
- descPtr->frameCount = 1;
- BlockMove(codecInfo.typeName, descPtr->name, 32);
- descPtr->depth = 32;
- descPtr->clutID = -1;
-
- /* If there is a PICT proxie, add an image description extension
- for use by QuickTime when QuickDraw GX is not installed.
- */
- if (proxie)
- {
- Handle prxyVersionHdl = NewHandle(sizeof(long));
-
- if (prxyVersionHdl != nil)
- {
- *(long*)*prxyVersionHdl = 0; /* version number for 'prxy' extension */
- AddImageDescriptionExtension(descHdl, prxyVersionHdl, 'prxy');
- }
- }
-
- /* The data in the compressed image handle needs to be locked
- during the call to the StdPix routine. We only unlock the data
- after we're done with the StdPix call.
- */
- HLock(dataHdl);
- dataPtr = StripAddress(*dataHdl);
-
- {
- gxRectangle geometry;
- gxShape shape;
-
- shape = GXNewRectangle(&bounds);
-
- GXScaleShape(shape, hScale, vScale, bounds.left, bounds.top);
- GXGetShapeBounds(shape, 0, &geometry);
-
- FixedRectToShort(&geometry, &dstRect);
- GXDisposeShape(shape);
- }
-
- {
- PixMapHandle tempPixMapHdl = NewPixMap();
- PixMapPtr tempPixMapPtr;
- MatrixRecord matrix;
- CQDProcs stdProcs;
- StdPixProcPtr pixProcPtr;
-
- MoveHHi((Handle)tempPixMapHdl);
- HLock((Handle)tempPixMapHdl);
-
- tempPixMapPtr = (PixMapPtr)StripAddress(*(Handle)tempPixMapHdl);
-
- /* Make a matrix that describes the mapping between the source
- and destination rectangles.
- */
- RectMatrix(&matrix, &srcRect, &dstRect);
-
- /* SetCompressedPixMapInfo creates a compressed 'PixMap' structure
- from an image description record and the compressed image data.
- */
- error = SetCompressedPixMapInfo(tempPixMapPtr, descHdl, dataPtr, 0, nil, nil);
-
- if (error == noErr)
- {
- /* Check for custom QuickDraw bottlenecks in the current grafPort. */
-
- if ((((CGrafPtr)qd.thePort)->grafProcs) == nil)
- {
- /* Retrieve the standard QuickDraw bottlenecks. */
-
- SetStdCProcs(&stdProcs);
-
- /* The 'newProc1' field is used by QuickTime for the 'StdPix'
- bottleneck routine.
- */
- pixProcPtr = (StdPixProcPtr)stdProcs.newProc1;
- }
- else
- {
- /* Use the custom 'StdPix' bottleneck routine from the grafPort. */
-
- pixProcPtr = (StdPixProcPtr)((CGrafPtr)qd.thePort)->grafProcs->newProc1;
- }
-
- /* Call the bottleneck routine. The flag bits for the StdPix
- routine are described in IM QuickTime p.3-139 and the function
- prototype is:
- pascal void StdPix (PixMapPtr src, const Rect *srcRect,
- MatrixRecordPtr matrix, short mode,
- RgnHandle mask, PixMapPtr matte,
- Rect *matteRect, short flags);
- */
- CallStdPixProc(pixProcPtr,
- tempPixMapPtr,
- &srcRect,
- &matrix,
- ditherCopy,
- nil,
- nil,
- nil,
- callOldBits | callStdBits);
- }
-
- HUnlock((Handle)tempPixMapHdl);
- DisposePixMap(tempPixMapHdl);
- }
-
- HUnlock((Handle)dataHdl);
- }
-
- GetCodecInfoFailed:
- OpenCPictureFailed:
- if (descHdl)
- DisposeHandle((Handle)descHdl);
- }
-
- if (dataHdl)
- DisposeHandle(dataHdl);
- }
-
- /* ---------------------------------------------------------------------------
- GXCdShapeToBitmap
- This routine converts a shape to a QuickDraw picture containing a 1-bit
- bitmap of the shape. This is used by ShapeToScrap to create a proxie when
- calling GXCdShapeToPicture. If you want to make the proxie prettier (and
- larger), change the bitmap to 8-bit. However, if you're using this in
- conjunction with GXCdShapeToPicture to place a gxShape on the clipboard,
- 1-bit should be enough, since the actual shape will be drawn, rather than
- the proxie (unless forPrintingOnly is true).
- --------------------------------------------------------------------------- */
-
- PicHandle GXCdShapeToBitmap(gxShape source)
- {
- gxRectangle bounds;
- gxShape bitShape;
- gxBitmap bitmap;
- PicHandle picture;
- Rect shortBounds;
-
- GetShapeLocalBounds(source, &bounds);
- // GXGetShapeLocalBounds(source, &bounds);
-
- FixedRectToShort(&bounds, &shortBounds);
- OffsetRect(&shortBounds, -shortBounds.left, -shortBounds.top);
-
- bitmap.width = shortBounds.right;
- bitmap.height = shortBounds.bottom;
- bitmap.rowBytes = bitmap.width + 31 >> 5 << 2;
- bitmap.pixelSize = 1;
- bitmap.space = gxIndexedSpace;
- bitmap.set = nil;
- bitmap.profile = nil;
- bitmap.image = NewPtrClear(bitmap.rowBytes * bitmap.height);
- if (bitmap.image == nil)
- return nil;
-
- bitShape = GXNewBitmap(&bitmap, nil);
- if (bitShape != nil)
- {
- gxViewGroup group = GXNewViewGroup();
- gxViewDevice device = GXNewViewDevice(group, bitShape);
- gxViewPort port = GXNewViewPort(group);
- gxTransform trans = GXCloneTransform(GXGetShapeTransform(source));
-
- GXSetShapeAttributes(source, GXGetShapeAttributes(source) | gxMapTransformShape);
- GXMoveShape(source, -bounds.left, -bounds.top);
- GXSetViewPortDither(port, 4);
- GXSetShapeViewPorts(source, 1, &port);
- GXDrawShape(source);
- GXSetShapeTransform(source, trans);
- GXDisposeTransform(trans);
-
- GXDisposeViewGroup(group); /* This disposes of the gxViewPort and gxViewDevice. */
- GXDisposeShape(bitShape);
- }
-
- {
- GrafPtr thePort;
- BitMap srcBits;
-
- GetPort(&thePort);
- srcBits.baseAddr = bitmap.image;
- srcBits.rowBytes = bitmap.rowBytes;
- srcBits.bounds = shortBounds;
-
- picture = OpenPicture(&shortBounds);
- ClipRect(&shortBounds);
- CopyBits(&srcBits, &thePort->portBits, &shortBounds, &shortBounds, srcOr, nil);
- ClosePicture();
- }
-
- DisposePtr((Ptr)bitmap.image);
-
- return picture;
- }
-
- /* ---------------------------------------------------------------------------
- GXCdShapeToScrap
- This routine puts a Quickdraw picture on the clipboard containing an
- embedded shape and, if addProxie is true, a 1-bit bitmap of the shape.
- Call this in response to the user choosing "Copy" or "Cut" from the Edit
- menu. For an explanation of the parameters, see the comment on
- GXCdShapeToPicture.
- --------------------------------------------------------------------------- */
-
- void GXCdShapeToScrap(gxShape source, Boolean addProxie, Boolean forPrintingOnly, Boolean eraseBackground)
- {
- PicHandle picture;
- PicHandle proxie = nil;
-
- if ( addProxie )
- proxie = GXCdShapeToBitmap(source);
- picture = GXCdShapeToPicture(source, proxie, ff(1), ff(1), forPrintingOnly, eraseBackground);
-
- if (proxie)
- KillPicture(proxie);
-
- if (picture)
- {
- HLock((Handle)picture);
- ZeroScrap();
- PutScrap(GetHandleSize((Handle)picture), 'PICT', (Ptr)*picture);
- KillPicture(picture);
- }
- }
-
- /* ---------------------------------------------------------------------------
- GXCdDragAndDropShape
- This routine will take the current mouse-down event and a shape, and handle
- dragging it to the desktop or to another Drag-friendly application. It
- offers to deliver the shape as either 'qdgx' or as a 'PICT' with the shape
- embedded using DecompressShape. To offer other flavors, just add
- additional calls to AddDragItemFlavor below, and add the corresponding
- cases in the switch statement in GXCdSendDataProc.
- --------------------------------------------------------------------------- */
-
- void GXCdDragAndDropShape(EventRecord* event, gxShape shape)
- { RgnHandle hilightRgn;
- gxRectangle bounds;
- Rect r;
- DragReference theDrag;
- DragSendDataUPP myDragSendDataUPP;
-
- if (NewDrag(&theDrag) == noErr)
- {
- myDragSendDataUPP = NewDragSendDataProc(GXCdSendDataProc);
- SetDragSendProc(theDrag, myDragSendDataUPP, nil);
-
- AddDragItemFlavor(theDrag, (unsigned long)shape, 'qdgx', nil, 0, 0);
- AddDragItemFlavor(theDrag, (unsigned long)shape, 'PICT', nil, 0, 0);
-
- hilightRgn = NewRgn();
- GXGetShapeDeviceBounds(shape, 0, 0, &bounds);
- FixedRectToShort(&bounds, &r);
- RectRgn(hilightRgn, &r);
- SetDragItemBounds(theDrag, 1, &r);
-
- /* Change the region from a fill to a frame. */
- {
- RgnHandle tempRgn = NewRgn();
-
- CopyRgn(hilightRgn, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(hilightRgn, tempRgn, hilightRgn);
- DisposeRgn(tempRgn);
- }
-
- TrackDrag(theDrag, event, hilightRgn);
- DisposeDrag(theDrag);
- DisposeRgn(hilightRgn);
- DisposeRoutineDescriptor(myDragSendDataUPP);
- }
- }
-
- /* ===========================================================================
- Private functions
- =========================================================================== */
-
- /* ---------------------------------------------------------------------------
- QuickDraw conversion utility functions
- --------------------------------------------------------------------------- */
-
- static gxRectangle *ShortRectToFixed(const Rect *shortRect, gxRectangle *fixedRect)
- {
- register Fixed *coord;
-
- if (shortRect == nil)
- {
- GXPostGraphicsError(parameter_is_nil);
- return nil;
- }
-
- if (fixedRect == nil)
- {
- GXPostGraphicsError(parameter_is_nil);
- return nil;
- }
-
- coord = (Fixed *) fixedRect;
- *coord++ = IntToFixed(shortRect->left);
- *coord++ = IntToFixed(shortRect->top);
- *coord++ = IntToFixed(shortRect->right);
- *coord = IntToFixed(shortRect->bottom);
- return fixedRect;
- }
-
- static Rect *FixedRectToShort(const gxRectangle *fixedRect, Rect *shortRect)
- {
- register short *coord;
-
- if (shortRect == nil)
- {
- GXPostGraphicsError(parameter_is_nil);
- return nil;
- }
-
- if (fixedRect == nil)
- {
- GXPostGraphicsError(parameter_is_nil);
- return nil;
- }
-
- coord = (short *) shortRect;
- *coord++ = FixedRound(fixedRect->top);
- *coord++ = FixedRound(fixedRect->left);
- *coord++ = FixedRound(fixedRect->bottom);
- *coord = FixedRound(fixedRect->right);
- return shortRect;
- }
-
- /* ---------------------------------------------------------------------------
- AppendAtom
- --------------------------------------------------------------------------- */
-
- static long* AppendAtom(long stream[], Size size, OSType tag, const void *data)
- {
- *stream++ = size + kAtomHeaderSize;
- *stream++ = tag;
- BlockMove(data, (Ptr)stream, size);
-
- return (long*)((char*)stream + size);
- }
-
- /* ---------------------------------------------------------------------------
- GXCdSendDataProc
- The ItemReference is the gxShape to be sent. The dragSendRefCon is
- ignored.
- --------------------------------------------------------------------------- */
-
- pascal OSErr GXCdSendDataProc(FlavorType theType, void *dragSendRefCon, ItemReference theItem, DragReference theDrag)
- {
- gxShape shape = (gxShape)theItem;
- OSErr error = noErr;
-
- switch (theType)
- {
- case 'qdgx':
- {
- Handle flat = GXStShapeToHandle(shape);
- if (flat)
- {
- HLock(flat);
- error = SetDragItemFlavorData(theDrag, theItem, 'qdgx', *flat, GetHandleSize(flat), 0);
- DisposeHandle(flat);
- }
- break;
- }
- case 'PICT':
- {
- PicHandle picture;
- PicHandle proxie;
-
- proxie = GXCdShapeToBitmap(shape);
- picture = GXCdShapeToPicture(shape, proxie, ff(1), ff(1), false, true);
-
- if (proxie)
- KillPicture(proxie);
-
- if (picture)
- {
- HLock((Handle)picture);
- error = SetDragItemFlavorData(theDrag, theItem, 'PICT', (Ptr)*picture, GetHandleSize((Handle)picture), 0);
- KillPicture(picture);
- }
- break;
- }
- default:
- error = badDragFlavorErr;
- break;
- }
-
- return error;
- }
-