From d10ed0b991da0dcf00ac312216c5ec0241429ad5 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sun, 11 Aug 2019 22:29:28 +0200 Subject: [PATCH] Implement wxPolygonFillMode in GDI+ and D2D graphics contexts Honour "fillStyle" parameter, which was previously ignored. Closes https://github.com/wxWidgets/wxWidgets/pull/1478 --- src/msw/graphics.cpp | 5 +++-- src/msw/graphicsd2d.cpp | 33 ++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index e5309c9bf7..a23948588d 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -1857,7 +1857,7 @@ void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points) } } -void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode WXUNUSED(fillStyle) ) +void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode fillStyle ) { if (m_composition == wxCOMPOSITION_DEST) return; @@ -1871,7 +1871,8 @@ void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPol } // for (int i = 0; i < n; i++) if ( !m_brush.IsNull() ) - m_context->FillPolygon( ((wxGDIPlusBrushData*)m_brush.GetRefData())->GetGDIPlusBrush() , cpoints , n ) ; + m_context->FillPolygon( ((wxGDIPlusBrushData*)m_brush.GetRefData())->GetGDIPlusBrush() , cpoints , n , + fillStyle == wxODDEVEN_RULE ? FillModeAlternate : FillModeWinding ) ; if ( !m_pen.IsNull() ) m_context->DrawLines( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , cpoints , n ) ; delete[] cpoints; diff --git a/src/msw/graphicsd2d.cpp b/src/msw/graphicsd2d.cpp index de24c1f9e1..a874e7229d 100644 --- a/src/msw/graphicsd2d.cpp +++ b/src/msw/graphicsd2d.cpp @@ -1143,6 +1143,16 @@ public : ~wxD2DPathData(); + void SetFillMode(D2D1_FILL_MODE fillMode) + { + m_fillMode = fillMode; + } + + D2D1_FILL_MODE GetFillMode() const + { + return m_fillMode; + } + ID2D1PathGeometry* GetPathGeometry(); // This closes the geometry sink, ensuring all the figures are stored inside @@ -1202,7 +1212,7 @@ private: void EndFigure(D2D1_FIGURE_END figureEnd); - ID2D1Geometry* GetFullGeometry() const; + ID2D1Geometry* GetFullGeometry(D2D1_FILL_MODE fillMode) const; bool IsEmpty() const; bool IsStateSafeForFlush() const; @@ -1238,6 +1248,8 @@ private : D2D1_POINT_2F m_figureLogStart; bool m_geometryWritable; + + D2D1_FILL_MODE m_fillMode; }; //----------------------------------------------------------------------------- @@ -1253,7 +1265,8 @@ wxD2DPathData::wxD2DPathData(wxGraphicsRenderer* renderer, ID2D1Factory* d2dFact m_figureStart(D2D1::Point2F(0.0f, 0.0f)), m_figureLogStartSet(false), m_figureLogStart(D2D1::Point2F(0.0f, 0.0f)), - m_geometryWritable(true) + m_geometryWritable(true), + m_fillMode(D2D1_FILL_MODE_ALTERNATE) { m_direct2dfactory->CreatePathGeometry(&m_pathGeometry); // To properly initialize path geometry there is also @@ -1419,7 +1432,7 @@ void wxD2DPathData::EndFigure(D2D1_FIGURE_END figureEnd) } } -ID2D1Geometry* wxD2DPathData::GetFullGeometry() const +ID2D1Geometry* wxD2DPathData::GetFullGeometry(D2D1_FILL_MODE fillMode) const { // Our final path geometry is represented by geometry group // which contains all transformed geometries plus current geometry. @@ -1435,7 +1448,7 @@ ID2D1Geometry* wxD2DPathData::GetFullGeometry() const // And use this array as a source to create geometry group. m_combinedGeometry.reset(); - HRESULT hr = m_direct2dfactory->CreateGeometryGroup(D2D1_FILL_MODE_ALTERNATE, + HRESULT hr = m_direct2dfactory->CreateGeometryGroup(fillMode, pGeometries, numGeometries+1, &m_combinedGeometry); wxFAILED_HRESULT_MSG(hr); delete []pGeometries; @@ -1830,7 +1843,7 @@ void wxD2DPathData::CloseSubpath() void* wxD2DPathData::GetNativePath() const { - return GetFullGeometry(); + return GetFullGeometry(GetFillMode()); } void wxD2DPathData::Transform(const wxGraphicsMatrixData* matrix) @@ -1920,7 +1933,7 @@ void wxD2DPathData::Transform(const wxGraphicsMatrixData* matrix) void wxD2DPathData::GetBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble *h) const { D2D1_RECT_F bounds; - ID2D1Geometry *curGeometry = GetFullGeometry(); + ID2D1Geometry *curGeometry = GetFullGeometry(GetFillMode()); HRESULT hr = curGeometry->GetBounds(D2D1::Matrix3x2F::Identity(), &bounds); wxCHECK_HRESULT_RET(hr); // Check if bounds are empty @@ -1934,10 +1947,11 @@ void wxD2DPathData::GetBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble *h) c if (h) *h = bounds.bottom - bounds.top; } -bool wxD2DPathData::Contains(wxDouble x, wxDouble y, wxPolygonFillMode WXUNUSED(fillStyle)) const +bool wxD2DPathData::Contains(wxDouble x, wxDouble y, wxPolygonFillMode fillStyle) const { BOOL result; - ID2D1Geometry *curGeometry = GetFullGeometry(); + D2D1_FILL_MODE fillMode = (fillStyle == wxODDEVEN_RULE) ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING; + ID2D1Geometry *curGeometry = GetFullGeometry(fillMode); curGeometry->FillContainsPoint(D2D1::Point2F(x, y), D2D1::Matrix3x2F::Identity(), &result); return result != FALSE; } @@ -3939,7 +3953,7 @@ void wxD2DContext::StrokePath(const wxGraphicsPath& p) } } -void wxD2DContext::FillPath(const wxGraphicsPath& p , wxPolygonFillMode WXUNUSED(fillStyle)) +void wxD2DContext::FillPath(const wxGraphicsPath& p , wxPolygonFillMode fillStyle) { if (m_composition == wxCOMPOSITION_DEST) return; @@ -3948,6 +3962,7 @@ void wxD2DContext::FillPath(const wxGraphicsPath& p , wxPolygonFillMode WXUNUSED AdjustRenderTargetSize(); wxD2DPathData* pathData = wxGetD2DPathData(p); + pathData->SetFillMode(fillStyle == wxODDEVEN_RULE ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING); pathData->Flush(); if (!m_brush.IsNull())