Fixed closing sub-paths of wxGraphicsPath with GDI+ renderer.

When sub-path is closed with CloseSubpath() then current point should be moved to the joined endpoint of the sub-path (what is equivalent of moving it to the starting point of the sub-path). Native CloseFigure() doesn't move the native current point to the starting point of the figure so we need to maintain it on our own in this case.
To implement this behaviour we need to store the starting point of the figure in a dedicate data member and use it to update the current point when the figure is closed.
But native GDI+ renderer doesn't offer any support for updating directly the current point (only explicit drawing operations update its value) so we need also to remember our "logical" current point (being the result of calling CloseSubPath, MoveToPoint, etc.) in a dedicated data member and use it instead of the native current point in the next operation which requires current point location.

Closes #17520
This commit is contained in:
Artur Wieczorek
2016-05-05 11:47:30 +02:00
parent 329aee5660
commit 984e54ffdd

View File

@@ -181,6 +181,10 @@ public :
private : private :
GraphicsPath* m_path; GraphicsPath* m_path;
bool m_logCurrentPointSet;
PointF m_logCurrentPoint;
bool m_figureOpened;
PointF m_figureStart;
}; };
class wxGDIPlusMatrixData : public wxGraphicsMatrixData class wxGDIPlusMatrixData : public wxGraphicsMatrixData
@@ -1161,6 +1165,10 @@ wxGDIPlusBitmapData::~wxGDIPlusBitmapData()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
wxGDIPlusPathData::wxGDIPlusPathData(wxGraphicsRenderer* renderer, GraphicsPath* path ) : wxGraphicsPathData(renderer) wxGDIPlusPathData::wxGDIPlusPathData(wxGraphicsRenderer* renderer, GraphicsPath* path ) : wxGraphicsPathData(renderer)
, m_logCurrentPointSet(false)
, m_logCurrentPoint(0.0, 0.0)
, m_figureOpened(false)
, m_figureStart(0.0, 0.0)
{ {
if ( path ) if ( path )
m_path = path; m_path = path;
@@ -1175,7 +1183,14 @@ wxGDIPlusPathData::~wxGDIPlusPathData()
wxGraphicsObjectRefData* wxGDIPlusPathData::Clone() const wxGraphicsObjectRefData* wxGDIPlusPathData::Clone() const
{ {
return new wxGDIPlusPathData( GetRenderer() , m_path->Clone()); wxGDIPlusPathData* newPathData =
new wxGDIPlusPathData(GetRenderer(), m_path->Clone());
newPathData->m_logCurrentPointSet = m_logCurrentPointSet;
newPathData->m_logCurrentPoint = m_logCurrentPoint;
newPathData->m_figureOpened = m_figureOpened;
newPathData->m_figureStart = m_figureStart;
return newPathData;
} }
// //
@@ -1185,19 +1200,40 @@ wxGraphicsObjectRefData* wxGDIPlusPathData::Clone() const
void wxGDIPlusPathData::MoveToPoint( wxDouble x , wxDouble y ) void wxGDIPlusPathData::MoveToPoint( wxDouble x , wxDouble y )
{ {
m_path->StartFigure(); m_path->StartFigure();
m_path->AddLine((REAL) x,(REAL) y,(REAL) x,(REAL) y); m_figureOpened = true;
m_figureStart = PointF((REAL)x, (REAL)y);
// Since native current point is not updated in any way
// we have to maintain current point location on our own in this case.
m_logCurrentPoint = m_figureStart;
m_logCurrentPointSet = true;
} }
void wxGDIPlusPathData::AddLineToPoint( wxDouble x , wxDouble y ) void wxGDIPlusPathData::AddLineToPoint( wxDouble x , wxDouble y )
{ {
PointF start; PointF start;
m_path->GetLastPoint(&start); if ( m_logCurrentPointSet )
{
start = m_logCurrentPoint;
// After calling AddLine() the native current point
// will be updated and can be used.
m_logCurrentPointSet = false;
}
else
{
m_path->GetLastPoint(&start);
}
m_path->AddLine(start.X, start.Y, (REAL)x, (REAL)y); m_path->AddLine(start.X, start.Y, (REAL)x, (REAL)y);
} }
void wxGDIPlusPathData::CloseSubpath() void wxGDIPlusPathData::CloseSubpath()
{ {
m_path->CloseFigure(); m_path->CloseFigure();
m_figureOpened = false;
// Since native GDI+ renderer doesn't move its current point
// to the starting point of the figure we need to maintain
// it on our own in this case.
m_logCurrentPoint = m_figureStart;
m_logCurrentPointSet = true;
} }
void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y ) void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
@@ -1206,7 +1242,17 @@ void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx
PointF c2(cx2,cy2); PointF c2(cx2,cy2);
PointF end(x,y); PointF end(x,y);
PointF start; PointF start;
m_path->GetLastPoint(&start); if ( m_logCurrentPointSet )
{
start = m_logCurrentPoint;
// After calling AddBezier() the native current point
// will be updated and can be used.
m_logCurrentPointSet = false;
}
else
{
m_path->GetLastPoint(&start);
}
m_path->AddBezier(start,c1,c2,end); m_path->AddBezier(start,c1,c2,end);
} }
@@ -1214,7 +1260,11 @@ void wxGDIPlusPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx
void wxGDIPlusPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const void wxGDIPlusPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
{ {
PointF start; PointF start;
m_path->GetLastPoint(&start); if ( m_logCurrentPointSet )
start = m_logCurrentPoint;
else
m_path->GetLastPoint(&start);
*x = start.X ; *x = start.X ;
*y = start.Y ; *y = start.Y ;
} }
@@ -1241,16 +1291,26 @@ void wxGDIPlusPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double start
} }
} }
m_path->AddArc((REAL) (x-r),(REAL) (y-r),(REAL) (2*r),(REAL) (2*r),wxRadToDeg(startAngle),wxRadToDeg(sweepAngle)); m_path->AddArc((REAL) (x-r),(REAL) (y-r),(REAL) (2*r),(REAL) (2*r),wxRadToDeg(startAngle),wxRadToDeg(sweepAngle));
// After calling AddArc() the native current point will be updated and can be used.
m_logCurrentPointSet = false;
} }
void wxGDIPlusPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) void wxGDIPlusPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
{ {
m_path->AddRectangle(RectF(x,y,w,h)); m_path->AddRectangle(RectF(x,y,w,h));
// Drawn rectangle is an intrinsically closed shape but native
// current point is not moved to the starting point of the figure
// (the same case as with CloseFigure) so we need to maintain it
// on our own in this case.
m_logCurrentPoint = PointF((REAL)x, (REAL)y);
m_logCurrentPointSet = true;
} }
void wxGDIPlusPathData::AddPath( const wxGraphicsPathData* path ) void wxGDIPlusPathData::AddPath( const wxGraphicsPathData* path )
{ {
m_path->AddPath( (GraphicsPath*) path->GetNativePath(), FALSE); m_path->AddPath( (GraphicsPath*) path->GetNativePath(), FALSE);
// We have to switch to the native current point.
m_logCurrentPointSet = false;
} }