Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Sample Components/SGChannelPict.c
/* |
File: SGChannelPict.r |
Written by: Peter Hoddie |
Copyright: © 1992 by Apple Computer, Inc., all rights reserved. |
*/ |
#include <Errors.h> |
#include <Memory.h> |
#include <OSUtils.h> |
#include <Packages.h> |
#include <QuickDraw.h> |
#include <Resources.h> |
#include <QuickTimeComponents.h> |
#define kMediaTimeScale 600 |
typedef struct { |
ComponentInstance self; |
SeqGrabComponent grabber; |
long usage; |
Boolean paused; |
CGrafPtr destPort; |
GDHandle destGD; |
CGrafPtr tempPort; |
MatrixRecord displayMatrix; |
Rect destRect; |
Rect srcRect; |
RgnHandle clip; |
Boolean inPreview; |
Boolean inRecord; |
TimeBase base; |
long bytesWritten; |
Boolean showTickCount; |
long saveUsage; |
} SGPictGlobalsRecord, *SGPictGlobals; |
pascal ComponentResult SGPictOpen (SGPictGlobals store, ComponentInstance self); |
pascal ComponentResult SGPictClose (SGPictGlobals store, ComponentInstance self); |
pascal ComponentResult SGPictCanDo (SGPictGlobals store, short ftnNumber ); |
pascal ComponentResult SGPictVersion (SGPictGlobals store); |
pascal ComponentResult SGPictSetGWorld (SGPictGlobals store, CGrafPtr gp, GDHandle gd); |
pascal ComponentResult SGPictSetChannelUsage (SGPictGlobals store, long usage); |
pascal ComponentResult SGPictGetChannelUsage (SGPictGlobals store, long *usage); |
pascal ComponentResult SGPictGetChannelInfo (SGPictGlobals store, long *channelInfo); |
pascal ComponentResult SGPictSetChannelMatrix (SGPictGlobals store, const MatrixRecord *m); |
pascal ComponentResult SGPictGetChannelMatrix (SGPictGlobals store, MatrixRecord *m); |
pascal ComponentResult SGPictSetChannelBounds (SGPictGlobals store, const Rect *bounds); |
pascal ComponentResult SGPictGetChannelBounds (SGPictGlobals store, Rect *bounds); |
pascal ComponentResult SGPictSetChannelClip (SGPictGlobals store, RgnHandle theClip); |
pascal ComponentResult SGPictGetChannelClip (SGPictGlobals store, RgnHandle *theClip); |
pascal ComponentResult SGPictStartPreview (SGPictGlobals store); |
pascal ComponentResult SGPictStartRecord (SGPictGlobals store); |
pascal ComponentResult SGPictIdle (SGPictGlobals store); |
pascal ComponentResult SGPictStop (SGPictGlobals store); |
pascal ComponentResult SGPictPause (SGPictGlobals store, Byte pause); |
pascal ComponentResult SGPictPrepare (SGPictGlobals store, Boolean prepareForPreview, |
Boolean prepareForRecord); |
pascal ComponentResult SGPictRelease (SGPictGlobals store); |
pascal ComponentResult SGPictGetChannelSampleDescription (SGPictGlobals store, Handle sampleDesc); |
pascal ComponentResult SGPictGetChannelDeviceList (SGPictGlobals store, long selectionFlags, |
SGDeviceList *list); |
pascal ComponentResult SGPictSetChannelDevice (SGPictGlobals store, StringPtr name); |
pascal ComponentResult SGPictGetChannelTimeScale (SGPictGlobals store, TimeScale *scale); |
pascal ComponentResult SGPictInitChannel (SGPictGlobals store, SeqGrabComponent owner); |
pascal ComponentResult SGPictWriteSamples (SGPictGlobals store, Movie m, AliasHandle theFile); |
pascal ComponentResult SGPictGetDataRate (SGPictGlobals store, long *bytesPerSecond); |
pascal ComponentResult SGPictPanelGetDitl (SGPictGlobals store, Handle *ditl); |
pascal ComponentResult SGPictPanelInstall (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset); |
pascal ComponentResult SGPictPanelEvent (SGPictGlobals store, SGChannel c, DialogPtr d, |
short itemOffset, EventRecord *theEvent, short *itemHit, Boolean *handled); |
pascal ComponentResult SGPictPanelRemove (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset); |
pascal ComponentResult SGPictPanelGetSettings (SGPictGlobals store, SGChannel c, UserData *ud, long flags); |
pascal ComponentResult SGPictPanelSetSettings (SGPictGlobals store, SGChannel c, UserData ud, long flags); |
pascal ComponentResult SGPictSetShowTickCount (SGPictGlobals store, Boolean show); |
pascal ComponentResult SGPictGetShowTickCount (SGPictGlobals store, Boolean *show); |
pascal ComponentResult SGPICTDispatcher(ComponentParameters *params, Handle storage); |
/************************ |
Component Management |
************************/ |
pascal ComponentResult SGPICTDispatcher(ComponentParameters *params, Handle storage) |
{ |
OSErr err = badComponentSelector; |
ComponentFunction componentProc = 0; |
switch (params->what) { |
case kComponentOpenSelect: componentProc = SGPictOpen; break; |
case kComponentCloseSelect: componentProc = SGPictClose; break; |
case kComponentCanDoSelect: componentProc = SGPictCanDo; break; |
case kComponentVersionSelect: componentProc = SGPictVersion; break; |
case kSGSetGWorldSelect: componentProc = SGPictSetGWorld; break; |
case kSGStartPreviewSelect: componentProc = SGPictStartPreview; break; |
case kSGStartRecordSelect: componentProc = SGPictStartRecord; break; |
case kSGIdleSelect: componentProc = SGPictIdle; break; |
case kSGStopSelect: componentProc = SGPictStop; break; |
case kSGPauseSelect: componentProc = SGPictPause; break; |
case kSGPrepareSelect: componentProc = SGPictPrepare; break; |
case kSGReleaseSelect: componentProc = SGPictRelease; break; |
case kSGCSetChannelUsageSelect: componentProc = SGPictSetChannelUsage; break; |
case kSGCGetChannelUsageSelect: componentProc = SGPictGetChannelUsage; break; |
case kSGCSetChannelBoundsSelect: componentProc = SGPictSetChannelBounds; break; |
case kSGCGetChannelBoundsSelect: componentProc = SGPictGetChannelBounds; break; |
case kSGCGetChannelInfoSelect: componentProc = SGPictGetChannelInfo; break; |
case kSGCSetChannelMatrixSelect: componentProc = SGPictSetChannelMatrix; break; |
case kSGCGetChannelMatrixSelect: componentProc = SGPictGetChannelMatrix; break; |
case kSGCSetChannelClipSelect: componentProc = SGPictSetChannelClip; break; |
case kSGCGetChannelClipSelect: componentProc = SGPictGetChannelClip; break; |
case kSGCGetChannelSampleDescriptionSelect: componentProc = SGPictGetChannelSampleDescription; break; |
case kSGCGetChannelDeviceListSelect: componentProc = SGPictGetChannelDeviceList; break; |
case kSGCSetChannelDeviceSelect: componentProc = SGPictSetChannelDevice; break; |
case kSGCGetChannelTimeScaleSelect: componentProc = SGPictGetChannelTimeScale; break; |
case kSGCInitChannelSelect: componentProc = SGPictInitChannel; break; |
case kSGCWriteSamplesSelect: componentProc = SGPictWriteSamples; break; |
case kSGCGetDataRateSelect: componentProc = SGPictGetDataRate; break; |
case kSGCPanelGetDitlSelect: componentProc = SGPictPanelGetDitl; break; |
case kSGCPanelInstallSelect: componentProc = SGPictPanelInstall; break; |
case kSGCPanelEventSelect: componentProc = SGPictPanelEvent; break; |
case kSGCPanelRemoveSelect: componentProc = SGPictPanelRemove; break; |
case kSGCPanelGetSettingsSelect: componentProc = SGPictPanelGetSettings; break; |
case kSGCPanelSetSettingsSelect: componentProc = SGPictPanelSetSettings; break; |
// Private component calls |
case 0x0100: componentProc = SGPictSetShowTickCount ;break; |
case 0x0101: componentProc = SGPictGetShowTickCount ;break; |
} |
if (componentProc) |
err = CallComponentFunctionWithStorage(storage, params, componentProc); |
return err; |
} |
pascal ComponentResult SGPictCanDo (SGPictGlobals store, short ftnNumber ) |
{ |
switch (ftnNumber) { |
case kComponentOpenSelect: |
case kComponentCloseSelect: |
case kComponentCanDoSelect: |
case kComponentVersionSelect: |
case kSGSetGWorldSelect: |
case kSGStartPreviewSelect: |
case kSGStartRecordSelect: |
case kSGIdleSelect: |
case kSGStopSelect: |
case kSGPauseSelect: |
case kSGPrepareSelect: |
case kSGReleaseSelect: |
case kSGCSetChannelUsageSelect: |
case kSGCGetChannelUsageSelect: |
case kSGCSetChannelBoundsSelect: |
case kSGCGetChannelBoundsSelect: |
case kSGCGetChannelInfoSelect: |
case kSGCSetChannelMatrixSelect: |
case kSGCGetChannelMatrixSelect: |
case kSGCSetChannelClipSelect: |
case kSGCGetChannelClipSelect: |
case kSGCGetChannelSampleDescriptionSelect: |
case kSGCGetChannelDeviceListSelect: |
case kSGCSetChannelDeviceSelect: |
case kSGCGetChannelTimeScaleSelect: |
case kSGCInitChannelSelect: |
case kSGCWriteSamplesSelect: |
case kSGCGetDataRateSelect: |
case kSGCPanelGetDitlSelect: |
case kSGCPanelInstallSelect: |
case kSGCPanelEventSelect: |
case kSGCPanelRemoveSelect: |
case kSGCPanelGetSettingsSelect: |
case kSGCPanelSetSettingsSelect: |
// Private component calls |
case 0x0100: |
case 0x0101: |
return true; |
default: |
return false; |
} |
} |
pascal ComponentResult SGPictVersion (SGPictGlobals store) |
{ |
return 0x00020001; |
} |
pascal ComponentResult SGPictOpen (SGPictGlobals store, ComponentInstance self) |
{ |
OSErr err; |
Rect r; |
CGrafPtr tempPort; |
GrafPtr savePort; |
// allocate globals |
store = (SGPictGlobals)NewPtrClear(sizeof(SGPictGlobalsRecord)); |
if (err = MemError()) goto bail; |
// create a temporary port for drawing to in the idle routine |
tempPort = (CGrafPtr)NewPtr(sizeof(CGrafPort)); |
if (err = MemError()) { |
DisposePtr((Ptr)store); |
goto bail; |
} |
GetPort(&savePort); |
OpenCPort(tempPort); |
SetPort((GrafPtr)tempPort); |
PortSize(4096, 4096); // randomly big port |
SetRect(&r, 0, 0, 4096, 4096); |
RectRgn(tempPort->visRgn, &r); |
ClipRect(&r); |
SetPort(savePort); |
store->self = self; |
store->tempPort = tempPort; |
store->showTickCount = false; |
SetComponentInstanceStorage(self, (Handle)store); |
bail: |
return err; |
} |
pascal ComponentResult SGPictClose (SGPictGlobals store, ComponentInstance self) |
{ |
if (store) { |
if (store->clip) DisposeRgn(store->clip); |
if (store->tempPort) { |
CloseCPort(store->tempPort); |
DisposePtr((Ptr)store->tempPort); |
} |
DisposPtr((Ptr)store); |
} |
return noErr; |
} |
/************************ |
Required SG Channel Calls |
************************/ |
pascal ComponentResult SGPictSetGWorld (SGPictGlobals store, CGrafPtr gp, GDHandle gd) |
{ |
// remember the destination GWorld |
store->destPort = gp; |
store->destGD = gd; |
return noErr; |
} |
pascal ComponentResult SGPictSetChannelUsage (SGPictGlobals store, long usage) |
{ |
store->usage = usage; |
return noErr; |
} |
pascal ComponentResult SGPictGetChannelUsage (SGPictGlobals store, long *usage) |
{ |
*usage = store->usage; |
return noErr; |
} |
pascal ComponentResult SGPictGetChannelInfo (SGPictGlobals store, long *channelInfo) |
{ |
*channelInfo = seqGrabHasBounds; |
return noErr; |
} |
pascal ComponentResult SGPictSetChannelMatrix (SGPictGlobals store, const MatrixRecord *m) |
{ |
OSErr err = noErr; |
MatrixRecord mat; |
short matType; |
// determine the matrix being set |
if (m) |
mat = *m; |
else |
SetIdentityMatrix(&mat); |
// validate it |
matType = GetMatrixType(&mat); |
if ((mat.matrix[0][0] < 0) || (mat.matrix[1][1] < 0) || (matType >= linearMatrixType)) |
return paramErr; |
// update the matrix and destination rect |
store->displayMatrix = mat; |
store->destRect = store->srcRect; |
TransformRect(&mat, &store->destRect, nil); |
return err; |
} |
pascal ComponentResult SGPictGetChannelMatrix (SGPictGlobals store, MatrixRecord *m) |
{ |
*m = store->displayMatrix; |
return noErr; |
} |
pascal ComponentResult SGPictSetChannelBounds (SGPictGlobals store, const Rect *bounds) |
{ |
// remember destination rect |
store->destRect = *bounds; |
// recalculate display matrix from it |
RectMatrix(&store->displayMatrix, &store->srcRect, &store->destRect); |
return noErr; |
} |
pascal ComponentResult SGPictGetChannelBounds (SGPictGlobals store, Rect *bounds) |
{ |
*bounds = store->destRect; |
return noErr; |
} |
pascal ComponentResult SGPictSetChannelClip (SGPictGlobals store, RgnHandle theClip) |
{ |
OSErr err = noErr; |
if (store->clip) { |
DisposeRgn(store->clip); |
store->clip = nil; |
} |
if (theClip) { |
err = HandToHand((Handle *)&theClip); |
store->clip = theClip; |
} |
return err; |
} |
pascal ComponentResult SGPictGetChannelClip (SGPictGlobals store, RgnHandle *theClip) |
{ |
OSErr err = noErr; |
if (*theClip = store->clip) |
err = HandToHand((Handle *)theClip); |
return err; |
} |
pascal ComponentResult SGPictStartPreview (SGPictGlobals store) |
{ |
store->inPreview = (store->usage & seqGrabPreview) != 0; |
return noErr; |
} |
pascal ComponentResult SGPictStartRecord (SGPictGlobals store) |
{ |
store->inRecord = (store->usage & seqGrabRecord) != 0; |
store->inPreview = (store->usage & seqGrabPlayDuringRecord) != 0; |
return noErr; |
} |
pascal ComponentResult SGPictIdle (SGPictGlobals store) |
{ |
OSErr err = noErr; |
if (!store->paused && (store->inRecord || store->inPreview)) { |
Point mouseLoc; |
Rect r; |
PicHandle tempPict = nil; |
TimeRecord tr; |
CGrafPtr savePort; |
GDHandle saveGD; |
Rect maxR; |
GetGWorld(&savePort, &saveGD); |
GetTimeBaseTime(store->base, kMediaTimeScale, &tr); |
// figure the current area around the mouse (only on main screen) |
SetGWorld(store->tempPort, GetMainDevice()); |
GetMouse(&mouseLoc); |
LocalToGlobal(&mouseLoc); |
r.top = r.bottom = mouseLoc.v; |
r.left = r.right = mouseLoc.h; |
InsetRect(&r, -(store->srcRect.right >> 1), -(store->srcRect.bottom >> 1)); |
maxR = (**GetMainDevice()).gdRect; |
if (r.left < maxR.left) OffsetRect(&r, -r.left + maxR.left, 0); |
if (r.top < maxR.top) OffsetRect(&r, 0, -r.top + maxR.top); |
if (r.right > maxR.right) OffsetRect(&r, maxR.right - r.right, 0); |
if (r.bottom > maxR.bottom) OffsetRect(&r, 0, maxR.bottom - r.bottom); |
// copy the screen into a picture |
tempPict = OpenPicture(&r); |
CopyBits((BitMap *)&store->tempPort->portPixMap, |
(BitMap *)&store->tempPort->portPixMap, &r, &r, srcCopy, nil); |
if (store->showTickCount) { |
// if they want to see ticks, draw them |
Str63 str; |
NumToString(TickCount(), str); |
r.right = r.left + StringWidth(str) + 4; // do some magic positioning |
r.bottom = r.top + 14; |
EraseRect(&r); |
MoveTo(r.left + 2, r.bottom - 3); |
TextSize(12); |
DrawString(str); |
} |
ClosePicture(); |
// if recording, add data to movie |
if (store->inRecord) { |
long offset; |
long pictSize = GetHandleSize((Handle)tempPict); |
HLock((Handle)tempPict); |
err = SGAddMovieData(store->grabber, store->self, |
(Ptr)*tempPict, pictSize, &offset, 0, tr.value.lo, seqGrabWriteAppend); |
store->bytesWritten += pictSize; |
} |
// if we need to show the preview image, do that |
if (store->inPreview) { |
RgnHandle saveClip; |
SetGWorld(store->destPort, store->destGD); |
if (store->clip) { |
saveClip = NewRgn(); |
GetClip(saveClip); |
SetClip(store->clip); |
} |
DrawPicture(tempPict, &store->destRect); |
if (store->clip) { |
SetClip(saveClip); |
DisposeRgn(saveClip); |
} |
} |
KillPicture(tempPict); |
SetGWorld(savePort, saveGD); |
} |
return err; |
} |
pascal ComponentResult SGPictStop (SGPictGlobals store) |
{ |
store->inRecord = store->inPreview = false; |
return noErr; |
} |
pascal ComponentResult SGPictPause (SGPictGlobals store, Byte pause) |
{ |
store->paused = pause; |
return noErr; |
} |
pascal ComponentResult SGPictPrepare (SGPictGlobals store, Boolean prepareForPreview, Boolean prepareForRecord) |
{ |
store->bytesWritten = 0; |
return noErr; |
} |
pascal ComponentResult SGPictRelease (SGPictGlobals store) |
{ |
return noErr; |
} |
pascal ComponentResult SGPictGetChannelSampleDescription (SGPictGlobals store, Handle sampleDesc) |
{ |
OSErr err; |
SampleDescriptionPtr sdp; |
SetHandleSize(sampleDesc, sizeof(SampleDescription)); |
if (err = MemError()) goto bail; |
// make up a minimal sample description |
sdp = (SampleDescriptionPtr)*sampleDesc; |
sdp->descSize = sizeof(SampleDescription); |
sdp->dataFormat = 'PICT'; |
sdp->resvd1 = 0; |
sdp->resvd2 = 0; |
sdp->dataRefIndex = 0; |
bail: |
return err; |
} |
pascal ComponentResult SGPictGetChannelDeviceList (SGPictGlobals store, long selectionFlags, SGDeviceList *list) |
{ |
*list = (SGDeviceList)NewHandleClear(sizeof(SGDeviceListRecord)); // no devices |
return MemError(); |
} |
pascal ComponentResult SGPictSetChannelDevice (SGPictGlobals store, StringPtr name) |
{ |
return noErr; |
} |
pascal ComponentResult SGPictGetChannelTimeScale (SGPictGlobals store, TimeScale *scale) |
{ |
*scale = kMediaTimeScale; |
return noErr; |
} |
pascal ComponentResult SGPictInitChannel (SGPictGlobals store, SeqGrabComponent owner) |
{ |
// initialize any variable here |
SetRect(&store->srcRect, 0, 0, 160, 120); // size around mouse that we capture |
SetIdentityMatrix(&store->displayMatrix); |
store->grabber = owner; |
SGGetTimeBase(owner, &store->base); |
return noErr; |
} |
pascal ComponentResult SGPictWriteSamples (SGPictGlobals store, Movie m, AliasHandle theFile) |
{ |
OSErr err = 0; |
Track pictT; |
Media pictM; |
long i; |
MatrixRecord aMatrix; |
Rect from, to; |
seqGrabFrameInfo fi; |
TimeRecord tr; |
TimeValue mediaDuration; |
SampleDescriptionHandle sampleDesc = 0; |
if (!(store->usage & seqGrabRecord)) |
return err; |
sampleDesc = (SampleDescriptionHandle)NewHandle(4); |
if (err = MemError()) goto bail; |
if (err = SGGetChannelSampleDescription(store->self, (Handle)sampleDesc)) goto bail; |
SetRect(&from, 0, 0, store->srcRect.right, store->srcRect.bottom); |
to = from; |
TransformRect(&store->displayMatrix, &to, nil); |
pictT = NewMovieTrack(m, (long)from.right << 16, (long)from.bottom << 16, 0); |
pictM = NewTrackMedia(pictT, 'PICT', kMediaTimeScale, (Handle)theFile, rAliasType); |
fi.frameChannel = store->self; |
i = -1; |
do { |
TimeValue frameDuration; |
err = SGGetNextFrameReference(store->grabber, &fi, &frameDuration, &i); |
if (err) { |
if (err == paramErr) |
err = 0; |
break; |
} |
err = AddMediaSampleReference(pictM, |
fi.frameOffset, fi.frameSize, |
frameDuration, |
sampleDesc, 1, |
0, 0); |
if (err == invalidDuration) { |
err = noErr; |
break; |
} |
} while (!err); |
done: |
if (err) goto bail; |
GetTimeBaseTime(store->base, 0, &tr); |
ConvertTimeScale(&tr, kMediaTimeScale); // trim media inserted to not extend beyond end time |
mediaDuration = GetMediaDuration(pictM); |
if (tr.value.lo > mediaDuration) |
tr.value.lo = mediaDuration; // this should never happen, |
// but avoiding an error at this step seems like a good idea |
err = InsertMediaIntoTrack(pictT, 0, 0, tr.value.lo, kFix1); |
RectMatrix(&aMatrix, &from, &to); |
SetTrackMatrix( pictT, &aMatrix ); |
if (store->clip) SetTrackClipRgn(pictT, store->clip); |
bail: |
DisposHandle((Handle)sampleDesc); |
return err; |
} |
pascal ComponentResult SGPictGetDataRate (SGPictGlobals store, long *bytesPerSecond) |
{ |
// take a guess at our data rate |
*bytesPerSecond = 24 * 1024; |
if (store->bytesWritten) { |
TimeValue timeNow = GetTimeBaseTime(store->base, 8, nil); // 1/8th second resolution |
if (!timeNow) |
return seqGrabInfoNotAvailable; |
*bytesPerSecond = (store->bytesWritten / timeNow) * 8; // convert back to seconds |
} |
return noErr; |
} |
/************************ |
SG Pict Channel |
Specific Calls |
************************/ |
pascal ComponentResult SGPictSetShowTickCount (SGPictGlobals store, Boolean show) |
{ |
store->showTickCount = show; |
return noErr; |
} |
pascal ComponentResult SGPictGetShowTickCount (SGPictGlobals store, Boolean *show) |
{ |
*show = store->showTickCount; |
return noErr; |
} |
/************************ |
Panel Calls |
************************/ |
pascal ComponentResult SGPictPanelGetDitl (SGPictGlobals store, Handle *ditl) |
{ |
*ditl = GetResource('DITL', 7000); |
if (!*ditl) return resNotFound; |
DetachResource(*ditl); |
return noErr; |
} |
pascal ComponentResult SGPictPanelInstall (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset) |
{ |
Rect newBounds; |
short kind; |
Handle h; |
// reset this channel to use the dialog window and be in preview mode with no clip |
SGSetGWorld(store->self, (CGrafPtr)d, GetMainDevice()); |
SGGetChannelUsage(store->self, &store->saveUsage); |
SGSetChannelUsage(store->self, seqGrabPreview); |
SGSetChannelClip(c, nil); |
GetDItem(d, 1 + itemOffset, &kind, &h, &newBounds); |
SGSetChannelBounds(c, &newBounds); |
SGStartPreview(store->self); |
return noErr; |
} |
pascal ComponentResult SGPictPanelEvent (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset, |
EventRecord *theEvent, short *itemHit, Boolean *handled) |
{ |
if (theEvent->what == nullEvent) |
return SGIdle(store->self); |
return noErr; |
} |
pascal ComponentResult SGPictPanelRemove (SGPictGlobals store, SGChannel c, DialogPtr d, short itemOffset) |
{ |
SGStop(store->self); |
SGRelease(store->self); |
// note that the clip and bounds are automatically restored for us because they were stored by us with the |
// SGGetSettings call |
SGSetChannelUsage(store->self, store->saveUsage); |
return noErr; |
} |
pascal ComponentResult SGPictPanelGetSettings (SGPictGlobals store, SGChannel c, UserData *result, long flags) |
{ |
OSErr err = noErr; |
UserData ud = 0; |
MatrixRecord matrix; |
RgnHandle clip; |
if (err = NewUserData(&ud)) goto bail; |
// add matrix to user data |
if (SGGetChannelMatrix(c, &matrix) == noErr) { |
if (err = SetUserDataItem(ud, &matrix, sizeof(matrix), sgMatrixType, 1)) goto bail; |
} |
// store clip, if there is one |
if (SGGetChannelClip(c, &clip) == noErr) { |
if (clip) |
err = AddUserData(ud, (Handle)clip, sgClipType); |
else |
err = SetUserDataItem(ud, nil, 0, sgClipType, 1); // add a dummy to indicate none |
DisposeRgn(clip); |
if (err) goto bail; |
} |
bail: |
if (err) { |
DisposeUserData(ud); |
ud = 0; |
} |
*result = ud; |
return err; |
} |
pascal ComponentResult SGPictPanelSetSettings (SGPictGlobals store, SGChannel c, UserData ud, long flags) |
{ |
OSErr err; |
RgnHandle clip = NewRgn(); |
MatrixRecord matrix; |
// restore clip, if one was stored |
if (GetUserData(ud, (Handle)clip, sgClipType, 1) == noErr) { |
if (err = SGSetChannelClip(c, GetHandleSize((Handle)clip) ? clip : 0)) goto bail; |
} |
// restore matrix |
if (err = GetUserDataItem(ud, &matrix, sizeof(matrix), sgMatrixType, 1)) goto bail; |
if (err = SGSetChannelMatrix(c, &matrix)) goto bail; |
bail: |
DisposeRgn(clip); |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14