home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / RgnMaster 1.0 / Source / Meat 'n Guts / Regions.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-25  |  8.1 KB  |  273 lines  |  [TEXT/KAHL]

  1. /*
  2.  
  3.         Regions.c++
  4.         by Hiep Dam, 3G Software.
  5.         March 1994.
  6.         Last Update April 1994
  7.         Contact: America Online: Starlabs
  8.                  Delphi        : StarLabs
  9.                  Internet      : starlabs@aol.com
  10.                               or starlabs@delphi.com
  11.  
  12.         Contains routines that deal with pictures and regions, and the
  13.         conversion of picts to regions.
  14.  
  15. */
  16.  
  17.  
  18. #include "Regions.h"
  19. #include "QDUtils.h"
  20.  
  21. // -----------------------------------------------------------------------------
  22.  
  23. // Globals, private to this file.
  24. static GrafPtr gOffscreenBuffer = nil;        // Offscreen grafport buffer we'll draw to.
  25. static ResType gRgnType = 'Rgn ';            // Default resource type of our regions.
  26. static Rect gBufferRect = { 0, 0, 0, 0 };    // Rect of the offscreen grafport buffer.
  27.  
  28. // -----------------------------------------------------------------------------
  29.  
  30. // Private routine to this file.
  31. OSErr CreateOffscreenBuffer(Rect *bufferRect);
  32.  
  33. // -----------------------------------------------------------------------------
  34. // -----------------------------------------------------------------------------
  35.  
  36. // Initialize the Region-making routines in this file.
  37. // Allocates an offscreen, black and white grafport buffer (so we can
  38. // draw pictures onto it and then convert it to regions).
  39.  
  40. // IN-> Size of offscreen grafport; preferably size of largest monitor (or
  41. //      largest region you'll be making.)
  42. //      Also specify the rgn resource type (by default its 'Rgn ').
  43. // OUT-> Error code, if any.
  44.  
  45. OSErr InitRegionMaker(Rect *screenSize, ResType rgnType) {
  46.     gRgnType = rgnType;
  47.     gBufferRect = *screenSize;
  48.     return(CreateOffscreenBuffer(screenSize));
  49. } // END InitRegionMaker
  50.  
  51. // -----------------------------------------------------------------------------
  52.  
  53. // DataFromScrap.
  54. // Given a specified resource type, try to fetch that resource lying in the
  55. // clipboard. If none exists, return nil. Allocates memory for that resource.
  56. // IN-> Specify a resource type, such as 'PICT', 'TEXT', etc.
  57. // OUT-> Returns a handle to specified resource type, if it exists. Else
  58. //         returns nil.
  59.  
  60. Handle DataFromScrap(ResType dataType) {
  61.     Handle dataHandle;
  62.     long scrapOffset, rc;
  63.  
  64.     // First, allocate a valid 0-length handle (required by _GetScrap())
  65.     dataHandle = NewHandle(0);
  66.  
  67.     // Now, just get size of data; do this by passing a handle with a size of 0.
  68.     rc = GetScrap(dataHandle, dataType, &scrapOffset );
  69.     if (rc < 0) {
  70.         // Data type not in scrap so... 
  71.         return(nil);
  72.     }
  73.     else {
  74.         // Yeah, our resource type is there. Increase handle size to actual
  75.         // size of our requested resource.
  76.         SetHandleSize(dataHandle, rc);
  77.         // Let's get it.
  78.         rc = GetScrap(dataHandle, dataType, &scrapOffset);
  79.         return(dataHandle);
  80.     }
  81. } // END DataFromScrap
  82.  
  83. // -----------------------------------------------------------------------------
  84.  
  85. // PictureFromScrap.
  86. // Just calls DataFromScrap(), requesting type 'PICT' and type-casting
  87. // the return value to PicHandle.
  88.  
  89. PicHandle PictureFromScrap() {
  90.     return((PicHandle)DataFromScrap('PICT'));
  91. } // END PictureFromScrap
  92.  
  93. // -----------------------------------------------------------------------------
  94.  
  95. // RegionToScrap.
  96. // Puts the specified region onto the clipboard. Region must be valid.
  97. // Returns an error code if anything went wrong (like not enough memory).
  98. // IN-> A valid region, preferably _HLocked.
  99. // OUT-> Error value, 0 if everything went OK.
  100.  
  101. OSErr RegionToScrap(RgnHandle theRgn) {
  102.     long scrapErr;
  103.  
  104.     (void)ZeroScrap();
  105.     scrapErr = PutScrap(GetHandleSize((Handle)theRgn), gRgnType, (Ptr)*theRgn);
  106.     return(scrapErr);
  107. } // END RegionToScrap
  108.  
  109. // -----------------------------------------------------------------------------
  110.  
  111. // ConvertPictureToRegion.
  112. // Here's the actual "engine" or "core" of Regions.c++. Given a handle to
  113. // a valid picture, convert that into a region and return that region. This
  114. // routine will allocate the region itself, and calls _BitMapToRegion() to do
  115. // the actual dirty work.
  116. // How it's done: The picture is drawn onto the black and white offscreen
  117. // grafport buffer, and the trap _BitMapToRegion() is called. Thus the picture
  118. // can be color as well, but is converted to black and white when it's drawn
  119. // to the black and white grafport...
  120. // Note that you must allocate the black and white grafport FIRST before calling
  121. // this routine; do that by calling InitRegionMaker().
  122.  
  123. // IN-> Valid pichandle. Need not be _HLocked by caller.
  124. // OUT-> Valid region. If error occurred, will return nil.
  125.  
  126. RgnHandle ConvertPictureToRegion(PicHandle thePicture, Boolean doOffset) {
  127.     GrafPtr savePort;
  128.     char picState;
  129.     RgnHandle returnRgn = NewRgn();
  130.  
  131.     GetPort(&savePort);
  132.  
  133.     if (gOffscreenBuffer == nil) {
  134.         // Hmm. Caller forgot to allocate offscreen grafport. Exit!
  135.         DisposeRgn(returnRgn);
  136.         return(nil);
  137.     }
  138.  
  139.     SetPort(gOffscreenBuffer);
  140.  
  141.     // Erase any previous pictures drawn onto this grafport, if any
  142.     FillRect(&gOffscreenBuffer->portRect, white);
  143.  
  144.     // Get handle state. (Is it locked? purgeable? etc.)
  145.     picState = HGetState((Handle)thePicture);
  146.     HLockHi((Handle)thePicture);
  147.     DrawPicture(thePicture, &(**thePicture).picFrame);
  148.     // Restore handle state
  149.     HSetState((Handle)thePicture, picState);
  150.  
  151.     // Let's do it!
  152.     if (BitMapToRegion(returnRgn, &gOffscreenBuffer->portBits) != noErr) {
  153.         DisposeRgn(returnRgn);
  154.         SetPort(savePort);
  155.         return(nil);
  156.     }
  157.  
  158.     // Just in case the region isn't located starting at 0, 0, we offset the
  159.     // region so it's topleft corner is at 0, 0.
  160.     if (doOffset)
  161.         OffsetRgn(returnRgn, -(**returnRgn).rgnBBox.left, -(**returnRgn).rgnBBox.top);
  162.  
  163.     SetPort(savePort);
  164.  
  165.     return(returnRgn);
  166. } // END ConvertPictureToRegion
  167.  
  168. // -----------------------------------------------------------------------------
  169.  
  170. // CreateOffscreenBuffer.
  171. // Does the dirty work of creating an offscreen b&w grafport. Actually calls
  172. // NewOffScreenBitMap() to do it, located in QDUtils.c++.
  173.  
  174. OSErr CreateOffscreenBuffer(Rect *bufferRect) {
  175.     GrafPtr savePort;
  176.     short grafErr;
  177.  
  178.     GetPort(&savePort);
  179.  
  180.     if(!NewOffScreenBitMap(&gOffscreenBuffer, bufferRect, 0))
  181.         grafErr = -1;
  182.     else
  183.         grafErr = noErr;
  184.  
  185.     SetPort(savePort);
  186.     return(grafErr);
  187. } // END CreateOffscreenBuffer
  188.  
  189. // -----------------------------------------------------------------------------
  190.  
  191. // SetRegionType and GetRegionType.
  192. // Obvious so I'll not comment them further.
  193.  
  194. void SetRegionType(ResType rgnType) {
  195.     gRgnType = rgnType;
  196. } // END SetRegionType
  197.  
  198. ResType GetRegionType() {
  199.     return(gRgnType);
  200. } // END GetRegionType
  201.  
  202. // -----------------------------------------------------------------------------
  203.  
  204. // PreviewRgn.
  205. // So you want to see what your region's gonna look like, huh? This
  206. // routine creates its own window, centered on the main screen.
  207.  
  208. // IN-> Valid region.
  209. // OUT-> None.
  210.  
  211. void PreviewRgn(RgnHandle theRgn) {
  212.     GrafPtr savePort;
  213.     WindowPtr rgnWindow;
  214.     Rect rgnRect;
  215.     EventRecord dummyEvent;
  216.     
  217.     if (theRgn == nil)
  218.         return;
  219.         
  220.     rgnRect = (**theRgn).rgnBBox;
  221.     
  222.     // Just in case the region isn't flushed topleft at 0, 0, make
  223.     // some adjustments to the window rect...
  224.     if (rgnRect.left != 0) {
  225.         rgnRect.right += rgnRect.left;
  226.         rgnRect.left = 0;
  227.     }
  228.     if (rgnRect.top != 0) {
  229.         rgnRect.bottom += rgnRect.top;
  230.         rgnRect.top = 0;
  231.     }
  232.  
  233.     GetPort(&savePort);
  234.  
  235.     // If the region is really tiny, let's not create a really tiny window.
  236.     // Instead make a small window, but large enough NOT to cause eyestrain.
  237.     // We'll arbitrarily set the region size limit to 20 pixels; any smaller
  238.     // and we create our window, else use a window based on the size of
  239.     // that region.
  240.     if ((rgnRect.right - rgnRect.left < 20) || (rgnRect.bottom - rgnRect.top < 20))
  241.         SetRect(&rgnRect, 0, 0, 24, 24);
  242.  
  243.     // Center the region's rect based on the rect of the offscreen
  244.     // grafport buffer. This call resides in QDUtils.c++
  245.     CenterRect(&rgnRect, &gBufferRect);
  246.     // Make our window.
  247.     rgnWindow = NewWindow(nil, &rgnRect, "\pPreview", false, noGrowDocProc,
  248.         (WindowPtr)-1, false, 0);
  249.  
  250.     SetPort(rgnWindow);
  251.     ShowWindow(rgnWindow);
  252.  
  253.     // Fill it.
  254.     FillRgn(theRgn, black);
  255.  
  256.     // Wait for a mouseDown or a keyDown.
  257.     do {
  258.         if (GetNextEvent(everyEvent, &dummyEvent))
  259.             if (dummyEvent.what == mouseDown || dummyEvent.what == keyDown)
  260.                 break;
  261.     } while (!Button());
  262.     // Flush any residual mouse clicks
  263.     FlushEvents(everyEvent, 0);
  264.  
  265.     // Clean up our act.
  266.     DisposeWindow(rgnWindow);
  267.     SetPort(savePort);
  268. } // END PreviewRgn
  269.  
  270.  
  271.  
  272.  
  273. // END Regions.c++