home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 21 / macformat_21.iso / Shareware / Programación / VideoToolbox / VideoToolboxSources / RectToAddress.c < prev    next >
Text File  |  1994-10-05  |  7KB  |  161 lines

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