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 validation errors for numeric wxPropertyGrid properties.
|
||||
- Add wxSYS_CARET_{ON,OFF,TIMEOUT}_MSEC system settings (brawer).
|
||||
- Add wxGraphicsContext::GetClipBox().
|
||||
|
||||
wxGTK:
|
||||
|
||||
|
@@ -544,6 +544,9 @@ public:
|
||||
// resets the clipping to original extent
|
||||
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
|
||||
virtual void * GetNativeContext() = 0;
|
||||
|
||||
|
@@ -510,6 +510,17 @@ public:
|
||||
*/
|
||||
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) ) \
|
||||
m( cairo_matrix_init_identity, \
|
||||
(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__
|
||||
#define wxCAIRO_PLATFORM_METHODS(m) \
|
||||
|
@@ -458,6 +458,9 @@ public:
|
||||
// resets the clipping to original extent
|
||||
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 bool SetAntialiasMode(wxAntialiasMode antialias) wxOVERRIDE;
|
||||
@@ -2371,6 +2374,23 @@ void wxCairoContext::ResetClip()
|
||||
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 )
|
||||
{
|
||||
|
@@ -364,6 +364,9 @@ public:
|
||||
// resets the clipping to original extent
|
||||
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 StrokePath( const wxGraphicsPath& p );
|
||||
@@ -1663,6 +1666,26 @@ void wxGDIPlusContext::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 )
|
||||
{
|
||||
if (m_composition == wxCOMPOSITION_DEST)
|
||||
|
@@ -3230,6 +3230,7 @@ public:
|
||||
void Clip(const wxRegion&) wxOVERRIDE {}
|
||||
void Clip(wxDouble, wxDouble, wxDouble, wxDouble) wxOVERRIDE {}
|
||||
void ResetClip() wxOVERRIDE {}
|
||||
void GetClipBox(wxDouble*, wxDouble*, wxDouble*, wxDouble*) wxOVERRIDE {}
|
||||
void* GetNativeContext() wxOVERRIDE { return NULL; }
|
||||
bool SetAntialiasMode(wxAntialiasMode) wxOVERRIDE { return false; }
|
||||
bool SetInterpolationQuality(wxInterpolationQuality) wxOVERRIDE { return false; }
|
||||
@@ -3327,6 +3328,8 @@ public:
|
||||
|
||||
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.
|
||||
void* GetNativeContext() wxOVERRIDE;
|
||||
|
||||
@@ -3618,6 +3621,102 @@ void wxD2DContext::ResetClip()
|
||||
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()
|
||||
{
|
||||
return &m_renderTargetHolder;
|
||||
|
Reference in New Issue
Block a user