Merge branch 'qt-region-fixes'
wxQt region-related fixes: fix bugs in clipping region handling and add wxRegion::DoCombine(). See https://github.com/wxWidgets/wxWidgets/pull/1162
This commit is contained in:
@@ -116,7 +116,7 @@ protected:
|
|||||||
QPainter *m_qtPainter;
|
QPainter *m_qtPainter;
|
||||||
QPixmap *m_qtPixmap;
|
QPixmap *m_qtPixmap;
|
||||||
|
|
||||||
wxRegion *m_clippingRegion;
|
wxRegion m_clippingRegion;
|
||||||
private:
|
private:
|
||||||
enum wxQtRasterColourOp
|
enum wxQtRasterColourOp
|
||||||
{
|
{
|
||||||
|
@@ -48,6 +48,8 @@ protected:
|
|||||||
virtual bool DoSubtract(const wxRegion& region);
|
virtual bool DoSubtract(const wxRegion& region);
|
||||||
virtual bool DoXor(const wxRegion& region);
|
virtual bool DoXor(const wxRegion& region);
|
||||||
|
|
||||||
|
virtual bool DoCombine(const wxRegion& rgn, wxRegionOp op);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxRegion);
|
wxDECLARE_DYNAMIC_CLASS(wxRegion);
|
||||||
};
|
};
|
||||||
|
@@ -48,7 +48,6 @@ wxIMPLEMENT_CLASS(wxQtDCImpl,wxDCImpl);
|
|||||||
wxQtDCImpl::wxQtDCImpl( wxDC *owner )
|
wxQtDCImpl::wxQtDCImpl( wxDC *owner )
|
||||||
: wxDCImpl( owner )
|
: wxDCImpl( owner )
|
||||||
{
|
{
|
||||||
m_clippingRegion = new wxRegion;
|
|
||||||
m_qtPixmap = NULL;
|
m_qtPixmap = NULL;
|
||||||
m_rasterColourOp = wxQtNONE;
|
m_rasterColourOp = wxQtNONE;
|
||||||
m_qtPenColor = new QColor;
|
m_qtPenColor = new QColor;
|
||||||
@@ -67,7 +66,6 @@ wxQtDCImpl::~wxQtDCImpl()
|
|||||||
delete m_qtPainter;
|
delete m_qtPainter;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete m_clippingRegion;
|
|
||||||
delete m_qtPenColor;
|
delete m_qtPenColor;
|
||||||
delete m_qtBrushColor;
|
delete m_qtBrushColor;
|
||||||
}
|
}
|
||||||
@@ -87,7 +85,7 @@ void wxQtDCImpl::QtPreparePainter( )
|
|||||||
|
|
||||||
if (m_clipping)
|
if (m_clipping)
|
||||||
{
|
{
|
||||||
wxRegionIterator ri(*m_clippingRegion);
|
wxRegionIterator ri(m_clippingRegion);
|
||||||
bool append = false;
|
bool append = false;
|
||||||
while (ri.HaveRects())
|
while (ri.HaveRects())
|
||||||
{
|
{
|
||||||
@@ -416,6 +414,17 @@ void wxQtDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if ( width < 0 )
|
||||||
|
{
|
||||||
|
width = -width;
|
||||||
|
x -= width - 1;
|
||||||
|
}
|
||||||
|
if ( height < 0 )
|
||||||
|
{
|
||||||
|
height = -height;
|
||||||
|
y -= height - 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_qtPainter->isActive())
|
if (m_qtPainter->isActive())
|
||||||
{
|
{
|
||||||
// Set QPainter clipping (intersection if not the first one)
|
// Set QPainter clipping (intersection if not the first one)
|
||||||
@@ -426,17 +435,21 @@ void wxQtDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y,
|
|||||||
// Set internal state for getters
|
// Set internal state for getters
|
||||||
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
||||||
* keep the region manually, which should be faster */
|
* keep the region manually, which should be faster */
|
||||||
if ( m_clipping )
|
if ( !m_clipping || m_clippingRegion.IsEmpty() )
|
||||||
m_clippingRegion->Union( wxRect( x, y, width, height ) );
|
{
|
||||||
else
|
int dcwidth, dcheight;
|
||||||
m_clippingRegion->Intersect( wxRect( x, y, width, height ) );
|
DoGetSize(&dcwidth, &dcheight);
|
||||||
|
|
||||||
wxRect clipRect = m_clippingRegion->GetBox();
|
m_clippingRegion = wxRegion(0, 0, dcwidth, dcheight);
|
||||||
|
}
|
||||||
|
m_clippingRegion.Intersect( wxRect(x, y, width, height) );
|
||||||
|
|
||||||
|
wxRect clipRect = m_clippingRegion.GetBox();
|
||||||
|
|
||||||
m_clipX1 = clipRect.GetLeft();
|
m_clipX1 = clipRect.GetLeft();
|
||||||
m_clipX2 = clipRect.GetRight();
|
m_clipX2 = clipRect.GetRight() + 1;
|
||||||
m_clipY1 = clipRect.GetTop();
|
m_clipY1 = clipRect.GetTop();
|
||||||
m_clipY2 = clipRect.GetBottom();
|
m_clipY2 = clipRect.GetBottom() + 1;
|
||||||
m_clipping = true;
|
m_clipping = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -465,16 +478,16 @@ void wxQtDCImpl::DoSetDeviceClippingRegion(const wxRegion& region)
|
|||||||
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
/* Note: Qt states that QPainter::clipRegion() may be slow, so we
|
||||||
* keep the region manually, which should be faster */
|
* keep the region manually, which should be faster */
|
||||||
if ( m_clipping )
|
if ( m_clipping )
|
||||||
m_clippingRegion->Union( region );
|
m_clippingRegion.Union( region );
|
||||||
else
|
else
|
||||||
m_clippingRegion->Intersect( region );
|
m_clippingRegion.Intersect( region );
|
||||||
|
|
||||||
wxRect clipRect = m_clippingRegion->GetBox();
|
wxRect clipRect = m_clippingRegion.GetBox();
|
||||||
|
|
||||||
m_clipX1 = clipRect.GetLeft();
|
m_clipX1 = clipRect.GetLeft();
|
||||||
m_clipX2 = clipRect.GetRight();
|
m_clipX2 = clipRect.GetRight() + 1;
|
||||||
m_clipY1 = clipRect.GetTop();
|
m_clipY1 = clipRect.GetTop();
|
||||||
m_clipY2 = clipRect.GetBottom();
|
m_clipY2 = clipRect.GetBottom() + 1;
|
||||||
m_clipping = true;
|
m_clipping = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -482,7 +495,7 @@ void wxQtDCImpl::DoSetDeviceClippingRegion(const wxRegion& region)
|
|||||||
void wxQtDCImpl::DestroyClippingRegion()
|
void wxQtDCImpl::DestroyClippingRegion()
|
||||||
{
|
{
|
||||||
wxDCImpl::DestroyClippingRegion();
|
wxDCImpl::DestroyClippingRegion();
|
||||||
m_clippingRegion->Clear();
|
m_clippingRegion.Clear();
|
||||||
|
|
||||||
if (m_qtPainter->isActive())
|
if (m_qtPainter->isActive())
|
||||||
m_qtPainter->setClipping( false );
|
m_qtPainter->setClipping( false );
|
||||||
|
@@ -20,35 +20,35 @@
|
|||||||
|
|
||||||
class wxRegionRefData: public wxGDIRefData
|
class wxRegionRefData: public wxGDIRefData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
wxRegionRefData()
|
wxRegionRefData()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegionRefData( QRect r ) : m_qtRegion( r )
|
wxRegionRefData( QRect r ) : m_qtRegion( r )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegionRefData( QBitmap b ) : m_qtRegion ( b )
|
wxRegionRefData( QBitmap b ) : m_qtRegion ( b )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegionRefData( QPolygon p, Qt::FillRule fr ) : m_qtRegion( p, fr )
|
wxRegionRefData( QPolygon p, Qt::FillRule fr ) : m_qtRegion( p, fr )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegionRefData( const wxRegionRefData& data )
|
wxRegionRefData( const wxRegionRefData& data )
|
||||||
: wxGDIRefData()
|
: wxGDIRefData()
|
||||||
{
|
{
|
||||||
m_qtRegion = data.m_qtRegion;
|
m_qtRegion = data.m_qtRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const wxRegionRefData& data) const
|
bool operator == (const wxRegionRefData& data) const
|
||||||
{
|
{
|
||||||
return m_qtRegion == data.m_qtRegion;
|
return m_qtRegion == data.m_qtRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegion m_qtRegion;
|
QRegion m_qtRegion;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define M_REGIONDATA ((wxRegionRefData *)m_refData)->m_qtRegion
|
#define M_REGIONDATA ((wxRegionRefData *)m_refData)->m_qtRegion
|
||||||
@@ -57,7 +57,7 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject);
|
|||||||
|
|
||||||
wxRegion::wxRegion()
|
wxRegion::wxRegion()
|
||||||
{
|
{
|
||||||
m_refData = new wxRegionRefData();
|
m_refData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
|
wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
|
||||||
@@ -113,16 +113,16 @@ wxRegion::wxRegion(const wxBitmap& bmp, const wxColour& transp, int tolerance)
|
|||||||
memset(raw.get(), 0, bmp.GetWidth()*bmp.GetHeight());
|
memset(raw.get(), 0, bmp.GetWidth()*bmp.GetHeight());
|
||||||
|
|
||||||
QImage img(bmp.GetHandle()->toImage());
|
QImage img(bmp.GetHandle()->toImage());
|
||||||
int r = transp.Red(), g = transp.Green(), b = transp.Blue();
|
const int r = transp.Red(), g = transp.Green(), b = transp.Blue();
|
||||||
for(int y=0; y<img.height(); y++)
|
for ( int y = 0; y < img.height(); y++ )
|
||||||
{
|
{
|
||||||
for(int x=0; x<img.width(); x++)
|
for ( int x = 0; x < img.width(); x++ )
|
||||||
{
|
{
|
||||||
QColor c = img.pixel(x, y);
|
const QColor c = img.pixel(x, y);
|
||||||
if ( abs(c.red() - r ) > tolerance ||
|
if ( abs(c.red() - r ) > tolerance ||
|
||||||
abs(c.green() - g) > tolerance ||
|
abs(c.green() - g) > tolerance ||
|
||||||
abs(c.blue() - b) > tolerance) {
|
abs(c.blue() - b) > tolerance) {
|
||||||
int ind = y*img.width()+x;
|
const int ind = y*img.width()+x;
|
||||||
raw[ind>>3] |= 1<<(ind&7);
|
raw[ind>>3] |= 1<<(ind&7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,14 +133,20 @@ wxRegion::wxRegion(const wxBitmap& bmp, const wxColour& transp, int tolerance)
|
|||||||
|
|
||||||
bool wxRegion::IsEmpty() const
|
bool wxRegion::IsEmpty() const
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), true, "Invalid region" );
|
if ( IsNull() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
wxCHECK_MSG(IsOk(), true, "Invalid region" );
|
||||||
|
|
||||||
return M_REGIONDATA.isEmpty();
|
return M_REGIONDATA.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxRegion::Clear()
|
void wxRegion::Clear()
|
||||||
{
|
{
|
||||||
wxCHECK_RET( IsOk(), "Invalid region" );
|
if ( IsNull() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxCHECK_RET(IsOk(), "Invalid region" );
|
||||||
|
|
||||||
AllocExclusive();
|
AllocExclusive();
|
||||||
M_REGIONDATA = QRegion();
|
M_REGIONDATA = QRegion();
|
||||||
@@ -148,6 +154,7 @@ void wxRegion::Clear()
|
|||||||
|
|
||||||
void wxRegion::QtSetRegion(QRegion region)
|
void wxRegion::QtSetRegion(QRegion region)
|
||||||
{
|
{
|
||||||
|
AllocExclusive();
|
||||||
M_REGIONDATA = region;
|
M_REGIONDATA = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +178,18 @@ bool wxRegion::DoIsEqual(const wxRegion& region) const
|
|||||||
|
|
||||||
bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
|
bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
|
||||||
{
|
{
|
||||||
|
if ( m_refData == NULL )
|
||||||
|
{
|
||||||
|
x =
|
||||||
|
y =
|
||||||
|
w =
|
||||||
|
h = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
||||||
|
|
||||||
QRect bounding = M_REGIONDATA.boundingRect();
|
const QRect bounding = M_REGIONDATA.boundingRect();
|
||||||
x = bounding.x();
|
x = bounding.x();
|
||||||
y = bounding.y();
|
y = bounding.y();
|
||||||
w = bounding.width();
|
w = bounding.width();
|
||||||
@@ -204,47 +220,98 @@ bool wxRegion::DoOffset(wxCoord x, wxCoord y)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRegion::DoUnionWithRect(const wxRect& rect)
|
// combine another region with this one
|
||||||
|
bool wxRegion::DoCombine(const wxRegion& region, wxRegionOp op)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
// we can't use the API functions if we don't have a valid region
|
||||||
|
if ( !m_refData )
|
||||||
|
{
|
||||||
|
// combining with an empty/invalid region works differently depending
|
||||||
|
// on the operation
|
||||||
|
switch ( op )
|
||||||
|
{
|
||||||
|
case wxRGN_COPY:
|
||||||
|
case wxRGN_OR:
|
||||||
|
case wxRGN_XOR:
|
||||||
|
*this = region;
|
||||||
|
break;
|
||||||
|
|
||||||
M_REGIONDATA = M_REGIONDATA.united( wxQtConvertRect( rect ) );
|
default:
|
||||||
|
wxFAIL_MSG(wxT("unknown region operation"));
|
||||||
|
wxFALLTHROUGH;
|
||||||
|
|
||||||
|
case wxRGN_AND:
|
||||||
|
case wxRGN_DIFF:
|
||||||
|
// leave empty/invalid
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // we have a valid region
|
||||||
|
{
|
||||||
|
AllocExclusive();
|
||||||
|
|
||||||
|
switch ( op )
|
||||||
|
{
|
||||||
|
case wxRGN_AND:
|
||||||
|
M_REGIONDATA = M_REGIONDATA.intersected(region.GetHandle());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxRGN_OR:
|
||||||
|
M_REGIONDATA = M_REGIONDATA.united(region.GetHandle());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxRGN_XOR:
|
||||||
|
M_REGIONDATA = M_REGIONDATA.xored(region.GetHandle());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxRGN_DIFF:
|
||||||
|
M_REGIONDATA = M_REGIONDATA.subtracted(region.GetHandle());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG(wxT("unknown region operation"));
|
||||||
|
wxFALLTHROUGH;
|
||||||
|
|
||||||
|
case wxRGN_COPY:
|
||||||
|
M_REGIONDATA = QRegion(region.GetHandle());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRegion::DoUnionWithRegion(const wxRegion& region)
|
bool wxRegion::DoUnionWithRegion(const wxRegion& region)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
return DoCombine(region, wxRGN_OR);
|
||||||
wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" );
|
|
||||||
|
|
||||||
M_REGIONDATA = M_REGIONDATA.united( region.GetHandle() );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRegion::DoIntersect(const wxRegion& region)
|
bool wxRegion::DoIntersect(const wxRegion& region)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
return DoCombine(region, wxRGN_AND);
|
||||||
wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" );
|
|
||||||
|
|
||||||
M_REGIONDATA = M_REGIONDATA.intersected( region.GetHandle() );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRegion::DoSubtract(const wxRegion& region)
|
bool wxRegion::DoSubtract(const wxRegion& region)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
return DoCombine(region, wxRGN_DIFF);
|
||||||
wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" );
|
|
||||||
|
|
||||||
M_REGIONDATA = M_REGIONDATA.subtracted( region.GetHandle() );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRegion::DoXor(const wxRegion& region)
|
bool wxRegion::DoXor(const wxRegion& region)
|
||||||
{
|
{
|
||||||
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
return DoCombine(region, wxRGN_XOR);
|
||||||
wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" );
|
}
|
||||||
|
|
||||||
M_REGIONDATA = M_REGIONDATA.xored( region.GetHandle() );
|
bool wxRegion::DoUnionWithRect(const wxRect& rect)
|
||||||
|
{
|
||||||
|
if ( m_refData == NULL )
|
||||||
|
{
|
||||||
|
m_refData = new wxRegionRefData(wxQtConvertRect(rect));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_MSG( IsOk(), false, "Invalid region" );
|
||||||
|
|
||||||
|
AllocExclusive();
|
||||||
|
M_REGIONDATA = M_REGIONDATA.united( wxQtConvertRect( rect ) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,14 +346,12 @@ wxRegionIterator::wxRegionIterator(const wxRegionIterator& ri)
|
|||||||
|
|
||||||
wxRegionIterator::~wxRegionIterator()
|
wxRegionIterator::~wxRegionIterator()
|
||||||
{
|
{
|
||||||
if ( m_qtRects != NULL )
|
delete m_qtRects;
|
||||||
delete m_qtRects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
|
wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
|
||||||
{
|
{
|
||||||
if ( m_qtRects != NULL )
|
delete m_qtRects;
|
||||||
delete m_qtRects;
|
|
||||||
|
|
||||||
m_qtRects = new QVector< QRect >( *ri.m_qtRects );
|
m_qtRects = new QVector< QRect >( *ri.m_qtRects );
|
||||||
m_pos = ri.m_pos;
|
m_pos = ri.m_pos;
|
||||||
@@ -300,8 +365,7 @@ void wxRegionIterator::Reset()
|
|||||||
|
|
||||||
void wxRegionIterator::Reset(const wxRegion& region)
|
void wxRegionIterator::Reset(const wxRegion& region)
|
||||||
{
|
{
|
||||||
if ( m_qtRects != NULL )
|
delete m_qtRects;
|
||||||
delete m_qtRects;
|
|
||||||
|
|
||||||
m_qtRects = new QVector< QRect >( region.GetHandle().rects() );
|
m_qtRects = new QVector< QRect >( region.GetHandle().rects() );
|
||||||
m_pos = 0;
|
m_pos = 0;
|
||||||
|
Reference in New Issue
Block a user