Implement wxPolygonFillMode in GDI+ and D2D graphics contexts

Honour "fillStyle" parameter, which was previously ignored.

Closes https://github.com/wxWidgets/wxWidgets/pull/1478
This commit is contained in:
Maarten Bent 2019-08-11 22:29:28 +02:00 committed by Vadim Zeitlin
parent 4b227835ac
commit d10ed0b991
2 changed files with 27 additions and 11 deletions

View File

@ -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) if (m_composition == wxCOMPOSITION_DEST)
return; return;
@ -1871,7 +1871,8 @@ void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPol
} // for (int i = 0; i < n; i++) } // for (int i = 0; i < n; i++)
if ( !m_brush.IsNull() ) 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() ) if ( !m_pen.IsNull() )
m_context->DrawLines( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , cpoints , n ) ; m_context->DrawLines( ((wxGDIPlusPenData*)m_pen.GetGraphicsData())->GetGDIPlusPen() , cpoints , n ) ;
delete[] cpoints; delete[] cpoints;

View File

@ -1143,6 +1143,16 @@ public :
~wxD2DPathData(); ~wxD2DPathData();
void SetFillMode(D2D1_FILL_MODE fillMode)
{
m_fillMode = fillMode;
}
D2D1_FILL_MODE GetFillMode() const
{
return m_fillMode;
}
ID2D1PathGeometry* GetPathGeometry(); ID2D1PathGeometry* GetPathGeometry();
// This closes the geometry sink, ensuring all the figures are stored inside // This closes the geometry sink, ensuring all the figures are stored inside
@ -1202,7 +1212,7 @@ private:
void EndFigure(D2D1_FIGURE_END figureEnd); void EndFigure(D2D1_FIGURE_END figureEnd);
ID2D1Geometry* GetFullGeometry() const; ID2D1Geometry* GetFullGeometry(D2D1_FILL_MODE fillMode) const;
bool IsEmpty() const; bool IsEmpty() const;
bool IsStateSafeForFlush() const; bool IsStateSafeForFlush() const;
@ -1238,6 +1248,8 @@ private :
D2D1_POINT_2F m_figureLogStart; D2D1_POINT_2F m_figureLogStart;
bool m_geometryWritable; 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_figureStart(D2D1::Point2F(0.0f, 0.0f)),
m_figureLogStartSet(false), m_figureLogStartSet(false),
m_figureLogStart(D2D1::Point2F(0.0f, 0.0f)), 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); m_direct2dfactory->CreatePathGeometry(&m_pathGeometry);
// To properly initialize path geometry there is also // 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 // Our final path geometry is represented by geometry group
// which contains all transformed geometries plus current geometry. // 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. // And use this array as a source to create geometry group.
m_combinedGeometry.reset(); m_combinedGeometry.reset();
HRESULT hr = m_direct2dfactory->CreateGeometryGroup(D2D1_FILL_MODE_ALTERNATE, HRESULT hr = m_direct2dfactory->CreateGeometryGroup(fillMode,
pGeometries, numGeometries+1, &m_combinedGeometry); pGeometries, numGeometries+1, &m_combinedGeometry);
wxFAILED_HRESULT_MSG(hr); wxFAILED_HRESULT_MSG(hr);
delete []pGeometries; delete []pGeometries;
@ -1830,7 +1843,7 @@ void wxD2DPathData::CloseSubpath()
void* wxD2DPathData::GetNativePath() const void* wxD2DPathData::GetNativePath() const
{ {
return GetFullGeometry(); return GetFullGeometry(GetFillMode());
} }
void wxD2DPathData::Transform(const wxGraphicsMatrixData* matrix) 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 void wxD2DPathData::GetBox(wxDouble* x, wxDouble* y, wxDouble* w, wxDouble *h) const
{ {
D2D1_RECT_F bounds; D2D1_RECT_F bounds;
ID2D1Geometry *curGeometry = GetFullGeometry(); ID2D1Geometry *curGeometry = GetFullGeometry(GetFillMode());
HRESULT hr = curGeometry->GetBounds(D2D1::Matrix3x2F::Identity(), &bounds); HRESULT hr = curGeometry->GetBounds(D2D1::Matrix3x2F::Identity(), &bounds);
wxCHECK_HRESULT_RET(hr); wxCHECK_HRESULT_RET(hr);
// Check if bounds are empty // 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; 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; 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); curGeometry->FillContainsPoint(D2D1::Point2F(x, y), D2D1::Matrix3x2F::Identity(), &result);
return result != FALSE; 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) if (m_composition == wxCOMPOSITION_DEST)
return; return;
@ -3948,6 +3962,7 @@ void wxD2DContext::FillPath(const wxGraphicsPath& p , wxPolygonFillMode WXUNUSED
AdjustRenderTargetSize(); AdjustRenderTargetSize();
wxD2DPathData* pathData = wxGetD2DPathData(p); wxD2DPathData* pathData = wxGetD2DPathData(p);
pathData->SetFillMode(fillStyle == wxODDEVEN_RULE ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);
pathData->Flush(); pathData->Flush();
if (!m_brush.IsNull()) if (!m_brush.IsNull())