]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/region.cpp
Update version to 2.9.4 in version.bkl too and rebake everything.
[wxWidgets.git] / src / osx / carbon / region.cpp
index e645ea9e92f9438b6a274d97640234c9d834bd71..83a2e15e12c369776d1b5ae96ef50c750177f185 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// File:      src/mac/carbon/region.cpp
+// File:      src/osx/carbon/region.cpp
 // Purpose:   Region class
 // Author:    Stefan Csomor
 // Created:   Fri Oct 24 10:46:34 MET 1997
 
 #include "wx/wxprec.h"
 
+#if wxOSX_USE_COCOA_OR_CARBON
+
 #include "wx/region.h"
 
 #ifndef WX_PRECOMP
     #include "wx/gdicmn.h"
+    #include "wx/dcmemory.h"
 #endif
 
-#include "wx/osx/uma.h"
+#include "wx/osx/private.h"
 
 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
@@ -65,14 +68,6 @@ public:
 // wxRegion
 //-----------------------------------------------------------------------------
 
-/*!
- * Create an empty region.
- */
-wxRegion::wxRegion()
-{
-    m_refData = new wxRegionRefData();
-}
-
 wxRegion::wxRegion(WXHRGN hRegion )
 {
     wxCFRef< HIShapeRef > shape( (HIShapeRef) hRegion );
@@ -87,8 +82,8 @@ wxRegion::wxRegion(long x, long y, long w, long h)
 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
 {
     m_refData = new wxRegionRefData(topLeft.x , topLeft.y ,
-                                    topLeft.x - bottomRight.x ,
-                                    topLeft.y - bottomRight.y);
+                                    bottomRight.x - topLeft.x,
+                                    bottomRight.y - topLeft.y);
 }
 
 wxRegion::wxRegion(const wxRect& rect)
@@ -96,14 +91,14 @@ wxRegion::wxRegion(const wxRect& rect)
     m_refData = new wxRegionRefData(rect.x , rect.y , rect.width , rect.height);
 }
 
-wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle))
+wxRegion::wxRegion(size_t n, const wxPoint *points, wxPolygonFillMode WXUNUSED(fillStyle))
 {
     wxUnusedVar(n);
     wxUnusedVar(points);
 
-#ifndef __LP64__
-
-    // TODO : any APIs ?
+#if 0
+    // no non-QD APIs available
+    // TODO : remove ?
     // OS X somehow does not collect the region invisibly as before, so sometimes things
     // get drawn on screen instead of just being combined into a region, therefore we allocate a temp gworld now
 
@@ -139,7 +134,7 @@ wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle))
 
         RgnHandle tempRgn = NewRgn();
         CloseRgn( tempRgn ) ;
+
         ::SetGWorld( oldWorld, oldGDHandle );
         wxCFRef<HIShapeRef> tempShape( HIShapeCreateWithQDRgn(tempRgn ) );
         m_refData = new wxRegionRefData(tempShape);
@@ -167,7 +162,7 @@ wxGDIRefData *wxRegion::CreateGDIRefData() const
 
 wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
 {
-    return new wxRegionRefData(*wx_static_cast(const wxRegionRefData *, data));
+    return new wxRegionRefData(*static_cast<const wxRegionRefData *>(data));
 }
 
 //-----------------------------------------------------------------------------
@@ -183,12 +178,14 @@ void wxRegion::Clear()
 // Move the region
 bool wxRegion::DoOffset(wxCoord x, wxCoord y)
 {
-    wxCHECK_MSG( M_REGION, false, _T("invalid wxRegion") );
+    wxCHECK_MSG( m_refData, false, wxT("invalid wxRegion") );
 
     if ( !x && !y )
         // nothing to do
         return true;
 
+    AllocExclusive();
+
     verify_noerr( HIShapeOffset( M_REGION , x , y ) ) ;
 
     return true ;
@@ -198,20 +195,34 @@ bool wxRegion::DoOffset(wxCoord x, wxCoord y)
 //! Union /e region with this.
 bool wxRegion::DoCombine(const wxRegion& region, wxRegionOp op)
 {
-    wxCHECK_MSG( region.Ok(), false, _T("invalid wxRegion") );
+    wxCHECK_MSG( region.IsOk(), false, wxT("invalid wxRegion") );
 
-    // Don't change shared data
-    if (!m_refData)
+    // Handle the special case of not initialized (e.g. default constructed)
+    // region as we can't use HIShape functions if we don't have any shape.
+    if ( !m_refData )
     {
-        m_refData = new wxRegionRefData();
-    }
-    else if (m_refData->GetRefCount() > 1)
-    {
-        wxRegionRefData* ref = (wxRegionRefData*)m_refData;
-        UnRef();
-        m_refData = new wxRegionRefData(*ref);
+        switch ( op )
+        {
+            case wxRGN_COPY:
+            case wxRGN_OR:
+            case wxRGN_XOR:
+                // These operations make sense with a null region.
+                *this = region;
+                return true;
+
+            case wxRGN_AND:
+            case wxRGN_DIFF:
+                // Those ones don't really make sense so just leave this region
+                // empty/invalid.
+                return false;
+        }
+
+        wxFAIL_MSG( wxT("Unknown region operation") );
+        return false;
     }
 
+    AllocExclusive();
+
     switch (op)
     {
         case wxRGN_AND:
@@ -248,11 +259,21 @@ bool wxRegion::DoCombine(const wxRegion& region, wxRegionOp op)
 //# Information on region
 //-----------------------------------------------------------------------------
 
-bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
+bool wxRegion::DoIsEqual(const wxRegion& region) const
 {
-    wxFAIL_MSG( _T("not implemented") );
+    // There doesn't seem to be any native function for checking the equality
+    // of HIShapes so we compute their differences to determine if they are
+    // equal.
+    wxRegion r(*this);
+    r.Subtract(region);
+
+    if ( !r.IsEmpty() )
+        return false;
 
-    return false;
+    wxRegion r2(region);
+    r2.Subtract(*this);
+
+    return r2.IsEmpty();
 }
 
 // Outer bounds of region
@@ -262,10 +283,10 @@ bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
     {
         CGRect box ;
         HIShapeGetBounds( M_REGION , &box ) ;
-        x = wx_static_cast(int, box.origin.x);
-        y = wx_static_cast(int, box.origin.y);
-        w = wx_static_cast(int, box.size.width);
-        h = wx_static_cast(int, box.size.height);
+        x = static_cast<int>(box.origin.x);
+        y = static_cast<int>(box.origin.y);
+        w = static_cast<int>(box.size.width);
+        h = static_cast<int>(box.size.height);
 
         return true;
     }
@@ -286,7 +307,7 @@ bool wxRegion::IsEmpty() const
         return true ;
 }
 
-const WXHRGN wxRegion::GetWXHRGN() const
+WXHRGN wxRegion::GetWXHRGN() const
 {
     return M_REGION ;
 }
@@ -301,7 +322,7 @@ wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
     if (!m_refData)
         return wxOutRegion;
 
-    CGPoint p = { y , x } ;
+    CGPoint p = { x, y } ;
     if (HIShapeContainsPoint( M_REGION , &p ) )
         return wxInRegion;
 
@@ -344,11 +365,7 @@ wxRegionIterator::wxRegionIterator()
 
 wxRegionIterator::~wxRegionIterator()
 {
-    if (m_rects)
-    {
-        delete [] m_rects;
-        m_rects = NULL;
-    }
+    wxDELETEA(m_rects);
 }
 
 wxRegionIterator::wxRegionIterator(const wxRegionIterator& iterator)
@@ -373,11 +390,7 @@ wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& iterator)
  */
 void wxRegionIterator::SetRects(long numRects, wxRect *rects)
 {
-    if (m_rects)
-    {
-        delete [] m_rects;
-        m_rects = NULL;
-    }
+    wxDELETEA(m_rects);
 
     if (rects && (numRects > 0))
     {
@@ -405,7 +418,15 @@ wxRegionIterator::wxRegionIterator(const wxRegion& region)
  * Reset iterator for a new /e region.
  */
 
-#ifndef __LP64__
+class RegionToRectsCallbackData
+{
+public :
+    wxRect* m_rects ;
+    long m_current ;
+};
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+
 OSStatus wxMacRegionToRectsCounterCallback(
     UInt16 message, RgnHandle WXUNUSED(region), const Rect *WXUNUSED(rect), void *data )
 {
@@ -422,13 +443,6 @@ OSStatus wxMacRegionToRectsCounterCallback(
     return noErr;
 }
 
-class RegionToRectsCallbackData
-{
-public :
-    wxRect* m_rects ;
-    long m_current ;
-};
-
 OSStatus wxMacRegionToRectsSetterCallback(
     UInt16 message, RgnHandle WXUNUSED(region), const Rect *rect, void *data )
 {
@@ -440,6 +454,39 @@ OSStatus wxMacRegionToRectsSetterCallback(
 
     return noErr;
 }
+
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+
+OSStatus wxOSXRegionToRectsCounterCallback(
+    int message, HIShapeRef WXUNUSED(region), const CGRect *WXUNUSED(rect), void *data )
+{
+    long *m_numRects = (long*) data ;
+    if ( message == kHIShapeEnumerateInit )
+    {
+        (*m_numRects) = 0 ;
+    }
+    else if (message == kHIShapeEnumerateRect)
+    {
+        (*m_numRects) += 1 ;
+    }
+
+    return noErr;
+}
+
+OSStatus wxOSXRegionToRectsSetterCallback(
+    int message, HIShapeRef WXUNUSED(region), const CGRect *rect, void *data )
+{
+    if (message == kHIShapeEnumerateRect)
+    {
+        RegionToRectsCallbackData *cb = (RegionToRectsCallbackData*) data ;
+        cb->m_rects[cb->m_current++] = wxRect( rect->origin.x , rect->origin.y , rect->size.width , rect->size.height ) ;
+    }
+
+    return noErr;
+}
+
 #endif
 
 void wxRegionIterator::Reset(const wxRegion& region)
@@ -447,11 +494,7 @@ void wxRegionIterator::Reset(const wxRegion& region)
     m_current = 0;
     m_region = region;
 
-    if (m_rects)
-    {
-        delete [] m_rects;
-        m_rects = NULL;
-    }
+    wxDELETEA(m_rects);
 
     if (m_region.IsEmpty())
     {
@@ -459,35 +502,59 @@ void wxRegionIterator::Reset(const wxRegion& region)
     }
     else
     {
-#ifdef __LP64__
+#if 0
+        // fallback code in case we ever need it again
         // copying this to a path and dissecting the path would be an option
         m_numRects = 1;
         m_rects = new wxRect[m_numRects];
         m_rects[0] = m_region.GetBox();
+#endif
 
-#else
-        RegionToRectsUPP proc = (RegionToRectsUPP) wxMacRegionToRectsCounterCallback;
-
-        OSStatus err = noErr;
-        RgnHandle rgn = NewRgn();
-        HIShapeGetAsQDRgn(OTHER_M_REGION(region), rgn);
-
-        err = QDRegionToRects (rgn, kQDParseRegionFromTopLeft, proc, (void*)&m_numRects);
-        if (err == noErr)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+        if ( HIShapeEnumerate != NULL )
         {
-            proc = (RegionToRectsUPP) wxMacRegionToRectsSetterCallback;
-            m_rects = new wxRect[m_numRects];
-            RegionToRectsCallbackData data ;
-            data.m_rects = m_rects ;
-            data.m_current = 0 ;
-            QDRegionToRects( rgn , kQDParseRegionFromTopLeft, proc, (void*)&data );
+            OSStatus err = HIShapeEnumerate (OTHER_M_REGION(region), kHIShapeParseFromTopLeft, wxOSXRegionToRectsCounterCallback,
+                (void*)&m_numRects);
+            if (err == noErr)
+            {
+                m_rects = new wxRect[m_numRects];
+                RegionToRectsCallbackData data ;
+                data.m_rects = m_rects ;
+                data.m_current = 0 ;
+                HIShapeEnumerate( OTHER_M_REGION(region), kHIShapeParseFromTopLeft, wxOSXRegionToRectsSetterCallback,
+                    (void*)&data );
+            }
+            else
+            {
+                m_numRects = 0;
+            }
         }
         else
+#endif
         {
-            m_numRects = 0;
-        }
-        DisposeRgn( rgn );
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+            OSStatus err = noErr;
+            RgnHandle rgn = NewRgn();
+            HIShapeGetAsQDRgn(OTHER_M_REGION(region), rgn);
+
+            err = QDRegionToRects (rgn, kQDParseRegionFromTopLeft, wxMacRegionToRectsCounterCallback
+                , (void*)&m_numRects);
+            if (err == noErr)
+            {
+                m_rects = new wxRect[m_numRects];
+                RegionToRectsCallbackData data ;
+                data.m_rects = m_rects ;
+                data.m_current = 0 ;
+                QDRegionToRects( rgn , kQDParseRegionFromTopLeft, wxMacRegionToRectsSetterCallback,
+                    (void*)&data );
+            }
+            else
+            {
+                m_numRects = 0;
+            }
+            DisposeRgn( rgn );
 #endif
+        }
     }
 }
 
@@ -548,3 +615,5 @@ long wxRegionIterator::GetH() const
 
     return 0;
 }
+
+#endif