Add wxGraphicsContext::GetClipBox() function
This method returns bounding box of the current clipping region. Added declaration, documentation and implemented for GDI+, Direct2D, Cairo renderers.
This commit is contained in:
@@ -97,6 +97,7 @@ All (GUI):
|
|||||||
- Fix displaying edited value of wxUIntProperty (wxPropertyGrid).
|
- Fix displaying edited value of wxUIntProperty (wxPropertyGrid).
|
||||||
- Fix displaying validation errors for numeric wxPropertyGrid properties.
|
- Fix displaying validation errors for numeric wxPropertyGrid properties.
|
||||||
- Add wxSYS_CARET_{ON,OFF,TIMEOUT}_MSEC system settings (brawer).
|
- Add wxSYS_CARET_{ON,OFF,TIMEOUT}_MSEC system settings (brawer).
|
||||||
|
- Add wxGraphicsContext::GetClipBox().
|
||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
@@ -544,6 +544,9 @@ public:
|
|||||||
// resets the clipping to original extent
|
// resets the clipping to original extent
|
||||||
virtual void ResetClip() = 0;
|
virtual void ResetClip() = 0;
|
||||||
|
|
||||||
|
// returns bounding box of the clipping region
|
||||||
|
virtual void GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) = 0;
|
||||||
|
|
||||||
// returns the native context
|
// returns the native context
|
||||||
virtual void * GetNativeContext() = 0;
|
virtual void * GetNativeContext() = 0;
|
||||||
|
|
||||||
|
@@ -510,6 +510,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h) = 0;
|
virtual void Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns bounding box of the current clipping region.
|
||||||
|
|
||||||
|
@remarks
|
||||||
|
- If clipping region is empty, then empty rectangle is returned
|
||||||
|
(@a x, @a y, @a w, @a h are set to zero).
|
||||||
|
|
||||||
|
@since 3.1.1
|
||||||
|
*/
|
||||||
|
virtual void GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) = 0;
|
||||||
|
|
||||||
/** @}
|
/** @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -172,6 +172,8 @@
|
|||||||
(cairo_t *cr, cairo_surface_t *surface, double x, double y), (cr, surface, x, y) ) \
|
(cairo_t *cr, cairo_surface_t *surface, double x, double y), (cr, surface, x, y) ) \
|
||||||
m( cairo_matrix_init_identity, \
|
m( cairo_matrix_init_identity, \
|
||||||
(cairo_matrix_t *matrix), (matrix) ) \
|
(cairo_matrix_t *matrix), (matrix) ) \
|
||||||
|
m( cairo_clip_extents, \
|
||||||
|
(cairo_t *cr, double *x1, double *y1, double *x2, double *y2), (cr, x1, y1, x2, y2) ) \
|
||||||
|
|
||||||
#ifdef __WXMAC__
|
#ifdef __WXMAC__
|
||||||
#define wxCAIRO_PLATFORM_METHODS(m) \
|
#define wxCAIRO_PLATFORM_METHODS(m) \
|
||||||
|
@@ -458,6 +458,9 @@ public:
|
|||||||
// resets the clipping to original extent
|
// resets the clipping to original extent
|
||||||
virtual void ResetClip() wxOVERRIDE;
|
virtual void ResetClip() wxOVERRIDE;
|
||||||
|
|
||||||
|
// returns bounding box of the clipping region
|
||||||
|
virtual void GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void * GetNativeContext() wxOVERRIDE;
|
virtual void * GetNativeContext() wxOVERRIDE;
|
||||||
|
|
||||||
virtual bool SetAntialiasMode(wxAntialiasMode antialias) wxOVERRIDE;
|
virtual bool SetAntialiasMode(wxAntialiasMode antialias) wxOVERRIDE;
|
||||||
@@ -2371,6 +2374,23 @@ void wxCairoContext::ResetClip()
|
|||||||
cairo_reset_clip(m_context);
|
cairo_reset_clip(m_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxCairoContext::GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h)
|
||||||
|
{
|
||||||
|
double x1, y1, x2, y2;
|
||||||
|
cairo_clip_extents(m_context, &x1, &y1, &x2, &y2);
|
||||||
|
// Check if we have an empty clipping box.
|
||||||
|
if ( x2 - x1 <= DBL_MIN || y2 - y1 <= DBL_MIN )
|
||||||
|
x1 = x2 = y1 = y2 = 0.0;
|
||||||
|
|
||||||
|
if ( x )
|
||||||
|
*x = x1;
|
||||||
|
if ( y )
|
||||||
|
*y = y1;
|
||||||
|
if ( w )
|
||||||
|
*w = x2 - x1;
|
||||||
|
if ( h )
|
||||||
|
*h = y2 - y1;
|
||||||
|
}
|
||||||
|
|
||||||
void wxCairoContext::StrokePath( const wxGraphicsPath& path )
|
void wxCairoContext::StrokePath( const wxGraphicsPath& path )
|
||||||
{
|
{
|
||||||
|
@@ -364,6 +364,9 @@ public:
|
|||||||
// resets the clipping to original extent
|
// resets the clipping to original extent
|
||||||
virtual void ResetClip();
|
virtual void ResetClip();
|
||||||
|
|
||||||
|
// returns bounding box of the clipping region
|
||||||
|
virtual void GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) wxOVERRIDE;
|
||||||
|
|
||||||
virtual void * GetNativeContext();
|
virtual void * GetNativeContext();
|
||||||
|
|
||||||
virtual void StrokePath( const wxGraphicsPath& p );
|
virtual void StrokePath( const wxGraphicsPath& p );
|
||||||
@@ -1663,6 +1666,26 @@ void wxGDIPlusContext::ResetClip()
|
|||||||
m_context->ResetClip();
|
m_context->ResetClip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxGDIPlusContext::GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h)
|
||||||
|
{
|
||||||
|
RectF r;
|
||||||
|
m_context->SetPixelOffsetMode(PixelOffsetModeNone);
|
||||||
|
m_context->GetVisibleClipBounds(&r);
|
||||||
|
m_context->SetPixelOffsetMode(PixelOffsetModeHalf);
|
||||||
|
// Check if we have an empty clipping box.
|
||||||
|
if ( r.Width <= REAL_MIN || r.Height <= REAL_MIN )
|
||||||
|
r.X = r.Y = r.Width = r.Height = 0.0F;
|
||||||
|
|
||||||
|
if ( x )
|
||||||
|
*x = r.X;
|
||||||
|
if ( y )
|
||||||
|
*y = r.Y;
|
||||||
|
if ( w )
|
||||||
|
*w = r.Width;
|
||||||
|
if ( h )
|
||||||
|
*h = r.Height;
|
||||||
|
}
|
||||||
|
|
||||||
void wxGDIPlusContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
|
void wxGDIPlusContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
|
||||||
{
|
{
|
||||||
if (m_composition == wxCOMPOSITION_DEST)
|
if (m_composition == wxCOMPOSITION_DEST)
|
||||||
|
@@ -3230,6 +3230,7 @@ public:
|
|||||||
void Clip(const wxRegion&) wxOVERRIDE {}
|
void Clip(const wxRegion&) wxOVERRIDE {}
|
||||||
void Clip(wxDouble, wxDouble, wxDouble, wxDouble) wxOVERRIDE {}
|
void Clip(wxDouble, wxDouble, wxDouble, wxDouble) wxOVERRIDE {}
|
||||||
void ResetClip() wxOVERRIDE {}
|
void ResetClip() wxOVERRIDE {}
|
||||||
|
void GetClipBox(wxDouble*, wxDouble*, wxDouble*, wxDouble*) wxOVERRIDE {}
|
||||||
void* GetNativeContext() wxOVERRIDE { return NULL; }
|
void* GetNativeContext() wxOVERRIDE { return NULL; }
|
||||||
bool SetAntialiasMode(wxAntialiasMode) wxOVERRIDE { return false; }
|
bool SetAntialiasMode(wxAntialiasMode) wxOVERRIDE { return false; }
|
||||||
bool SetInterpolationQuality(wxInterpolationQuality) wxOVERRIDE { return false; }
|
bool SetInterpolationQuality(wxInterpolationQuality) wxOVERRIDE { return false; }
|
||||||
@@ -3327,6 +3328,8 @@ public:
|
|||||||
|
|
||||||
void ResetClip() wxOVERRIDE;
|
void ResetClip() wxOVERRIDE;
|
||||||
|
|
||||||
|
void GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h) wxOVERRIDE;
|
||||||
|
|
||||||
// The native context used by wxD2DContext is a Direct2D render target.
|
// The native context used by wxD2DContext is a Direct2D render target.
|
||||||
void* GetNativeContext() wxOVERRIDE;
|
void* GetNativeContext() wxOVERRIDE;
|
||||||
|
|
||||||
@@ -3618,6 +3621,102 @@ void wxD2DContext::ResetClip()
|
|||||||
GetRenderTarget()->SetTransform(&currTransform);
|
GetRenderTarget()->SetTransform(&currTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxD2DContext::GetClipBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h)
|
||||||
|
{
|
||||||
|
// To obtain actual clipping box we have to start with rectangle
|
||||||
|
// covering the entire render target and interesect with this rectangle
|
||||||
|
// all clipping layers. Bounding box of the final geometry
|
||||||
|
// (being intersection of all clipping layers) is a clipping box.
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
wxCOMPtr<ID2D1RectangleGeometry> rectGeometry;
|
||||||
|
hr = m_direct2dFactory->CreateRectangleGeometry(
|
||||||
|
D2D1::RectF(0.0F, 0.0F, (FLOAT)m_width, (FLOAT)m_height),
|
||||||
|
&rectGeometry);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
|
wxCOMPtr<ID2D1Geometry> clipGeometry(rectGeometry);
|
||||||
|
|
||||||
|
wxStack<LayerData> layers(m_layers);
|
||||||
|
while( !layers.empty() )
|
||||||
|
{
|
||||||
|
LayerData ld = layers.top();
|
||||||
|
layers.pop();
|
||||||
|
|
||||||
|
if ( ld.type == CLIP_LAYER )
|
||||||
|
{
|
||||||
|
// If current geometry is empty (null region)
|
||||||
|
// or there is no intersection between geometries
|
||||||
|
// then final result is "null" rectangle geometry.
|
||||||
|
FLOAT area;
|
||||||
|
hr = ld.geometry->ComputeArea(ld.transformMatrix, &area);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
D2D1_GEOMETRY_RELATION geomRel;
|
||||||
|
hr = clipGeometry->CompareWithGeometry(ld.geometry, ld.transformMatrix, &geomRel);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
if ( area <= FLT_MIN || geomRel == D2D1_GEOMETRY_RELATION_DISJOINT )
|
||||||
|
{
|
||||||
|
wxCOMPtr<ID2D1RectangleGeometry> nullGeometry;
|
||||||
|
hr = m_direct2dFactory->CreateRectangleGeometry(
|
||||||
|
D2D1::RectF(0.0F, 0.0F, 0.0F, 0.0F), &nullGeometry);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
|
clipGeometry.reset();
|
||||||
|
clipGeometry = nullGeometry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCOMPtr<ID2D1PathGeometry> pathGeometryClip;
|
||||||
|
hr = m_direct2dFactory->CreatePathGeometry(&pathGeometryClip);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
wxCOMPtr<ID2D1GeometrySink> pGeometrySink;
|
||||||
|
hr = pathGeometryClip->Open(&pGeometrySink);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
|
hr = clipGeometry->CombineWithGeometry(ld.geometry, D2D1_COMBINE_MODE_INTERSECT,
|
||||||
|
ld.transformMatrix, pGeometrySink);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
hr = pGeometrySink->Close();
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
pGeometrySink.reset();
|
||||||
|
|
||||||
|
clipGeometry = pathGeometryClip;
|
||||||
|
pathGeometryClip.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final clipping geometry is given in device coordinates
|
||||||
|
// so we need to transform its bounds to logical coordinates.
|
||||||
|
D2D1::Matrix3x2F currTransform;
|
||||||
|
GetRenderTarget()->GetTransform(&currTransform);
|
||||||
|
currTransform.Invert();
|
||||||
|
|
||||||
|
D2D1_RECT_F bounds;
|
||||||
|
// First check if clip region is empty.
|
||||||
|
FLOAT clipArea;
|
||||||
|
hr = clipGeometry->ComputeArea(currTransform, &clipArea);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
if ( clipArea <= FLT_MIN )
|
||||||
|
{
|
||||||
|
bounds.left = bounds.top = bounds.right = bounds.bottom = 0.0F;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If it is not empty then get it bounds.
|
||||||
|
hr = clipGeometry->GetBounds(currTransform, &bounds);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( x )
|
||||||
|
*x = bounds.left;
|
||||||
|
if ( y )
|
||||||
|
*y = bounds.top;
|
||||||
|
if ( w )
|
||||||
|
*w = (double)bounds.right - bounds.left;
|
||||||
|
if ( h )
|
||||||
|
*h = (double)bounds.bottom - bounds.top;
|
||||||
|
}
|
||||||
|
|
||||||
void* wxD2DContext::GetNativeContext()
|
void* wxD2DContext::GetNativeContext()
|
||||||
{
|
{
|
||||||
return &m_renderTargetHolder;
|
return &m_renderTargetHolder;
|
||||||
|
Reference in New Issue
Block a user