From 947c6d4954b6f05b0b28a871afe8db7323fad283 Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Fri, 15 Jul 2016 21:01:57 +0200 Subject: [PATCH] Fixed setting clipping region (passed in wxRegion) for Direct2D renderer. If empty wxRegion is passed to wxD2DContext::Clip() then ID2D1RectangleGeometry object representing geometric mask used by ID2D1Layer object (clipping layer) has to be created in a special way because wxRegionIterator doesn't extract empty rectangle. ID2D1RectangleGeometry object representing geometric mask has to be maintained as long as corresponding clipping layer is in use so we have to store a reference to this object together with other layer data. Object is released when layer is destroyed. Closes #17596 --- src/msw/graphicsd2d.cpp | 75 ++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/src/msw/graphicsd2d.cpp b/src/msw/graphicsd2d.cpp index 632cca4ffe..0d382290a9 100644 --- a/src/msw/graphicsd2d.cpp +++ b/src/msw/graphicsd2d.cpp @@ -757,40 +757,62 @@ D2D1_RECT_F wxD2DConvertRect(const wxRect& rect) wxCOMPtr wxD2DConvertRegionToGeometry(ID2D1Factory* direct2dFactory, const wxRegion& region) { - wxRegionIterator regionIterator(region); - - // Count the number of rectangles which compose the region - int rectCount = 0; - while(regionIterator++) - rectCount++; - // Build the array of geometries - ID2D1Geometry** geometries = new ID2D1Geometry*[rectCount]; - regionIterator.Reset(region); - - int i = 0; - while(regionIterator) + HRESULT hr; + int i; + ID2D1Geometry** geometries; + int rectCount; + if ( region.IsEmpty() ) { - geometries[i] = NULL; + // Empty region is skipped by iterator + // so we have to create it in a special way. + rectCount = 1; + geometries = new ID2D1Geometry*[rectCount]; - wxRect rect = regionIterator.GetRect(); - rect.SetWidth(rect.GetWidth() + 1); - rect.SetHeight(rect.GetHeight() + 1); + geometries[0] = NULL; + hr = direct2dFactory->CreateRectangleGeometry( + D2D1::RectF(0.0F, 0.0F, 0.0F, 0.0F), + (ID2D1RectangleGeometry**)(&geometries[0])); + wxFAILED_HRESULT_MSG(hr); + } + else + { + // Count the number of rectangles which compose the region + wxRegionIterator regionIterator(region); + rectCount = 0; + while(regionIterator++) + rectCount++; - direct2dFactory->CreateRectangleGeometry( - wxD2DConvertRect(rect), - (ID2D1RectangleGeometry**)(&geometries[i])); + geometries = new ID2D1Geometry*[rectCount]; + regionIterator.Reset(region); - i++; regionIterator++; + i = 0; + while(regionIterator) + { + geometries[i] = NULL; + + wxRect rect = regionIterator.GetRect(); + rect.SetWidth(rect.GetWidth() + 1); + rect.SetHeight(rect.GetHeight() + 1); + + hr = direct2dFactory->CreateRectangleGeometry( + wxD2DConvertRect(rect), + (ID2D1RectangleGeometry**)(&geometries[i])); + wxFAILED_HRESULT_MSG(hr); + + i++; + ++regionIterator; + } } // Create a geometry group to hold all the rectangles wxCOMPtr resultGeometry; - direct2dFactory->CreateGeometryGroup( + hr = direct2dFactory->CreateGeometryGroup( D2D1_FILL_MODE_WINDING, geometries, rectCount, &resultGeometry); + wxFAILED_HRESULT_MSG(hr); // Cleanup temporaries for (i = 0; i < rectCount; ++i) @@ -3400,6 +3422,7 @@ private: LayerType type; D2D1_LAYER_PARAMETERS params; wxCOMPtr layer; + wxCOMPtr geometry; }; private: @@ -3493,6 +3516,8 @@ wxD2DContext::~wxD2DContext() else { GetRenderTarget()->PopLayer(); + ld.layer.reset(); + ld.geometry.reset(); } } @@ -3512,12 +3537,14 @@ void wxD2DContext::Clip(const wxRegion& region) wxCOMPtr clipGeometry = wxD2DConvertRegionToGeometry(m_direct2dFactory, region); wxCOMPtr clipLayer; - GetRenderTarget()->CreateLayer(&clipLayer); + HRESULT hr = GetRenderTarget()->CreateLayer(&clipLayer); + wxCHECK_HRESULT_RET(hr); LayerData ld; ld.type = CLIP_LAYER; ld.params = D2D1::LayerParameters(D2D1::InfiniteRect(), clipGeometry); ld.layer = clipLayer; + ld.geometry = clipGeometry; GetRenderTarget()->PushLayer(ld.params, clipLayer); // Store layer parameters. @@ -3556,6 +3583,7 @@ void wxD2DContext::ResetClip() { GetRenderTarget()->PopLayer(); ld.layer.reset(); + ld.geometry.reset(); continue; } @@ -3666,7 +3694,8 @@ bool wxD2DContext::SetCompositionMode(wxCompositionMode compositionMode) void wxD2DContext::BeginLayer(wxDouble opacity) { wxCOMPtr layer; - GetRenderTarget()->CreateLayer(&layer); + HRESULT hr = GetRenderTarget()->CreateLayer(&layer); + wxCHECK_HRESULT_RET(hr); LayerData ld; ld.type = OTHER_LAYER;