/* File: SimpleFormat.c Copyright 1993 by Adobe Systems, Inc. */ #include #include #include #include #include #include #include #include #include #include "PITypes.h" #include "PIGeneral.h" #include "PIFormat.h" #include "DialogUtilities.h" #include "PIUtilities.h" #ifdef THINK_C #define ENTRYPOINT main #endif /*****************************************************************************/ typedef struct GlobalData { FormatRecordPtr stuff; short result; BufferID pixelBuffer; Ptr pixelData; int32 rowBytes; int32 done; int32 total; } Globals, *GPtr, **GHdl; /*****************************************************************************/ #define gStuff ((**globals).stuff) #define gResult ((**globals).result) #define gPixelBuffer ((**globals).pixelBuffer) #define gPixelData ((**globals).pixelData) #define gRowBytes ((**globals).rowBytes) #define gDone ((**globals).done) #define gTotal ((**globals).total) /*****************************************************************************/ void InitGlobals (GHdl globals); void DoAbout (GHdl globals); void DoReadPrepare (GHdl globals); void DoReadStart (GHdl globals); void DoReadContinue (GHdl globals); void DoReadFinish (GHdl globals); void DoOptionsPrepare (GHdl globals); void DoOptionsStart (GHdl globals); void DoOptionsContinue (GHdl globals); void DoOptionsFinish (GHdl globals); void DoEstimatePrepare (GHdl globals); void DoEstimateStart (GHdl globals); void DoEstimateContinue (GHdl globals); void DoEstimateFinish (GHdl globals); void DoWritePrepare (GHdl globals); void DoWriteStart (GHdl globals); void DoWriteContinue (GHdl globals); void DoWriteFinish (GHdl globals); /*****************************************************************************/ typedef struct FileHeader { int16 mode; int16 depth; int16 rows; int16 cols; int16 planes; int32 resourceLength; } FileHeader; /*****************************************************************************/ /* Main dispatching routine. Initializes and sets up the global variables, and performs the operation specified by the selector. */ pascal void ENTRYPOINT (short selector, FormatRecordPtr stuff, long *data, short *result) { /* Set up the globals. */ GHdl globals; if (!*data) { *data = (long) NewHandle (sizeof (Globals)); if (!*data) { *result = memFullErr; return; } InitGlobals ((GHdl) *data); } globals = (GHdl) *data; /* Perform the requested operation */ gStuff = stuff; gResult = noErr; switch (selector) { case formatSelectorAbout: DoAbout (globals); break; case formatSelectorReadPrepare: DoReadPrepare (globals); break; case formatSelectorReadStart: DoReadStart (globals); break; case formatSelectorReadContinue: DoReadContinue (globals); break; case formatSelectorReadFinish: DoReadFinish (globals); break; case formatSelectorOptionsPrepare: DoOptionsPrepare (globals); break; case formatSelectorOptionsStart: DoOptionsStart (globals); break; case formatSelectorOptionsContinue: DoOptionsContinue (globals); break; case formatSelectorOptionsFinish: DoOptionsFinish (globals); break; case formatSelectorEstimatePrepare: DoEstimatePrepare (globals); break; case formatSelectorEstimateStart: DoEstimateStart (globals); break; case formatSelectorEstimateContinue: DoEstimateContinue (globals); break; case formatSelectorEstimateFinish: DoEstimateFinish (globals); break; case formatSelectorWritePrepare: DoWritePrepare (globals); break; case formatSelectorWriteStart: DoWriteStart (globals); break; case formatSelectorWriteContinue: DoWriteContinue (globals); break; case formatSelectorWriteFinish: DoWriteFinish (globals); break; default: gResult = formatBadParameters; } *result = gResult; } /*****************************************************************************/ /* Sets the global variables to their default values. */ void InitGlobals (GHdl globals) { Ptr p; int16 count; p = (Ptr) *globals; count = sizeof(Globals); while (count--) *p++ = 0; } /*****************************************************************************/ /* Displays the about dialog box for the plug-in module. */ void DoAbout (GHdl globals) { #pragma unused (globals) #define dialogID 16000 ShowAbout (dialogID); #undef dialogID } /*****************************************************************************/ Boolean CheckForServices (GHdl globals) { return WarnBufferProcsAvailable (); } /*****************************************************************************/ int32 RowBytes (GHdl globals) { return (gStuff->imageSize.h * (int32) gStuff->depth + 7) >> 3; } /*****************************************************************************/ void AllocatePixelBuffer (GHdl globals) { BufferID buffer; /* We will want a buffer that is one line wide. */ gPixelBuffer = 0; gRowBytes = RowBytes (globals); gResult = AllocateBuffer (gRowBytes, &buffer); if (gResult == noErr) { gPixelBuffer = buffer; gPixelData = LockBuffer (gPixelBuffer, FALSE); } } /*****************************************************************************/ void DisposePixelBuffer (GHdl globals) { if (gPixelBuffer) { BufferID buffer = gPixelBuffer; /* Globals can move! */ FreeBuffer (buffer); gPixelBuffer = 0; gPixelData = 0; } } /*****************************************************************************/ void DoReadPrepare (GHdl globals) { /* Allow some space for the image resources if handle procs are unavailable. */ if (!HandleProcsAvailable (NULL)) gStuff->maxData = 0x010000L; else gStuff->maxData = 0; } /*****************************************************************************/ void ReadSome (GHdl globals, int32 count, void *buffer) { int32 readCount = count; if (gResult != noErr) return; gResult = FSRead (gStuff->dataFork, &readCount, buffer); if (gResult == noErr && readCount != count) gResult = eofErr; } /*****************************************************************************/ void WriteSome (GHdl globals, int32 count, void *buffer) { int32 writeCount = count; if (gResult != noErr) return; gResult = FSWrite (gStuff->dataFork, &writeCount, buffer); if (gResult == noErr && writeCount != count) gResult = dskFulErr; } /*****************************************************************************/ void ReadRow (GHdl globals) { ReadSome (globals, gRowBytes, gPixelData); } /*****************************************************************************/ void WriteRow (GHdl globals) { WriteSome (globals, gRowBytes, gPixelData); } /*****************************************************************************/ void DisposeImageResources (GHdl globals) { if (gStuff->imageRsrcData) { PIDisposeHandle (gStuff->imageRsrcData); gStuff->imageRsrcData = NULL; gStuff->imageRsrcSize = 0; } } /*****************************************************************************/ void DoReadStart (GHdl globals) { FileHeader header; /* Exit if we have already encountered an error. */ if (gResult != noErr) return; /* Check for the needed services. */ if (!CheckForServices (globals)) { gResult = 1; return; } /* If we have not encountered an error, then we want to read the file header. */ gResult = SetFPos (gStuff->dataFork, fsFromStart, 0); ReadSome (globals, sizeof (FileHeader), &header); if (gResult != noErr) return; gStuff->imageMode = header.mode; gStuff->imageSize.v = header.rows; gStuff->imageSize.h = header.cols; gStuff->depth = header.depth; gStuff->planes = header.planes; /* Next, we will try to read the image resources. */ if (header.resourceLength > 0) { gStuff->imageRsrcData = PINewHandle (header.resourceLength); if (!gStuff->imageRsrcData) { gResult = memFullErr; return; } ReadSome (globals, header.resourceLength, PILockHandle (gStuff->imageRsrcData, FALSE)); PIUnlockHandle (gStuff->imageRsrcData); if (gResult != noErr) goto CleanUp; gStuff->imageRsrcSize = header.resourceLength; } /* Next, we will will read the lookup tables if in indexed color mode. */ if (header.mode == plugInModeIndexedColor) { ReadSome (globals, 3 * sizeof (LookUpTable), &gStuff->redLUT); if (gResult != noErr) goto CleanUp; } /* Set up the progress variables. */ gDone = 0; gTotal = header.rows * (long) header.planes; /* Next, we will allocate the pixel buffer. */ AllocatePixelBuffer (globals); if (gResult != noErr) goto CleanUp; /* Set up to start returning chunks of data. */ gStuff->theRect.top = 0; gStuff->theRect.bottom = 1; gStuff->theRect.left = 0; gStuff->theRect.right = header.cols; gStuff->loPlane = 0; gStuff->hiPlane = 0; gStuff->colBytes = 1; gStuff->rowBytes = gRowBytes; gStuff->planeBytes = 0; /* Read that chunk of data. */ ReadRow (globals); if (gResult == noErr) { gStuff->data = gPixelData; return; } /* The following code does any clean-up work in the event of an error. */ CleanUp: DisposeImageResources (globals); DisposePixelBuffer (globals); } /*****************************************************************************/ void DoReadContinue (GHdl globals) { /* Dispose of the image resource data if it exists. */ DisposeImageResources (globals); /* Exit if we have an error. */ if (gResult != noErr) { gStuff->data = NULL; return; } /* Advance the rectangle. */ gStuff->theRect.top++; gStuff->theRect.bottom++; /* If we have gone off the end, advance the plane. */ if (gStuff->theRect.top >= gStuff->imageSize.v) { gStuff->theRect.top = 0; gStuff->theRect.bottom = 1; gStuff->loPlane++; gStuff->hiPlane++; /* If we are past the last plane. Set data to NULL and return. */ if (gStuff->loPlane >= gStuff->planes) { gStuff->data = NULL; return; } } ReadRow (globals); ++gDone; UpdateProgress (gDone, gTotal); } /*****************************************************************************/ void DoReadFinish (GHdl globals) { /* Dispose of the image resource data if it exists. */ DisposeImageResources (globals); /* Free the pixel buffer. */ DisposePixelBuffer (globals); gStuff->data = NULL; } /*****************************************************************************/ void DoOptionsPrepare (GHdl globals) { gStuff->maxData = 0; } /*****************************************************************************/ void DoOptionsStart (GHdl globals) { /* Check for the needed services. */ if (!CheckForServices (globals)) { gResult = 1; return; } gStuff->data = NULL; } /*****************************************************************************/ void DoOptionsContinue (GHdl globals) { #pragma unused (globals) } /*****************************************************************************/ void DoOptionsFinish (GHdl globals) { #pragma unused (globals) } /*****************************************************************************/ void DoEstimatePrepare (GHdl globals) { gStuff->maxData = 0; } /*****************************************************************************/ void DoEstimateStart (GHdl globals) { int32 dataBytes; /* Check for the needed services. */ if (!CheckForServices (globals)) { gResult = 1; return; } dataBytes = sizeof (FileHeader) + gStuff->imageRsrcSize + RowBytes (globals) * gStuff->planes * gStuff->imageSize.v; if (gStuff->imageMode == plugInModeIndexedColor) dataBytes += 3 * sizeof (LookUpTable); gStuff->minDataBytes = dataBytes; gStuff->maxDataBytes = dataBytes; gStuff->data = NULL; } /*****************************************************************************/ void DoEstimateContinue (GHdl globals) { #pragma unused (globals) } /*****************************************************************************/ void DoEstimateFinish (GHdl globals) { #pragma unused (globals) } /*****************************************************************************/ void DoWritePrepare (GHdl globals) { gStuff->maxData = 0; } /*****************************************************************************/ void DoWriteStart (GHdl globals) { FileHeader header; if (gResult != noErr) return; /* Check for the needed services. */ if (!CheckForServices (globals)) { gResult = 1; return; } /* Write the header. */ gResult = SetFPos (gStuff->dataFork, fsFromStart, 0); header.mode = gStuff->imageMode; header.rows = gStuff->imageSize.v; header.cols = gStuff->imageSize.h; header.depth = gStuff->depth; header.planes = gStuff->planes; if (gStuff->imageRsrcData) header.resourceLength = gStuff->imageRsrcSize; else header.resourceLength = 0; WriteSome (globals, sizeof (FileHeader), &header); if (gResult != noErr) return; /* Write the image resources if any. */ if (header.resourceLength > 0) { WriteSome (globals, header.resourceLength, PILockHandle (gStuff->imageRsrcData, FALSE)); PIUnlockHandle (gStuff->imageRsrcData); if (gResult != noErr) return; } /* Write the lookup tables if appropriate. */ if (header.mode == plugInModeIndexedColor) { WriteSome (globals, 3 * sizeof (LookUpTable), &gStuff->redLUT); if (gResult != noErr) return; } /* Set up the progress variables. */ gDone = 0; gTotal = header.rows * (long) header.planes; /* Next, we will allocate the pixel buffer. */ AllocatePixelBuffer (globals); if (gResult != noErr) return; /* Set up to start receiving chunks of data. */ gStuff->theRect.top = 0; gStuff->theRect.bottom = 1; gStuff->theRect.left = 0; gStuff->theRect.right = header.cols; gStuff->loPlane = 0; gStuff->hiPlane = 0; gStuff->colBytes = 1; gStuff->rowBytes = gRowBytes; gStuff->planeBytes = 0; gStuff->data = gPixelData; } /*****************************************************************************/ void DoWriteContinue (GHdl globals) { /* Exit if we have an error. */ if (gResult != noErr) { gStuff->data = NULL; return; } /* Write the row currently in the buffer. */ WriteRow (globals); if (gResult != noErr) { gStuff->data = NULL; return; } /* Update the progress. */ ++gDone; UpdateProgress (gDone, gTotal); /* Advance the rectangle. */ gStuff->theRect.top++; gStuff->theRect.bottom++; /* If we have gone off the end, advance the plane. */ if (gStuff->theRect.top >= gStuff->imageSize.v) { gStuff->theRect.top = 0; gStuff->theRect.bottom = 1; gStuff->loPlane++; gStuff->hiPlane++; /* If we are past the last plane. Set data to NULL and return. */ if (gStuff->loPlane >= gStuff->planes) gStuff->data = NULL; } } /*****************************************************************************/ void DoWriteFinish (GHdl globals) { DisposePixelBuffer (globals); gStuff->data = NULL; }