/* InitBitMap: assumes that the BitMap is declared, and that its bound are known and already set in BitMap->bounds. All the function does is to allocate the proper sized memory space in BitMap->rowBytes and BitMap->baseAddr, according to the most efficient size rule for CopyBits usage, which is: the width must be an even multiple of 8 bits which at least equal to the number of bits needed for the width of the image. */ /* LoadPicResIntoBitmap: given a resource file name, a picID and a pointer to a bitmap, will load said PICT resource into an offscreen bitmap. This function uses InitBitMap, CreateOffscreenBitMap and DestroyOffscreenBitmap. It sets a temporary offscreen port to draw the PICT resource into the bitmap space, and cleans up everything afterward. */ /* CreateOffscreenBitMap: can be used for standalone "sprite graphics" which are sized appropriately for PICT resources, for example. Can also be used for a double buffer technique, in which a duplicate of the screen can be tailored with "silently", is screen sized and then copied over completely in one CopyBits pass into the viewable screen. I'm not sure this is viable for Mac Plus speeds, though. It is much preferable to use CopyBits to stay on the safe side. */ /* DestroyOffscreenBitMap: destroys an offscreen GrafPtr when you're done with it */ Boolean InitBitMap(BitMap *loadBM); Boolean LoadPicResIntoBitMap(BitMap *loadBM,int picID, ConstStr255Param fileName); Boolean CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds); void DestroyOffscreenBitMap(GrafPtr oldOffscreen); Boolean InitBitMap(BitMap *loadBM) { loadBM->rowBytes = ((loadBM->bounds.right - loadBM->bounds.left + 15) >> 4) << 1; /* number of bytes in BitMap is rowBytes * number of rows */ loadBM->baseAddr = NewPtr(loadBM->rowBytes * (long) (loadBM->bounds.bottom - loadBM->bounds.top)); if (loadBM->baseAddr == nil) return FALSE; return TRUE; } Boolean LoadPicResIntoBitMap(BitMap *loadBM,int picID, ConstStr255Param fileName) { PicHandle myPicH; int resID; GrafPtr oldG, newG; BitMap *oldBM; /* Performs a check for bogus or incomplete parameters */ if(!(loadBM) || !(picID) || !(fileName)) return FALSE; /* saves port before function call, will restore at end */ GetPort(&oldG); oldBM=&(oldG->portBits); /* 5 following lines handle the PICT retrieval */ resID=OpenResFile(fileName); if(!resID) ExitToShell(); myPicH=GetPicture(picID); if(myPicH==NULL) ExitToShell(); HLock((Handle)myPicH); loadBM->bounds=(*myPicH)->picFrame; InitBitMap(loadBM); /* Next line creates a new port with the correct sized Rect read from the PICT */ if (!CreateOffscreenBitMap(&newG, &(loadBM->bounds))) { SysBeep(1); ExitToShell(); } SetPort(newG); SetPortBits(loadBM); EraseRect(&(loadBM->bounds)); /* Once the offscreen BitMap object is set as the port, draw onto it from the picHandle*/ DrawPicture(myPicH,&(loadBM->bounds)); HUnlock((Handle)myPicH); /* Last lines take care of the cleanup, hopefully the BitMap is still usable */ SetPort(oldG); SetPortBits(oldBM); DestroyOffscreenBitMap(newG); return TRUE; } Boolean CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds) { GrafPtr savePort; GrafPtr newPort; BitMap *oldBM; GetPort(&savePort); /* need this to restore thePort after OpenPort */ oldBM=&(savePort->portBits); newPort = (GrafPtr) NewPtr(sizeof(GrafPort)); /* allocate the grafPort */ if (MemError() != noErr) return FALSE; /* failed to allocate the off-screen port */ /* the call to OpenPort does the following . . . allocates space for visRgn (set to screenBits.bounds) and clipRgn (set wide open) sets portBits to screenBits sets portRect to screenBits.bounds (See Inside Mac: Imaging with QuickDraw, pages 2-38 to 2-39) side effect: does a SetPort(&offScreen) */ OpenPort(newPort); /* make bitmap the size of the bounds that caller supplied */ newPort->portRect = *inBounds; newPort->portBits.bounds = *inBounds; RectRgn(newPort->clipRgn, inBounds); /* avoid wide-open clipRgn, be safe */ RectRgn(newPort->visRgn, inBounds); /* in case newBounds is screen bounds */ /* rowBytes is size of row, it must be rounded up to an even number of bytes */ newPort->portBits.rowBytes = ((inBounds->right - inBounds->left + 15) >> 4) << 1; /* number of bytes in BitMap is rowBytes * number of rows */ /* see notes at end of Technote about using _NewHandle rather than _NewPtr*/ newPort->portBits.baseAddr = NewPtr(newPort->portBits.rowBytes * (long) (inBounds->bottom - inBounds->top)); if (newPort->portBits.baseAddr == nil) { /* check to see if we had enough room for the bits */ SetPort(savePort); ClosePort(newPort); /* dump the visRgn and clipRgn */ DisposPtr((Ptr)newPort); /* dump the GrafPort */ return false; /* tell caller we failed */ } /* since the bits are just memory, let's clear them before we start*/ EraseRect(inBounds); /* OpenPort did a SetPort(newPort) so we are ok */ *newOffscreen = newPort; SetPort(savePort); SetPortBits(oldBM); return TRUE; /* tell caller we succeeded! */ } void DestroyOffscreenBitMap(GrafPtr oldOffscreen) { ClosePort(oldOffscreen); /* dump the visRgn and clipRgn */ DisposePtr(oldOffscreen->portBits.baseAddr); DisposPtr((Ptr)oldOffscreen); /* dump the port */ }