Implement DrawSpline in wxSVGFileDC

Drawing Bézier curves is supported natively in SVG so these curves
should be used instead of generic wxDC implementation based on
polygonal approximation.
This commit is contained in:
Artur Wieczorek 2021-07-04 19:22:02 +02:00
parent 02c90d126c
commit cc5bfc0fb1
2 changed files with 54 additions and 0 deletions

View File

@ -198,6 +198,9 @@ private:
virtual void DoDrawLines(int n, const wxPoint points[], virtual void DoDrawLines(int n, const wxPoint points[],
wxCoord xoffset, wxCoord yoffset) wxOVERRIDE; wxCoord xoffset, wxCoord yoffset) wxOVERRIDE;
#if wxUSE_SPLINES
void DoDrawSpline(const wxPointList* points) wxOVERRIDE;
#endif // wxUSE_SPLINES
virtual void DoDrawPoint(wxCoord x, wxCoord y) wxOVERRIDE; virtual void DoDrawPoint(wxCoord x, wxCoord y) wxOVERRIDE;

View File

@ -630,6 +630,57 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset
} }
} }
#if wxUSE_SPLINES
void wxSVGFileDCImpl::DoDrawSpline(const wxPointList* points)
{
wxCHECK_RET(points, "NULL pointer to spline points");
wxCHECK_RET(points->size() >= 2, "incomplete list of spline points");
NewGraphicsIfNeeded();
wxPointList::const_iterator itPt = points->begin();
const wxPoint* pt = *itPt; ++itPt;
wxPoint2DDouble p1(*pt);
pt = *itPt; ++itPt;
wxPoint2DDouble p2(*pt);
wxPoint2DDouble p3 = (p1 + p2) / 2.0;
wxString s = " <path d=\"";
s += wxString::Format("M %s %s L %s %s",
NumStr(p1.m_x), NumStr(p1.m_y), NumStr(p3.m_x), NumStr(p3.m_y));
CalcBoundingBox(wxRound(p1.m_x), wxRound(p1.m_y));
CalcBoundingBox(wxRound(p3.m_x), wxRound(p3.m_y));
while ( itPt != points->end() )
{
pt = *itPt; ++itPt;
wxPoint2DDouble p0 = p3;
p1 = p2;
p2 = *pt;
p3 = (p1 + p2) / 2.0;
// Calculate using degree elevation to a cubic bezier
wxPoint2DDouble c1 = (p0 + (p1 * 2.0)) / 3.0;
wxPoint2DDouble c2 = ((p1 * 2.0) + p3) / 3.0;
s += wxString::Format(" C %s %s, %s %s, %s %s",
NumStr(c1.m_x), NumStr(c1.m_y), NumStr(c2.m_x), NumStr(c2.m_y), NumStr(p3.m_x), NumStr(p3.m_y));
CalcBoundingBox(wxRound(p0.m_x), wxRound(p0.m_y));
CalcBoundingBox(wxRound(p3.m_x), wxRound(p3.m_y));
}
s += wxString::Format(" L %s %s", NumStr(p2.m_x), NumStr(p2.m_y));
CalcBoundingBox(wxRound(p2.m_x), wxRound(p2.m_y));
s += wxString::Format("\" style=\"fill:none\" %s %s/>\n",
GetRenderMode(m_renderingMode), GetPenPattern(m_pen));
write(s);
}
#endif // wxUSE_SPLINES
void wxSVGFileDCImpl::DoDrawPoint(wxCoord x, wxCoord y) void wxSVGFileDCImpl::DoDrawPoint(wxCoord x, wxCoord y)
{ {
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();