From c468dd67cb363dcd9095786a9e1b1fd2a1d0834f Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Tue, 9 Aug 2016 20:47:56 +0200 Subject: [PATCH] Fix setting rectangular clipping region for Direct2D If transformation matrix of wxGraphicsContext with Direct2D renderer is e.g. rotated then rectangular clipping region represented by layer created with ID2D1RenderTarget::PushAxisAlignedClip is invalid because this kind of layers create axis-aligned clipping regions which edges are always horizontal or vertical (not e.g. rotated). To take into account current transformation matrix when clipping region is set there is necessary to represent all clipping regions (even rectangular) by generic layers (ID2D1Layer) created with ID2D1RenderTarget::CreateLayer. Closes #17622 --- src/msw/graphicsd2d.cpp | 87 ++++++++++++----------------------------- 1 file changed, 26 insertions(+), 61 deletions(-) diff --git a/src/msw/graphicsd2d.cpp b/src/msw/graphicsd2d.cpp index 0d382290a9..ed112ef480 100644 --- a/src/msw/graphicsd2d.cpp +++ b/src/msw/graphicsd2d.cpp @@ -3409,10 +3409,11 @@ private: ID2D1RenderTarget* GetRenderTarget() const; + void SetClipLayer(ID2D1Geometry* clipGeometry); + private: enum LayerType { - CLIP_AXIS_ALIGNED_RECT, CLIP_LAYER, OTHER_LAYER }; @@ -3509,16 +3510,9 @@ wxD2DContext::~wxD2DContext() LayerData ld = m_layers.top(); m_layers.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PopAxisAlignedClip(); - } - else - { - GetRenderTarget()->PopLayer(); - ld.layer.reset(); - ld.geometry.reset(); - } + GetRenderTarget()->PopLayer(); + ld.layer.reset(); + ld.geometry.reset(); } HRESULT result = GetRenderTarget()->EndDraw(); @@ -3536,13 +3530,29 @@ void wxD2DContext::Clip(const wxRegion& region) { wxCOMPtr clipGeometry = wxD2DConvertRegionToGeometry(m_direct2dFactory, region); + SetClipLayer(clipGeometry); +} + +void wxD2DContext::Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h) +{ + wxCOMPtr clipGeometry; + HRESULT hr = m_direct2dFactory->CreateRectangleGeometry( + D2D1::RectF(x, y, x + w, y + h), &clipGeometry); + wxCHECK_HRESULT_RET(hr); + + SetClipLayer(clipGeometry); +} + +void wxD2DContext::SetClipLayer(ID2D1Geometry* clipGeometry) +{ wxCOMPtr clipLayer; HRESULT hr = GetRenderTarget()->CreateLayer(&clipLayer); wxCHECK_HRESULT_RET(hr); LayerData ld; ld.type = CLIP_LAYER; - ld.params = D2D1::LayerParameters(D2D1::InfiniteRect(), clipGeometry); + ld.params = D2D1::LayerParameters(D2D1::InfiniteRect(), clipGeometry, + wxD2DConvertAntialiasMode(m_antialias)); ld.layer = clipLayer; ld.geometry = clipGeometry; @@ -3551,19 +3561,6 @@ void wxD2DContext::Clip(const wxRegion& region) m_layers.push(ld); } -void wxD2DContext::Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h) -{ - LayerData ld; - ld.type = CLIP_AXIS_ALIGNED_RECT; - ld.params = D2D1::LayerParameters(D2D1::RectF(x, y, x + w, y + h), - NULL, D2D1_ANTIALIAS_MODE_ALIASED); - - GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds, - D2D1_ANTIALIAS_MODE_ALIASED); - // Store layer parameters. - m_layers.push(ld); -} - void wxD2DContext::ResetClip() { wxStack layersToRestore; @@ -3573,12 +3570,6 @@ void wxD2DContext::ResetClip() LayerData ld = m_layers.top(); m_layers.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PopAxisAlignedClip(); - continue; - } - if ( ld.type == CLIP_LAYER ) { GetRenderTarget()->PopLayer(); @@ -3722,13 +3713,6 @@ void wxD2DContext::EndLayer() LayerData ld = m_layers.top(); m_layers.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PopAxisAlignedClip(); - layersToRestore.push(ld); - continue; - } - if ( ld.type == CLIP_LAYER ) { GetRenderTarget()->PopLayer(); @@ -3754,12 +3738,7 @@ void wxD2DContext::EndLayer() LayerData ld = layersToRestore.top(); layersToRestore.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds, - ld.params.maskAntialiasMode); - } - else if ( ld.type == CLIP_LAYER ) + if ( ld.type == CLIP_LAYER ) { GetRenderTarget()->PushLayer(ld.params, ld.layer); } @@ -4093,14 +4072,7 @@ void wxD2DContext::Flush() LayerData ld = m_layers.top(); m_layers.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PopAxisAlignedClip(); - } - else - { - GetRenderTarget()->PopLayer(); - } + GetRenderTarget()->PopLayer(); // Save layer data. layersToRestore.push(ld); @@ -4123,15 +4095,8 @@ void wxD2DContext::Flush() LayerData ld = layersToRestore.top(); layersToRestore.pop(); - if ( ld.type == CLIP_AXIS_ALIGNED_RECT ) - { - GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds, - ld.params.maskAntialiasMode); - } - else - { - GetRenderTarget()->PushLayer(ld.params, ld.layer); - } + GetRenderTarget()->PushLayer(ld.params, ld.layer); + // Store layer parameters. m_layers.push(ld); }