/* Prototypes */ PicHandle CreatePICT2( PixMap *srcBits, Rect *srcRect, Rect *dstRect, short mode ); void PutOutPixMapSrcRectDstRectAndMode( PixMap *srcBits, short** inPicPtr, Rect *srcRect, Rect *dstRect, short mode ); long PutOutPackedIndexedPixData( PixMap *srcBits, short **picPtr ); long PutOutPackedDirectPixData( PixMap *srcBits, short **picPtr ); PicHandle CreatePICT2(PixMap *srcBits, Rect *srcRect, Rect *dstRect, short mode) { PicHandle myPic; short myRowBytes; short *picPtr; short iii; long handleSize; #define CLIPSIZE 12 #define PIXMAPRECSIZE 50 #define HEADERSIZE 40 #define MAXCOLORTABLESIZE 256*8+8 #define OPCODEMISCSIZE 2+8+8+2 /* opcode+srcRect+dstRect+mode */ #define ENDOFPICTSIZE 2 #define PICSIZE PIXMAPRECSIZE + HEADERSIZE + MAXCOLORTABLESIZE +\ ENDOFPICTSIZE + OPCODEMISCSIZE + CLIPSIZE myRowBytes = srcBits->rowBytes & 0x3fff; /* Allocate worst-case memory scenario using PackBits packing. */ myPic = (PicHandle) NewHandle( PICSIZE + (long)((myRowBytes/127)+2+myRowBytes)*(long)(srcBits->bounds.bottom - srcBits->bounds.top)); if(!myPic) return(0); /* Skip picSize and put out picFrame (10 bytes). */ picPtr = (short *) (((long)*myPic) + 2); *picPtr++ = dstRect->top; *picPtr++ = dstRect->left; *picPtr++ = dstRect->bottom; *picPtr++ = dstRect->right; /* Put out header (30 bytes). This could be done from a resource or taken from an existing picture. */ *picPtr++ = 0x11; /* Version opcode. */ *picPtr++ = 0x2ff; /* Version number. */ *picPtr++ = 0xC00; /* Header opcode. */ *picPtr++ = 0xFFFF; /* Put out PICT header version. */ *picPtr++ = 0xFFFF; /* The rest of the header is ignored--0 it out. */ for(iii = 10; iii > 0; iii--) *picPtr++ = 0; /* Write out 24 bytes of 0. */ /* Put out current port's clip region. */ *picPtr++ = 0x01; *picPtr++ = 0x0A; /* Clip region only has bounds rectangle. */ *picPtr++ = (**thePort->clipRgn).rgnBBox.top; *picPtr++ = (**thePort->clipRgn).rgnBBox.left; *picPtr++ = (**thePort->clipRgn).rgnBBox.bottom; *picPtr++ = (**thePort->clipRgn).rgnBBox.right; HLock(myPic); if(srcBits->pixelType == RGBDirect) { /* Must be 32-bits/pixel */ /* Put out opCode $9A, DirectBitsRect. */ *picPtr++ = 0x9A; *picPtr++ = 0; /* BaseAddr for direct pixMaps is 0x000000FF. */ *picPtr++ = 0xFF; PutOutPixMapSrcRectDstRectAndMode(srcBits, &picPtr, srcRect, dstRect, mode); if(PutOutPackedDirectPixData(srcBits, &picPtr)) /* Nonzero indicates an error. */ goto errorExit; } else { /* Put out opCode $98, PackBitsRect. */ *picPtr++ = 0x98; PutOutPixMapSrcRectDstRectAndMode(srcBits, &picPtr, srcRect, dstRect, mode); if(PutOutPackedIndexedPixData(srcBits, &picPtr)) /* Nonzero indicates an error. */ goto errorExit; } HUnlock(myPic); /* All done! Put out end-of-picture opcode, $00FF. */ *picPtr++ = 0x00FF; /* Size handle down to the amount actually used. */ handleSize = (long) picPtr - (long) *myPic; SetHandleSize( myPic, handleSize ); /* Write out picture size. */ *((short *)*myPic) = (short) handleSize; return(myPic); errorExit: DisposHandle(myPic); return(0); } void PutOutPixMapSrcRectDstRectAndMode( PixMap *srcBits, short** inPicPtr, Rect *srcRect, Rect *dstRect, short mode ) { short iii; short * picPtr = *inPicPtr; short myRowBytes = srcBits->rowBytes & 0x3fff; /* put out pixMap */ *picPtr++ = srcBits->rowBytes | 0x8000; /*always make PixMaps */ *picPtr++ = srcBits->bounds.top; /* Bounds */ *picPtr++ = srcBits->bounds.left; *picPtr++ = srcBits->bounds.bottom; *picPtr++ = srcBits->bounds.right; *picPtr++ = 0; /* version number */ /* ** Put out packing format: ** 0 is default indexed packing. ** 1 is no packing (rowBytes < 8 ) ** 4 is default direct packing - run length encoded scan lines by component, red first. */ if( myRowBytes < 8 && myRowBytes > 0 ) *picPtr++ = 1; /* packing format: unpacked */ else { if( srcBits->pixelType == RGBDirect ) *picPtr++ = 4; else *picPtr++ = 0; /* packing format: standard */ } *picPtr++ = 0; /* packed size */ *picPtr++ = 0; *picPtr++ = 0x48; /* horizontal resolution: $0048 0000 */ *picPtr++ = 0; *picPtr++ = 0x48; /* vertical resolution: $0048 0000 */ *picPtr++ = 0; /* these fields are different for BitMap/PixMap */ if( srcBits->rowBytes < 0 ) {/* do PixMap */ *picPtr++ = srcBits->pixelType; *picPtr++ = srcBits->pixelSize; /* pixel size */ *picPtr++ = srcBits->cmpCount; /* number of components */ *picPtr++ = srcBits->cmpSize; /* size of each component */ } else {/* do BitMap */ *picPtr++ = 0; *picPtr++ = 1; /* pixel size */ *picPtr++ = 1; /* number of components */ *picPtr++ = 1; /* size of each component */ } *picPtr++ = 0; /* offset to next plane */ *picPtr++ = 0; if( srcBits->pixelType == RGBDirect ) { *picPtr++ = 0; /* color table is nil for Direct pixmaps*/ *picPtr++ = 0; } else { *picPtr++ = (unsigned short) srcBits->pmTable>>16; /* color table */ *picPtr++ = (unsigned short) srcBits->pmTable; } *picPtr++ = 0; /* reserved */ *picPtr++ = 0; /* put out colortable if indexed pixmap*/ if( (srcBits->rowBytes < 0) && (srcBits->pmTable) && (srcBits->pixelType != RGBDirect) ) { short* ctPtr = (short *) *(srcBits->pmTable); /* Get ptr to color table */ *picPtr++ = *ctPtr++; /* copy ctSeed */ *picPtr++ = *ctPtr++; *picPtr++ = *ctPtr++; /* copy ctFlags */ iii = *ctPtr; *picPtr++ = *ctPtr++; /* copy ctSize */ for( ; iii >= 0; iii-- ) {/* put out all entries */ *picPtr++ = *ctPtr++; /* pixel value */ *picPtr++ = *ctPtr++; /* red */ *picPtr++ = *ctPtr++; /* green */ *picPtr++ = *ctPtr++; /* blue */ } } else if( srcBits->pixelType != RGBDirect ) { for( iii = 8; iii > 0; iii-- ) *picPtr++ = 0; /* put out an empty color table: 8 words of 0 */ } /* put out srcrect, dstrect, and mode */ *picPtr++ = srcRect->top; *picPtr++ = srcRect->left; *picPtr++ = srcRect->bottom; *picPtr++ = srcRect->right; *picPtr++ = dstRect->top; *picPtr++ = dstRect->left; *picPtr++ = dstRect->bottom; *picPtr++ = dstRect->right; *picPtr++ = mode; *inPicPtr = picPtr; } long PutOutPackedIndexedPixData( PixMap *srcBits, short **picPtr ) { Ptr srcPtr = srcBits->baseAddr; Ptr dstPtr; Ptr packBuf; Ptr tempPicPtr = (char*) *picPtr; short packedSize; short iii, jjj; unsigned short myRowBytes; myRowBytes = srcBits->rowBytes & 0x3fff; /* put out PixData */ if( myRowBytes < 8 ) { /* no packing */ short * pixMapPtr = (short *) srcBits->baseAddr; for( iii = (myRowBytes*(srcBits->bounds.bottom - srcBits->bounds.top))/2; iii > 0; iii-- ) *tempPicPtr++ = *pixMapPtr++; return( 0 ); } packBuf = (Ptr)NewPtr( myRowBytes * 2 ); if( !packBuf ) return( -1 ); /* Must use only byte accesses to avoid address errors on 68K class machines */ for( iii = srcBits->bounds.bottom - srcBits->bounds.top; iii > 0; iii-- ) { dstPtr = packBuf; PackBits( &srcPtr, &dstPtr, myRowBytes ); packedSize = (long)dstPtr - (long)packBuf; if( myRowBytes <= 250 ) { /* put a byte to the picture */ *tempPicPtr++ = (unsigned char)packedSize; } else { /* put a word to the picture */ *tempPicPtr++ = (unsigned char)(packedSize>>8); *tempPicPtr++ = (unsigned char)packedSize; } /* put the packed data out */ dstPtr = packBuf; for( jjj = packedSize; jjj > 0; jjj-- ) { *tempPicPtr++ = *dstPtr++; } } DisposPtr( packBuf ); if( (long)tempPicPtr & (long)0x0001 ) /* do long alignment */ tempPicPtr++; *picPtr = (short *) tempPicPtr; return( 0 ); } long PutOutPackedDirectPixData( PixMap *srcBits, short **picPtr ) { Ptr srcPtr; Ptr dstPtr; Ptr packBuf; Ptr srcBuf; Ptr srcBufPtr; Ptr tempPicPtr = (char*) *picPtr; short packedSize; short iii, jjj, kkk; unsigned short myRowBytes = srcBits->rowBytes & 0x3fff; unsigned short componentRowBytes = myRowBytes>>2; /* put out PixData */ if( myRowBytes < 8 ) { /* no packing */ short * pixMapPtr = (short *) srcBits->baseAddr; for( iii = (myRowBytes*(srcBits->bounds.bottom - srcBits->bounds.top))/2; iii > 0; iii-- ) *tempPicPtr++ = *pixMapPtr++; return( 0 ); } packBuf = (Ptr)NewPtr( myRowBytes * 2 ); if( !packBuf ) return( -1 ); /* allocate a buffer for separating the components */ srcBuf = (Ptr)NewPtr( componentRowBytes*3 ); if( !srcBuf ) return( -1 ); /* Must use only byte accesses to avoid address errors on 68K class machines */ for( iii = 0; iii < srcBits->bounds.bottom - srcBits->bounds.top; iii++ ) { srcBufPtr = srcBuf; for( jjj = 1; jjj <= 3; jjj++ ) /* Do red, green, and blue */ { srcPtr = srcBits->baseAddr + (unsigned long)myRowBytes * iii; srcPtr += jjj; /*point to this component */ for( kkk = 0; kkk < componentRowBytes; kkk++ ) { *srcBufPtr++ = *srcPtr; srcPtr += 4; } } dstPtr = packBuf; srcBufPtr = srcBuf; PackBits( &srcBufPtr, &dstPtr, componentRowBytes*3 ); packedSize = (long)dstPtr - (long)packBuf; if( myRowBytes <= 250 ) { /* put a byte to the picture */ *tempPicPtr++ = (unsigned char)packedSize; } else { /* put a word to the picture */ *tempPicPtr++ = (unsigned char)(packedSize>>8); *tempPicPtr++ = (unsigned char)packedSize; } /* put the packed data out */ dstPtr = packBuf; for( kkk = packedSize; kkk > 0; kkk-- ) { *tempPicPtr++ = *dstPtr++; } } DisposPtr( packBuf ); DisposPtr( srcBuf ); if( (long)tempPicPtr & (long)0x0001 ) /* do long alignment */ tempPicPtr++; *picPtr = (short *) tempPicPtr; return( 0 ); }