Fix retrieving clipping box after changing wxDC coordinates (GTK)
Member data containing clipping box have to be updated not only when the clipping region is explicitly changed by SetClippingRegion()/DestroyClippingRegion() but also when wxDC coordinates are transformed with SetDeviceOrigin(), SetLogicalOrigin(), SetUserScale(), SetLogicalScale(), SetTransformMatrix() or ResetTransformMatrix(). When any of these functions is called then clipping box data are marked as invalid and updated by recalculating extents of the clipping region in new coordinates at nearest call to GetClippingBox(). Closes #17646.
This commit is contained in:
@@ -113,6 +113,7 @@ wxGTK:
|
|||||||
- Cosmetic fix for empty wxCheckBoxes display (Chuddah).
|
- Cosmetic fix for empty wxCheckBoxes display (Chuddah).
|
||||||
- Fix crashes in wxFileSystemWatcher implementation (David Hart).
|
- Fix crashes in wxFileSystemWatcher implementation (David Hart).
|
||||||
- Fix wxBitmap ctor from XBM for non-square bitmaps.
|
- Fix wxBitmap ctor from XBM for non-square bitmaps.
|
||||||
|
- Fix wxDC::GetClippingBox() for transformed wxDC.
|
||||||
|
|
||||||
wxMSW:
|
wxMSW:
|
||||||
|
|
||||||
|
@@ -71,6 +71,7 @@ public:
|
|||||||
virtual bool DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const wxOVERRIDE;
|
virtual bool DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const wxOVERRIDE;
|
||||||
virtual void DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) wxOVERRIDE;
|
virtual void DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) wxOVERRIDE;
|
||||||
virtual void DoSetDeviceClippingRegion( const wxRegion ®ion ) wxOVERRIDE;
|
virtual void DoSetDeviceClippingRegion( const wxRegion ®ion ) wxOVERRIDE;
|
||||||
|
virtual void DoGetClippingBox(wxCoord *x, wxCoord *y, wxCoord *w, wxCoord *h) const wxOVERRIDE;
|
||||||
|
|
||||||
virtual wxCoord GetCharWidth() const wxOVERRIDE;
|
virtual wxCoord GetCharWidth() const wxOVERRIDE;
|
||||||
virtual wxCoord GetCharHeight() const wxOVERRIDE;
|
virtual wxCoord GetCharHeight() const wxOVERRIDE;
|
||||||
@@ -110,6 +111,7 @@ public:
|
|||||||
bool m_isScreenDC;
|
bool m_isScreenDC;
|
||||||
wxRegion m_currentClippingRegion;
|
wxRegion m_currentClippingRegion;
|
||||||
wxRegion m_paintClippingRegion;
|
wxRegion m_paintClippingRegion;
|
||||||
|
bool m_isClipBoxValid;
|
||||||
|
|
||||||
// PangoContext stuff for GTK 2.0
|
// PangoContext stuff for GTK 2.0
|
||||||
PangoContext *m_context;
|
PangoContext *m_context;
|
||||||
@@ -123,6 +125,9 @@ public:
|
|||||||
|
|
||||||
virtual GdkWindow *GetGDKWindow() const wxOVERRIDE { return m_gdkwindow; }
|
virtual GdkWindow *GetGDKWindow() const wxOVERRIDE { return m_gdkwindow; }
|
||||||
|
|
||||||
|
// Update the internal clip box variables
|
||||||
|
void UpdateClipBox();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawingSetup(GdkGC*& gc, bool& originChanged);
|
void DrawingSetup(GdkGC*& gc, bool& originChanged);
|
||||||
GdkPixmap* MonoToColor(GdkPixmap* monoPixmap, int x, int y, int w, int h) const;
|
GdkPixmap* MonoToColor(GdkPixmap* monoPixmap, int x, int y, int w, int h) const;
|
||||||
|
@@ -269,6 +269,7 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) :
|
|||||||
m_context = NULL;
|
m_context = NULL;
|
||||||
m_layout = NULL;
|
m_layout = NULL;
|
||||||
m_fontdesc = NULL;
|
m_fontdesc = NULL;
|
||||||
|
m_isClipBoxValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
|
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
|
||||||
@@ -284,6 +285,7 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
|
|||||||
m_cmap = NULL;
|
m_cmap = NULL;
|
||||||
m_isScreenDC = false;
|
m_isScreenDC = false;
|
||||||
m_font = window->GetFont();
|
m_font = window->GetFont();
|
||||||
|
m_isClipBoxValid = false;
|
||||||
|
|
||||||
GtkWidget *widget = window->m_wxwindow;
|
GtkWidget *widget = window->m_wxwindow;
|
||||||
m_gdkwindow = window->GTKGetDrawingWindow();
|
m_gdkwindow = window->GTKGetDrawingWindow();
|
||||||
@@ -1865,6 +1867,74 @@ void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) )
|
|||||||
wxFAIL_MSG( wxT("wxWindowDCImpl::SetPalette not implemented") );
|
wxFAIL_MSG( wxT("wxWindowDCImpl::SetPalette not implemented") );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxWindowDCImpl::UpdateClipBox()
|
||||||
|
{
|
||||||
|
int dcWidth, dcHeight;
|
||||||
|
DoGetSize(&dcWidth, &dcHeight);
|
||||||
|
wxRect dcRect(0, 0, dcWidth, dcHeight);
|
||||||
|
|
||||||
|
wxRect r;
|
||||||
|
if ( m_clipping )
|
||||||
|
{
|
||||||
|
if ( !m_currentClippingRegion.IsEmpty() )
|
||||||
|
{
|
||||||
|
r = m_currentClippingRegion.GetBox();
|
||||||
|
// Effective clipping box is an intersection
|
||||||
|
// of current clipping box and DC surface.
|
||||||
|
r.Intersect(dcRect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = wxRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( m_currentClippingRegion.IsEmpty() )
|
||||||
|
{
|
||||||
|
// Clipping box is just a DC surface.
|
||||||
|
r = dcRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( r.IsEmpty() )
|
||||||
|
{
|
||||||
|
m_clipX1 = m_clipY1 = m_clipX2 = m_clipY2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_clipX1 = DeviceToLogicalX(r.GetLeft());
|
||||||
|
m_clipY1 = DeviceToLogicalY(r.GetTop());
|
||||||
|
m_clipX2 = m_clipX1 + DeviceToLogicalXRel(r.GetWidth());
|
||||||
|
m_clipY2 = m_clipY1 + DeviceToLogicalYRel(r.GetHeight());
|
||||||
|
}
|
||||||
|
m_isClipBoxValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxWindowDCImpl::DoGetClippingBox(wxCoord *x, wxCoord *y, wxCoord *w, wxCoord *h) const
|
||||||
|
{
|
||||||
|
wxCHECK_RET( IsOk(), wxS("invalid window dc") );
|
||||||
|
|
||||||
|
// Check if we should try to retrieve the clipping region possibly not set
|
||||||
|
// by our SetClippingRegion() but preset or modified by application: this
|
||||||
|
// can happen when wxDC logical coordinates are transformed with
|
||||||
|
// SetDeviceOrigin(), SetLogicalOrigin(), SetUserScale(), SetLogicalScale().
|
||||||
|
if ( !m_isClipBoxValid )
|
||||||
|
{
|
||||||
|
wxWindowDCImpl *self = wxConstCast(this, wxWindowDCImpl);
|
||||||
|
self->UpdateClipBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( x )
|
||||||
|
*x = m_clipX1;
|
||||||
|
if ( y )
|
||||||
|
*y = m_clipY1;
|
||||||
|
if ( w )
|
||||||
|
*w = m_clipX2 - m_clipX1;
|
||||||
|
if ( h )
|
||||||
|
*h = m_clipY2 - m_clipY1;
|
||||||
|
}
|
||||||
|
|
||||||
void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
|
void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
|
wxCHECK_RET( IsOk(), wxT("invalid window dc") );
|
||||||
@@ -1915,11 +1985,8 @@ void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion ®ion )
|
|||||||
if (!m_paintClippingRegion.IsNull())
|
if (!m_paintClippingRegion.IsNull())
|
||||||
m_currentClippingRegion.Intersect( m_paintClippingRegion );
|
m_currentClippingRegion.Intersect( m_paintClippingRegion );
|
||||||
#endif
|
#endif
|
||||||
|
m_clipping = true;
|
||||||
wxCoord xx, yy, ww, hh;
|
UpdateClipBox();
|
||||||
m_currentClippingRegion.GetBox( xx, yy, ww, hh );
|
|
||||||
wxGTKDCImpl::DoSetClippingRegion(DeviceToLogicalX(xx), DeviceToLogicalY(yy),
|
|
||||||
DeviceToLogicalXRel(ww), DeviceToLogicalYRel(hh));
|
|
||||||
|
|
||||||
GdkRegion* gdkRegion = m_currentClippingRegion.GetRegion();
|
GdkRegion* gdkRegion = m_currentClippingRegion.GetRegion();
|
||||||
gdk_gc_set_clip_region(m_penGC, gdkRegion);
|
gdk_gc_set_clip_region(m_penGC, gdkRegion);
|
||||||
@@ -1951,6 +2018,8 @@ void wxWindowDCImpl::DestroyClippingRegion()
|
|||||||
gdk_gc_set_clip_region(m_brushGC, gdkRegion);
|
gdk_gc_set_clip_region(m_brushGC, gdkRegion);
|
||||||
gdk_gc_set_clip_region(m_textGC, gdkRegion);
|
gdk_gc_set_clip_region(m_textGC, gdkRegion);
|
||||||
gdk_gc_set_clip_region(m_bgGC, gdkRegion);
|
gdk_gc_set_clip_region(m_bgGC, gdkRegion);
|
||||||
|
|
||||||
|
m_isClipBoxValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxWindowDCImpl::Destroy()
|
void wxWindowDCImpl::Destroy()
|
||||||
@@ -2000,6 +2069,8 @@ void wxWindowDCImpl::ComputeScaleAndOrigin()
|
|||||||
m_pen = wxNullPen;
|
m_pen = wxNullPen;
|
||||||
SetPen( pen );
|
SetPen( pen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isClipBoxValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolution in pixels per logical inch
|
// Resolution in pixels per logical inch
|
||||||
|
Reference in New Issue
Block a user