/////////////////////////////////////////////////////////////////////////////
-// 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)
// wxRegion
//-----------------------------------------------------------------------------
-/*!
- * Create an empty region.
- */
-wxRegion::wxRegion()
-{
- m_refData = new wxRegionRefData();
-}
-
wxRegion::wxRegion(WXHRGN hRegion )
{
wxCFRef< HIShapeRef > shape( (HIShapeRef) hRegion );
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)
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 fillStyle)
{
- wxUnusedVar(n);
- wxUnusedVar(points);
-
-#ifndef __LP64__
-
- // TODO : any APIs ?
- // 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
-
- GWorldPtr gWorld = NULL;
- GWorldPtr oldWorld;
- GDHandle oldGDHandle;
- OSStatus err;
- Rect destRect = { 0, 0, 1, 1 };
-
- ::GetGWorld( &oldWorld, &oldGDHandle );
- err = ::NewGWorld( &gWorld, 32, &destRect, NULL, NULL, 0 );
- if ( err == noErr )
- {
- ::SetGWorld( gWorld, GetGDevice() );
-
- OpenRgn();
-
- wxCoord x1, x2 , y1 , y2 ;
- x2 = x1 = points[0].x ;
- y2 = y1 = points[0].y ;
-
- ::MoveTo( x1, y1 );
- for (size_t i = 1; i < n; i++)
- {
- x2 = points[i].x ;
- y2 = points[i].y ;
- ::LineTo( x2, y2 );
- }
-
- // close the polyline if necessary
- if ( x1 != x2 || y1 != y2 )
- ::LineTo( x1, y1 ) ;
-
- RgnHandle tempRgn = NewRgn();
- CloseRgn( tempRgn ) ;
+ // Set the region to a polygon shape generically using a bitmap with the
+ // polygon drawn on it.
- ::SetGWorld( oldWorld, oldGDHandle );
- wxCFRef<HIShapeRef> tempShape( HIShapeCreateWithQDRgn(tempRgn ) );
- m_refData = new wxRegionRefData(tempShape);
- DisposeRgn( tempRgn );
- }
- else
- {
- m_refData = new wxRegionRefData;
- }
-#else
- wxFAIL_MSG( "not implemented" );
- m_refData = NULL;
-#endif
+ m_refData = new wxRegionRefData();
+
+ wxCoord mx = 0;
+ wxCoord my = 0;
+ wxPoint p;
+ size_t idx;
+
+ // Find the max size needed to draw the polygon
+ for (idx=0; idx<n; idx++)
+ {
+ wxPoint pt = points[idx];
+ if (pt.x > mx)
+ mx = pt.x;
+ if (pt.y > my)
+ my = pt.y;
+ }
+
+ // Make the bitmap
+ wxBitmap bmp(mx, my);
+ wxMemoryDC dc(bmp);
+ dc.SetBackground(*wxBLACK_BRUSH);
+ dc.Clear();
+ dc.SetPen(*wxWHITE_PEN);
+ dc.SetBrush(*wxWHITE_BRUSH);
+ dc.DrawPolygon(n, (wxPoint*)points, 0, 0, fillStyle);
+ dc.SelectObject(wxNullBitmap);
+ bmp.SetMask(new wxMask(bmp, *wxBLACK));
+
+ // Use it to set this region
+ Union(bmp);
}
wxRegion::~wxRegion()
// 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 ;
}
+bool wxRegion::DoUnionWithRect(const wxRect& rect)
+{
+ if ( !m_refData )
+ {
+ m_refData = new wxRegionRefData(rect.x , rect.y , rect.width , rect.height);
+ return true;
+ }
+
+ AllocExclusive();
+
+ CGRect r = CGRectMake(rect.x , rect.y , rect.width , rect.height);
+ HIShapeUnionWithRect(M_REGION , &r);
+
+ return true;
+}
//! 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)
- {
- m_refData = new wxRegionRefData();
- }
- else if (m_refData->GetRefCount() > 1)
+ // 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 )
{
- 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:
//# 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);
- return false;
+ if ( !r.IsEmpty() )
+ return false;
+
+ wxRegion r2(region);
+ r2.Subtract(*this);
+
+ return r2.IsEmpty();
}
// Outer bounds of region
return true ;
}
-const WXHRGN wxRegion::GetWXHRGN() const
+WXHRGN wxRegion::GetWXHRGN() const
{
+ if ( !m_refData )
+ return NULL;
+
return M_REGION ;
}
if (!m_refData)
return wxOutRegion;
- CGPoint p = { y , x } ;
+ CGPoint p = CGPointMake( x, y ) ;
if (HIShapeContainsPoint( M_REGION , &p ) )
return wxInRegion;
wxRegionIterator::~wxRegionIterator()
{
- if (m_rects)
- {
- delete [] m_rects;
- m_rects = NULL;
- }
+ wxDELETEA(m_rects);
}
wxRegionIterator::wxRegionIterator(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))
{
* Reset iterator for a new /e region.
*/
-#ifndef __LP64__
-OSStatus wxMacRegionToRectsCounterCallback(
- UInt16 message, RgnHandle WXUNUSED(region), const Rect *WXUNUSED(rect), void *data )
+class RegionToRectsCallbackData
+{
+public :
+ wxRect* m_rects ;
+ long m_current ;
+};
+
+OSStatus wxOSXRegionToRectsCounterCallback(
+ int message, HIShapeRef WXUNUSED(region), const CGRect *WXUNUSED(rect), void *data )
{
long *m_numRects = (long*) data ;
- if ( message == kQDRegionToRectsMsgInit )
+ if ( message == kHIShapeEnumerateInit )
{
(*m_numRects) = 0 ;
}
- else if (message == kQDRegionToRectsMsgParse)
+ else if (message == kHIShapeEnumerateRect)
{
(*m_numRects) += 1 ;
}
return noErr;
}
-class RegionToRectsCallbackData
+OSStatus wxOSXRegionToRectsSetterCallback(
+ int message, HIShapeRef WXUNUSED(region), const CGRect *rect, void *data )
{
-public :
- wxRect* m_rects ;
- long m_current ;
-};
-
-OSStatus wxMacRegionToRectsSetterCallback(
- UInt16 message, RgnHandle WXUNUSED(region), const Rect *rect, void *data )
-{
- if (message == kQDRegionToRectsMsgParse)
+ if (message == kHIShapeEnumerateRect)
{
RegionToRectsCallbackData *cb = (RegionToRectsCallbackData*) data ;
- cb->m_rects[cb->m_current++] = wxRect( rect->left , rect->top , rect->right - rect->left , rect->bottom - rect->top ) ;
+ 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)
{
m_current = 0;
m_region = region;
- if (m_rects)
- {
- delete [] m_rects;
- m_rects = NULL;
- }
+ wxDELETEA(m_rects);
if (m_region.IsEmpty())
{
}
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();
-
-#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);
+#endif
+ OSStatus err = HIShapeEnumerate (OTHER_M_REGION(region), kHIShapeParseFromTopLeft, wxOSXRegionToRectsCounterCallback,
+ (void*)&m_numRects);
if (err == noErr)
{
- 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 );
+ HIShapeEnumerate( OTHER_M_REGION(region), kHIShapeParseFromTopLeft, wxOSXRegionToRectsSetterCallback,
+ (void*)&data );
}
else
{
m_numRects = 0;
}
- DisposeRgn( rgn );
-#endif
}
}
return 0;
}
+
+#endif