/* File: Dissolve.c Copyright 1990 by Thomas Knoll. Copyright 1993 by Adobe Systems, Inc. C source file for Dissolve example. */ #include #include #include #include #include #include #include #include #include #include "PITypes.h" #include "PIGeneral.h" #include "PIFilter.h" #include "DialogUtilities.h" #include "PIUtilities.h" #ifdef THINK_C #define ENTRYPOINT main #endif /*****************************************************************************/ typedef struct TParameters { short percent; } TParameters, *PParameters, **HParameters; /*****************************************************************************/ typedef struct Globals { short result; FilterRecord *stuff; } Globals, *GPtr, **GHdl; #define gResult ((**globals).result) #define gStuff ((**globals).stuff) /*****************************************************************************/ void InitGlobals (GHdl globals); void DoAbout (GHdl globals); void DoParameters (GHdl globals); void DoPrepare (GHdl globals); void DoStart (GHdl globals); void DoContinue (GHdl globals); void DoFinish (GHdl globals); /*****************************************************************************/ /* All calls to the plug-in module come through this routine. It must be placed first in the resource. To achieve this, most development systems require that this be the first routine in the source. */ pascal void ENTRYPOINT (short selector, FilterRecord *stuff, long *data, short *result) { GHdl globals; if (!*data) { *data = (long) NewHandle (sizeof (Globals)); if (!*data) { *result = memFullErr; return; } InitGlobals ((GHdl) *data); } globals = (GHdl) *data; gStuff = stuff; gResult = noErr; switch (selector) { case filterSelectorAbout: DoAbout (globals); break; case filterSelectorParameters: DoParameters (globals); break; case filterSelectorPrepare: DoPrepare (globals); break; case filterSelectorStart: DoStart (globals); break; case filterSelectorContinue: DoContinue (globals); break; case filterSelectorFinish: DoFinish (globals); break; default: gResult = filterBadParameters; } *result = gResult; } /*****************************************************************************/ void InitGlobals (GHdl globals) { #pragma unused (globals) /* None of the globals requires initialization. */ } /*****************************************************************************/ /* Displays the about dialog box for the plug-in module. */ void DoAbout (GHdl globals) { #pragma unused (globals) #define dialogID 16000 ShowAbout (dialogID); #undef dialogID } /*****************************************************************************/ static ProcessEventProc gProcessEvent = NULL; MACPASCAL void ProcessEvent(void *event) { if (gProcessEvent != NULL) { #ifdef __powerc CallUniversalProc((UniversalProcPtr)gProcessEvent, uppProcessEventProcInfo, event); #else (*gProcessEvent)(event); #endif } } /*****************************************************************************/ /* Asks the user for the plug-in filter module's parameters. Note that the image size information is not yet defined at this point. Also, do not assume that the calling program will call this routine every time the filter is run (it may save the data held by the parameters handle in a macro file). */ void DoParameters (GHdl globals) { #define dialogID 16001 #define hookItem 3 #define percentItem 4 long x; short item; DialogPtr dp; DialogTHndl dt; if (!gStuff->parameters) { gStuff->parameters = NewHandle ((long) sizeof (TParameters)); if (!gStuff->parameters) { gResult = memFullErr; return; } ((PParameters) *gStuff->parameters)->percent = 50; } dt = (DialogTHndl) GetResource ('DLOG', dialogID); HNoPurge ((Handle) dt); CenterDialog (dt); SetUpMoveableModal (dt, gStuff->hostSig); dp = GetNewDialog (dialogID, nil, (WindowPtr) -1); SetOutlineOKHook (dp, hookItem); StuffNumber (dp, percentItem, ((PParameters) *gStuff->parameters)->percent); SetArrowCursor (); SelectTextItem (dp, percentItem); do { gProcessEvent = gStuff->processEvent; MoveableModalDialog (dp, &ProcessEvent, nil, &item); gProcessEvent = NULL; if (item == ok) { if (!FetchNumber (dp, percentItem, 1, 99, &x)) item = 0; } } while (item != ok && item != cancel); DisposDialog (dp); HPurge ((Handle) dt); if (item == cancel) { gResult = 1; return; } ((PParameters) *gStuff->parameters)->percent = x; #undef dialogID #undef hookItem #undef percentItem } /*****************************************************************************/ /* Prepare to filter an image. If the plug-in filter needs a large amount of buffer memory, this routine should set the bufferSpace field to the number of bytes required. */ void DoPrepare (GHdl globals) { gStuff->bufferSpace = 0; } /*****************************************************************************/ void DoInitialRect (GHdl globals); Boolean DoNextRect (GHdl globals); void DoFilterRect (GHdl globals); /*****************************************************************************/ /* Requests pointer to the first part of the image to be filtered. */ void DoStart (GHdl globals) { DoInitialRect (globals); } /*****************************************************************************/ /* Filters the area and requests the next area. */ void DoContinue (GHdl globals) { if (TestAbort ()) { gResult = 1; return; } DoFilterRect (globals); if (!DoNextRect (globals)) { SetRect (&gStuff->inRect, 0, 0, 0, 0); SetRect (&gStuff->outRect, 0, 0, 0, 0); } } /*****************************************************************************/ /* Requests first part of the image to be filtered. */ void DoInitialRect (GHdl globals) { gStuff->inRect = gStuff->filterRect; gStuff->inRect.bottom = gStuff->inRect.top + 1; gStuff->inLoPlane = 0; gStuff->inHiPlane = gStuff->planes - 1; gStuff->outRect = gStuff->inRect; gStuff->outLoPlane = gStuff->inLoPlane; gStuff->outHiPlane = gStuff->inHiPlane; } /*****************************************************************************/ /* Request the next area. */ Boolean DoNextRect (GHdl globals) { gStuff->inRect.top = gStuff->inRect.top + 1; gStuff->inRect.bottom = gStuff->inRect.bottom + 1; gStuff->outRect = gStuff->inRect; return gStuff->inRect.top < gStuff->filterRect.bottom; } /*****************************************************************************/ /* Filter the area. */ void DoFilterRect (GHdl globals) { short rand; short count; short plane; short percent; unsigned char *srcPtr; unsigned char *dstPtr; UpdateProgress ((long) gStuff->inRect.top - gStuff->filterRect.top, (long) gStuff->filterRect.bottom - gStuff->filterRect.top); percent = ((PParameters) *gStuff->parameters)->percent; srcPtr = (unsigned char *) gStuff->inData; dstPtr = (unsigned char *) gStuff->outData; count = gStuff->filterRect.right - gStuff->filterRect.left; while (count--) { rand = Random (); rand = (rand < 0 ? -rand : rand); if (rand % 100 < percent) { for (plane = 0; plane < gStuff->planes; ++plane) *(dstPtr++) = plane < 4 ? gStuff->backColor [plane] : 255; srcPtr += gStuff->planes; } else for (plane = 0; plane < gStuff->planes; ++plane) *(dstPtr++) = *(srcPtr++); } } /*****************************************************************************/ /* This routine will always be called if DoStart does not return an error (even if DoContinue returns an error or the user aborts the operation). This allows the module to perform any needed cleanup. None is required in this example. */ void DoFinish (GHdl globals) { /* We will attempt to add a resource showing that we made this change. Unfortunately, we will not be able to remove this resource if the user chooses undo. This could change in the future, so do not count on it. */ Str255 string; short stringLength; short numLength; Handle h; if (!ResourceProcsAvailable (NULL)) return; GetIndString (string, 16000, 1); stringLength = (unsigned char) (string [0]); h = PINewHandle (stringLength); if (!h) return; BlockMove (&(string [1]), PILockHandle (h, FALSE), stringLength); PIUnlockHandle (h); NumToString (((PParameters) *gStuff->parameters)->percent, string); numLength = (unsigned char) string [0]; if (PISetHandleSize (h, stringLength + numLength + 1) == noErr) { BlockMove (&(string [1]), PILockHandle (h, FALSE) + stringLength, numLength); PIUnlockHandle (h); stringLength += numLength; (*h) [stringLength] = '%'; (void) AddPIResource ('hist', h); } PIDisposeHandle (h); } /*****************************************************************************/