home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / VideoToolbox / VideoToolboxSources / RectToAddress.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-14  |  6.1 KB  |  150 lines  |  [TEXT/KAHL]

  1. /* RectToAddress.c
  2. Finds the 32-bit memory address of a pixel in a PixMap or BitMap. Completely
  3. general: multiple screens, on- or off-screen, BitMaps, PixMaps, and any pixel
  4. size. Doesn't require color quickdraw. The optional parameters return the row
  5. length of the pixmap or bitmap, the pixel size, and the offset in bits into the
  6. byte (for pixels that are smaller than a byte).
  7.  
  8. The returned address corresponds to the upper-left pixel in *rectPtr in
  9. *pixMapPtr, AFTER clipping by the bounds associated with the pix/bitmap: If
  10. it's an off-screen Pix/BitMap it clips *rectPtr to the PixMap bounds; if it's
  11. on-screen it clips *rectPtr to that screen device. The returned address is NULL
  12. if *rectPtr is empty after clipping.
  13.  
  14. You should only access the address returned by RectToAddress inside a block of
  15. code that operates in 32-bit addressing mode. Use SwapMMUMode(), which is
  16. documented in Apple's Inside Macintosh.
  17.  
  18. Copyright ©1989-1993 Denis G. Pelli.
  19.  
  20. HISTORY:
  21. 4/89    dgp    v. 1.0 extracted it from CopyBitsQuickly.
  22. 2/91    dgp    v. 1.1 no longer requires color quickdraw.
  23. 4/5/91    dgp    v. 1.2 fixed overflow bug reported by Brady Duga.
  24. 8/24/91    dgp    Made compatible with THINK C 5.0.
  25. 4/27/92    dgp    Though I haven't experienced any problems I took the advice of Apple's
  26.             Inside Mac VI and now get the pixmap base address by means of the new
  27.             GetPixBaseAddr() if that trap is available.
  28. 7/13/92    dgp    enhanced the documentation above. Removed support for THINK C version 4.
  29. 1/11/93    dgp only call GetPixBaseAddr() for PixMap, not for BitMap.
  30. 2/7/93    dgp    return NULL if supplied pix/bitmap pointer is NULL.
  31. 3/14/93    dgp    Use GetPixBaseAddr() only if the working version is present, i.e.
  32.             not the first version of 32-bit QuickDraw.
  33. 4/1/93    dgp    Changed test for valid GetPixBaseAddr() to require version gestalt32BitQD13 
  34.             or later, as specified by New Tech Note "Color QuickDraw Q&As".
  35. 4/21/93    dgp    Now always return a 32-bit address, even under System 6.
  36.             Wrote GetPixBaseAddr32() which is a more-dependable substitute for
  37.             Apple's GetPixBaseAddr, and accepts bit/pixmaps to boot.
  38. 4/27/93    dgp    Josh discovered a bug; RectToAddress was finding the device that
  39.             held the upper left corner of the rect, BEFORE clipping by the pixmap,
  40.             which resulted in a null rect when the wrong device was later clipped
  41.             by the pixmap. Now I do the right thing, which is to find the device
  42.             that holds the upper left corner of the pixmap. Also, I now always
  43.             return the clipping to the user, which wasn't being done consistently,
  44.             e.g. never for bitmaps.
  45. */
  46. #include "VideoToolbox.h"
  47.     
  48. Ptr GetPixBaseAddr32(PixMap **pm)
  49. // Returns the 32-bit address of the pixels/bits in a pix/bitmap.
  50. {
  51.     Ptr address;
  52.     long qD;
  53.     GDHandle device;
  54.     short i;
  55.     
  56.     // Apple's GetPixBaseAddr() did not work in the early versions of 32-bit QuickDraw
  57.     Gestalt(gestaltQuickdrawVersion,&qD);
  58.     if(qD>=gestalt32BitQD13 && ((**pm).rowBytes&0x8000))
  59.         return GetPixBaseAddr(pm);    // Guaranteed to be 32-bit.
  60.     address=(**pm).baseAddr;
  61.     if(qD>=gestalt8BitQD){
  62.         // If it's the base address of a screen then it's a 32-bit address.
  63.         for(i=0;;i++){
  64.             device=GetScreenDevice(i);
  65.             if(device==NULL)break;
  66.             if(address==(**(**device).gdPMap).baseAddr)return address;
  67.         }
  68.     }
  69.     // Otherwise it must be in RAM and we should strip it, 
  70.     // since we may be in 24-bit mode.
  71.     address=StripAddress(address);
  72.     return address;
  73. }
  74.  
  75. unsigned char *RectToAddress(PixMap *pixMapPtr,Rect *rectPtr,short *rowBytesPtr, 
  76.     short *pixelSizePtr,short *bitsOffsetPtr)
  77. /*
  78. *pixMapPtr is the PixMap or BitMap that you're working in.
  79. *rectPtr is the Rect you're interested in, in local coordinates. 
  80.     Will be clipped by pixmap/device bounds.
  81. *rowBytesPtr optionally returns rowBytes.
  82. *pixelSizePtr optionally returns pixelSize.
  83. *bitsOffsetPtr optionally returns positive offset in bits from returned
  84.     byte address to the location specified by upper left corner of rectPtr
  85. */
  86. {
  87.     GDHandle device,mainDevice;
  88.     Rect rect,smallRect;
  89.     register Ptr address;
  90.     short notEmpty;
  91.     long x0,y0;
  92.     long qD;
  93.     
  94.     if(pixMapPtr==NULL)return NULL;
  95.     Gestalt(gestaltQuickdrawVersion,&qD);
  96.     x0=pixMapPtr->bounds.left;
  97.     y0=pixMapPtr->bounds.top;
  98.     if(qD>=gestalt8BitQD)mainDevice=GetMainDevice();
  99.     else mainDevice=NULL;
  100.     address=GetPixBaseAddr32(&pixMapPtr);
  101.     if(address==NULL)return NULL;
  102.     if(mainDevice != NULL && address == (*(*mainDevice)->gdPMap)->baseAddr){
  103.         /* When there are multiple screens, all windows refer to main device PixMap */
  104.         /* so we have to figure out which is the actual device. */
  105.         rect = *rectPtr;
  106.         OffsetRect(&rect,-x0,-y0);            /* convert to global coordinates */
  107.         #if 0
  108.             // OLD MISTAKE: Find device that displays the upper left pixel of rect
  109.             smallRect = rect;
  110.             smallRect.bottom=smallRect.top+1;
  111.             smallRect.right=smallRect.left+1;
  112.         #else
  113.             // NEW: Find device that displays the upper left pixel of PixMap
  114.             SetRect(&smallRect,-x0,-y0,-x0+1,-y0+1);    // global coordinates
  115.         #endif
  116.         device = GetMaxDevice(&smallRect);
  117.         if(device==NULL)return NULL;
  118.         pixMapPtr = *(*device)->gdPMap;    /* Use the DEVICE'S PixMap */
  119.         address=pixMapPtr->baseAddr;
  120.         notEmpty=SectRect(&rect,&pixMapPtr->bounds,&rect);
  121.         *rectPtr=rect;                    // Clip user's rect too.
  122.         OffsetRect(rectPtr,x0,y0);        // convert that back to local coordinates
  123.                                             // convert ours to device coordinates
  124.         OffsetRect(&rect,-(*device)->gdRect.left,-(*device)->gdRect.top);
  125.     }
  126.     else {
  127.         /* Just clip and convert to global coordinates */
  128.         rect = *rectPtr;
  129.         notEmpty=SectRect(&rect,&pixMapPtr->bounds,&rect);
  130.         *rectPtr=rect;                    // Clip user's rect too.
  131.         OffsetRect(&rect,-x0,-y0);            /* convert to global coordinates */
  132.     }
  133.     address += rect.top*(long)(pixMapPtr->rowBytes & 0x1fff);
  134.     if(pixMapPtr->rowBytes & 0x8000){                    /* Pixmap or Bitmap? */
  135.         // Pixmap
  136.         address += (rect.left*(long)pixMapPtr->pixelSize)/8;
  137.         if(bitsOffsetPtr != NULL) *bitsOffsetPtr=(rect.left*(long)pixMapPtr->pixelSize)%8;
  138.         if(pixelSizePtr != NULL) *pixelSizePtr=pixMapPtr->pixelSize;
  139.     }
  140.     else{
  141.         // Bitmap
  142.         address += rect.left/8;        
  143.         if(bitsOffsetPtr != NULL) *bitsOffsetPtr=rect.left%8;
  144.         if(pixelSizePtr != NULL) *pixelSizePtr=1;
  145.     }
  146.     if(rowBytesPtr != NULL) (*rowBytesPtr)=pixMapPtr->rowBytes & 0x1fff;
  147.     if(!notEmpty)address=NULL;    
  148.     return (unsigned char *) address;
  149. }
  150.