Files
wxWidgets/src/dfb/region.cpp
Vadim Zeitlin 8a16d7370e The Great wxRegion Refactoring:
1. added wxRegionBase class and derive all wxRegions from it
2. also added wxRegionWithCombine for the ports providing Combine() method
   (MSW, OS2 and Mac) to reduce code duplication further
3. made sure region comparison works the same way in all ports (except those
   not implementing it) and added IsEqual() method


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41429 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2006-09-25 11:47:23 +00:00

257 lines
6.3 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/mgl/region.cpp
// Purpose: Region handling for wxWidgets/DFB
// Author: Vaclav Slavik
// Created: 2006-08-08
// RCS-ID: $Id$
// Copyright: (c) 2006 REA Elektronik GmbH
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/region.h"
IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
//-----------------------------------------------------------------------------
// wxRegionRefData
//-----------------------------------------------------------------------------
class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
{
public:
wxRegionRefData() {}
wxRegionRefData(const wxRect& rect) : m_rect(rect) {}
wxRegionRefData(const wxRegionRefData& data) : m_rect(data.m_rect) {}
~wxRegionRefData() {}
// default assignment and comparision operators are OK
wxRect m_rect;
};
#define M_REGION_OF(r) ((wxRegionRefData*)((r).m_refData))
#define M_REGION M_REGION_OF(*this)
//-----------------------------------------------------------------------------
// wxRegion
//-----------------------------------------------------------------------------
wxObjectRefData *wxRegion::CreateRefData() const
{
return new wxRegionRefData;
}
wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
{
return new wxRegionRefData(*(wxRegionRefData *)data);
}
wxRegion::wxRegion()
{
m_refData = NULL;
}
wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
{
m_refData = new wxRegionRefData(wxRect(x, y, w, h));
}
wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
{
m_refData = new wxRegionRefData(wxRect(topLeft, bottomRight));
}
wxRegion::wxRegion(const wxRect& r)
{
m_refData = new wxRegionRefData(r);
}
wxRegion::~wxRegion()
{
// m_refData unrefed in ~wxObject
}
//-----------------------------------------------------------------------------
// Information about the region
//-----------------------------------------------------------------------------
bool wxRegion::DoIsEqual(const wxRegion& region) const
{
return M_REGION->m_rect == M_REGION_OF(region)->m_rect;
}
bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
{
if ( !m_refData )
return false;
const wxRect& r = M_REGION->m_rect;
x = r.GetX();
y = r.GetY();
w = r.GetWidth();
h = r.GetHeight();
return true;
}
bool wxRegion::IsEmpty() const
{
if (!m_refData)
return true;
return M_REGION->m_rect.IsEmpty();
}
//-----------------------------------------------------------------------------
// Modifications
//-----------------------------------------------------------------------------
void wxRegion::Clear()
{
UnRef();
}
bool wxRegion::DoOffset(wxCoord x, wxCoord y)
{
AllocExclusive();
M_REGION->m_rect.Offset(x, y);
return true;
}
bool wxRegion::DoUnionWithRect(const wxRect& rect)
{
AllocExclusive();
if ( M_REGION->m_rect.Contains(rect) )
{
return true;
}
else if ( rect.Contains(M_REGION->m_rect) )
{
M_REGION->m_rect = rect;
return true;
}
else
{
wxFAIL_MSG( _T("only rectangular regions are supported") );
return false;
}
}
bool wxRegion::DoUnionWithRegion(const wxRegion& region)
{
wxCHECK_MSG( region.Ok(), false, _T("invalid region") );
return DoUnionWithRect(M_REGION_OF(region)->m_rect);
}
bool wxRegion::DoIntersect(const wxRegion& region)
{
wxCHECK_MSG( region.Ok(), false, _T("invalid region") );
AllocExclusive();
M_REGION->m_rect.Intersect(M_REGION_OF(region)->m_rect);
return true;
}
bool wxRegion::DoSubtract(const wxRegion& region)
{
wxCHECK_MSG( region.Ok(), false, _T("invalid region") );
wxCHECK_MSG( Ok(), false, _T("invalid region") );
const wxRect& rect = M_REGION_OF(region)->m_rect;
if ( rect.Contains(M_REGION->m_rect) )
{
// subtracted rectangle contains this one, so the result is empty
// rectangle
M_REGION->m_rect = wxRect();
return true;
}
else if ( !M_REGION->m_rect.Intersects(rect) )
{
// the rectangles are disjoint, so substracting has no effect
return true;
}
else
{
wxFAIL_MSG( _T("only rectangular regions implemented") );
return false;
}
}
bool wxRegion::DoXor(const wxRegion& region)
{
wxCHECK_MSG( region.Ok(), false, _T("invalid region") );
wxFAIL_MSG( _T("Xor not implemented") );
return false;
}
//-----------------------------------------------------------------------------
// Tests
//-----------------------------------------------------------------------------
wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
{
wxCHECK_MSG( Ok(), wxOutRegion, _T("invalid region") );
if (M_REGION->m_rect.Contains(x, y))
return wxInRegion;
else
return wxOutRegion;
}
wxRegionContain wxRegion::DoContainsRect(const wxRect& rect) const
{
wxCHECK_MSG( Ok(), wxOutRegion, _T("invalid region") );
// 1) is the rectangle entirely covered by the region?
if (M_REGION->m_rect.Contains(rect))
return wxInRegion;
// 2) is the rectangle completely outside the region?
if (!M_REGION->m_rect.Intersects(rect))
return wxOutRegion;
// 3) neither case happened => it is partially covered:
return wxPartRegion;
}
//-----------------------------------------------------------------------------
// wxRegionIterator
//-----------------------------------------------------------------------------
void wxRegionIterator::Reset(const wxRegion& region)
{
wxRegionRefData *d = M_REGION_OF(region);
m_rect = d ? d->m_rect : wxRect();
}
wxRegionIterator& wxRegionIterator::operator++()
{
// there's only one rectangle in the iterator, so iterating always
// reaches the end:
Reset();
return *this;
}
wxRegionIterator wxRegionIterator::operator++(int)
{
wxRegionIterator tmp = *this;
// there's only one rectangle in the iterator, so iterating always
// reaches the end:
Reset();
return tmp;
}