From a41a8ded79998cecbbcd1402b964d4adf9eb71a8 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Sat, 10 Aug 2019 21:56:14 +0200 Subject: [PATCH] Allow to set wxSVGFileDC shape rendering mode --- include/wx/dcsvg.h | 20 +++++++++-- interface/wx/dcsvg.h | 28 +++++++++++++++ src/common/dcsvg.cpp | 81 ++++++++++++++++++++++++++++++++------------ 3 files changed, 105 insertions(+), 24 deletions(-) diff --git a/include/wx/dcsvg.h b/include/wx/dcsvg.h index 2a64f8882c..964e3166a9 100644 --- a/include/wx/dcsvg.h +++ b/include/wx/dcsvg.h @@ -11,16 +11,25 @@ #ifndef _WX_DCSVG_H_ #define _WX_DCSVG_H_ +#if wxUSE_SVG + #include "wx/string.h" #include "wx/filename.h" #include "wx/dc.h" - -#if wxUSE_SVG - #include "wx/scopedptr.h" #define wxSVGVersion wxT("v0101") +enum wxSVGShapeRenderingMode +{ + wxSVG_SHAPE_RENDERING_AUTO = 0, + wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED, + wxSVG_SHAPE_RENDERING_CRISP_EDGES, + wxSVG_SHAPE_RENDERING_GEOMETRIC_PRECISION, + + wxSVG_SHAPE_RENDERING_OPTIMISE_SPEED = wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED +}; + class WXDLLIMPEXP_FWD_BASE wxFileOutputStream; class WXDLLIMPEXP_FWD_CORE wxSVGFileDC; @@ -146,6 +155,8 @@ public: void SetBitmapHandler(wxSVGBitmapHandler* handler); + void SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode); + private: virtual bool DoGetPixel(wxCoord, wxCoord, wxColour *) const wxOVERRIDE { @@ -255,6 +266,7 @@ private: double m_dpi; wxScopedPtr m_outfile; wxScopedPtr m_bmp_handler; // class to handle bitmaps + wxSVGShapeRenderingMode m_renderingMode; // The clipping nesting level is incremented by every call to // SetClippingRegion() and reset when DestroyClippingRegion() is called. @@ -284,6 +296,8 @@ public: // Use a custom bitmap handler: takes ownership of the handler. void SetBitmapHandler(wxSVGBitmapHandler* handler); + + void SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode); }; #endif // wxUSE_SVG diff --git a/interface/wx/dcsvg.h b/interface/wx/dcsvg.h index f4d55e22a1..bc6355139d 100644 --- a/interface/wx/dcsvg.h +++ b/interface/wx/dcsvg.h @@ -5,6 +5,23 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +/** + SVG shape rendering mode. + + These options represent the values defined in the SVG specification: + https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty +*/ +enum wxSVGShapeRenderingMode +{ + wxSVG_SHAPE_RENDERING_AUTO = 0, + wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED, + wxSVG_SHAPE_RENDERING_CRISP_EDGES, + wxSVG_SHAPE_RENDERING_GEOMETRIC_PRECISION, + + wxSVG_SHAPE_RENDERING_OPTIMISE_SPEED = wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED +}; + + /** @class wxSVGFileDC @@ -74,6 +91,17 @@ public: */ void SetBitmapHandler(wxSVGBitmapHandler* handler); + /** + Set the shape rendering mode of the generated SVG. + All subsequent drawing calls will have this rendering mode set in the + SVG file. + + The default mode is wxSVG_SHAPE_RENDERING_AUTO. + + @since 3.1.3 + */ + void SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode); + /** Sets the clipping region for this device context to the intersection of the given region described by the parameters of this method and the previously diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index f5029d7f34..9d6b16b265 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -281,7 +281,30 @@ wxString wxGetBrushFill(wxBrush const& brush) return s; } -wxString wxCreateBrushFill(wxBrush& brush) +wxString wxRenderMode(wxSVGShapeRenderingMode const& style) +{ + wxString mode; + switch (style) { + case wxSVG_SHAPE_RENDERING_OPTIMIZE_SPEED: + mode = wxS("optimizeSpeed"); + break; + case wxSVG_SHAPE_RENDERING_CRISP_EDGES: + mode = wxS("crispEdges"); + break; + case wxSVG_SHAPE_RENDERING_GEOMETRIC_PRECISION: + mode = wxS("geometricPrecision"); + break; + case wxSVG_SHAPE_RENDERING_AUTO: + default: + mode = wxS("auto"); + break; + } + + wxString s = wxString::Format(wxS("shape-rendering=\"%s\""), mode); + return s; +} + +wxString wxCreateBrushFill(wxBrush& brush, wxSVGShapeRenderingMode mode) { wxString s; wxString patternName = wxGetBrushStyleName(brush); @@ -317,8 +340,8 @@ wxString wxCreateBrushFill(wxBrush& brush) s += wxString::Format(wxS(" \n"), patternName, brushColourStr.substr(1)); - s += wxString::Format(wxS(" \n"), - brushColourStr, pattern); + s += wxString::Format(wxS(" \n"), + brushColourStr, pattern, wxRenderMode(mode)); s += wxS(" \n"); } @@ -444,6 +467,11 @@ void wxSVGFileDC::SetBitmapHandler(wxSVGBitmapHandler* handler) ((wxSVGFileDCImpl*)GetImpl())->SetBitmapHandler(handler); } +void wxSVGFileDC::SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode) +{ + ((wxSVGFileDCImpl*)GetImpl())->SetShapeRenderingMode(renderingMode); +} + // ---------------------------------------------------------- // wxSVGFileDCImpl // ---------------------------------------------------------- @@ -484,6 +512,8 @@ void wxSVGFileDCImpl::Init(const wxString &filename, int Width, int Height, m_filename = filename; m_graphics_changed = true; + m_renderingMode = wxSVG_SHAPE_RENDERING_AUTO; + ////////////////////code here m_bmp_handler.reset(); @@ -542,8 +572,8 @@ void wxSVGFileDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) NewGraphicsIfNeeded(); wxString s; - s = wxString::Format(wxS(" \n"), - x1, y1, x2, y2, wxGetPenPattern(m_pen)); + s = wxString::Format(wxS(" \n"), + x1, y1, x2, y2, wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen)); write(s); @@ -569,8 +599,8 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset); } - s += wxString::Format(wxS("\" style=\"fill:none\" %s/>\n"), - wxGetPenPattern(m_pen)); + s += wxString::Format(wxS("\" style=\"fill:none\" %s %s/>\n"), + wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen)); write(s); } @@ -691,8 +721,9 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor NumStr(-angle), NumStr(xRect), NumStr(yRect)); s = wxString::Format( - wxS(" \n"), - NumStr(xRect), NumStr(yRect), ww, hh, rectStyle, rectTransform); + wxS(" \n"), + NumStr(xRect), NumStr(yRect), ww, hh, + wxRenderMode(m_renderingMode), rectStyle, rectTransform); write(s); } @@ -725,9 +756,9 @@ void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width NewGraphicsIfNeeded(); wxString s; - s = wxString::Format(wxS(" \n"), + s = wxString::Format(wxS(" \n"), x, y, width, height, NumStr(radius), - wxGetPenPattern(m_pen), wxGetBrushFill(m_brush)); + wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen), wxGetBrushFill(m_brush)); write(s); @@ -751,8 +782,8 @@ void wxSVGFileDCImpl::DoDrawPolygon(int n, const wxPoint points[], CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset); } - s += wxString::Format(wxS("\" %s %s style=\"fill-rule:%s;\"/>\n"), - wxGetPenPattern(m_pen), wxGetBrushFill(m_brush), + s += wxString::Format(wxS("\" %s %s %s style=\"fill-rule:%s;\"/>\n"), + wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen), wxGetBrushFill(m_brush), (fillStyle == wxODDEVEN_RULE) ? wxS("evenodd") : wxS("nonzero")); write(s); @@ -808,8 +839,9 @@ void wxSVGFileDCImpl::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord const double rw = width / 2.0; wxString s; - s = wxString::Format(wxS(" \n"); write(s); @@ -877,7 +909,8 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, x1, y1, NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2, line); } - s += wxString::Format(wxS("\" %s/>\n"), wxGetPenPattern(m_pen)); + s += wxString::Format(wxS("\" %s %s/>\n"), + wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen)); write(s); } @@ -962,16 +995,17 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord NewGraphicsIfNeeded(); wxString arcFill = arcPath; - arcFill += wxString::Format(wxS(" L%s %s z\" %s/>\n"), - NumStr(xc), NumStr(yc), wxGetPenPattern(m_pen)); + arcFill += wxString::Format(wxS(" L%s %s z\" %s %s/>\n"), + NumStr(xc), NumStr(yc), + wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen)); write(arcFill); } wxDCBrushChanger setTransp(*GetOwner(), *wxTRANSPARENT_BRUSH); NewGraphicsIfNeeded(); - wxString arcLine = wxString::Format(wxS("%s\" %s/>\n"), - arcPath, wxGetPenPattern(m_pen)); + wxString arcLine = wxString::Format(wxS("%s\" %s %s/>\n"), + arcPath, wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen)); write(arcLine); } @@ -1078,13 +1112,18 @@ void wxSVGFileDCImpl::SetBitmapHandler(wxSVGBitmapHandler* handler) m_bmp_handler.reset(handler); } +void wxSVGFileDCImpl::SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode) +{ + m_renderingMode = renderingMode; +} + void wxSVGFileDCImpl::SetBrush(const wxBrush& brush) { m_brush = brush; m_graphics_changed = true; - wxString pattern = wxCreateBrushFill(m_brush); + wxString pattern = wxCreateBrushFill(m_brush, m_renderingMode); if ( !pattern.IsEmpty() ) { NewGraphicsIfNeeded();