Allow to set wxSVGFileDC shape rendering mode

This commit is contained in:
Maarten Bent
2019-08-10 21:56:14 +02:00
parent 75f08dfd51
commit a41a8ded79
3 changed files with 105 additions and 24 deletions

View File

@@ -11,16 +11,25 @@
#ifndef _WX_DCSVG_H_ #ifndef _WX_DCSVG_H_
#define _WX_DCSVG_H_ #define _WX_DCSVG_H_
#if wxUSE_SVG
#include "wx/string.h" #include "wx/string.h"
#include "wx/filename.h" #include "wx/filename.h"
#include "wx/dc.h" #include "wx/dc.h"
#if wxUSE_SVG
#include "wx/scopedptr.h" #include "wx/scopedptr.h"
#define wxSVGVersion wxT("v0101") #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_BASE wxFileOutputStream;
class WXDLLIMPEXP_FWD_CORE wxSVGFileDC; class WXDLLIMPEXP_FWD_CORE wxSVGFileDC;
@@ -146,6 +155,8 @@ public:
void SetBitmapHandler(wxSVGBitmapHandler* handler); void SetBitmapHandler(wxSVGBitmapHandler* handler);
void SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode);
private: private:
virtual bool DoGetPixel(wxCoord, wxCoord, wxColour *) const wxOVERRIDE virtual bool DoGetPixel(wxCoord, wxCoord, wxColour *) const wxOVERRIDE
{ {
@@ -255,6 +266,7 @@ private:
double m_dpi; double m_dpi;
wxScopedPtr<wxFileOutputStream> m_outfile; wxScopedPtr<wxFileOutputStream> m_outfile;
wxScopedPtr<wxSVGBitmapHandler> m_bmp_handler; // class to handle bitmaps wxScopedPtr<wxSVGBitmapHandler> m_bmp_handler; // class to handle bitmaps
wxSVGShapeRenderingMode m_renderingMode;
// The clipping nesting level is incremented by every call to // The clipping nesting level is incremented by every call to
// SetClippingRegion() and reset when DestroyClippingRegion() is called. // SetClippingRegion() and reset when DestroyClippingRegion() is called.
@@ -284,6 +296,8 @@ public:
// Use a custom bitmap handler: takes ownership of the handler. // Use a custom bitmap handler: takes ownership of the handler.
void SetBitmapHandler(wxSVGBitmapHandler* handler); void SetBitmapHandler(wxSVGBitmapHandler* handler);
void SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode);
}; };
#endif // wxUSE_SVG #endif // wxUSE_SVG

View File

@@ -5,6 +5,23 @@
// Licence: wxWindows licence // 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 @class wxSVGFileDC
@@ -74,6 +91,17 @@ public:
*/ */
void SetBitmapHandler(wxSVGBitmapHandler* handler); 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 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 the given region described by the parameters of this method and the previously

View File

@@ -281,7 +281,30 @@ wxString wxGetBrushFill(wxBrush const& brush)
return s; 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 s;
wxString patternName = wxGetBrushStyleName(brush); wxString patternName = wxGetBrushStyleName(brush);
@@ -317,8 +340,8 @@ wxString wxCreateBrushFill(wxBrush& brush)
s += wxString::Format(wxS(" <pattern id=\"%s%s\" patternUnits=\"userSpaceOnUse\" width=\"8\" height=\"8\">\n"), s += wxString::Format(wxS(" <pattern id=\"%s%s\" patternUnits=\"userSpaceOnUse\" width=\"8\" height=\"8\">\n"),
patternName, brushColourStr.substr(1)); patternName, brushColourStr.substr(1));
s += wxString::Format(wxS(" <path style=\"stroke:%s;\" %s/>\n"), s += wxString::Format(wxS(" <path style=\"stroke:%s;\" %s %s/>\n"),
brushColourStr, pattern); brushColourStr, pattern, wxRenderMode(mode));
s += wxS(" </pattern>\n"); s += wxS(" </pattern>\n");
} }
@@ -444,6 +467,11 @@ void wxSVGFileDC::SetBitmapHandler(wxSVGBitmapHandler* handler)
((wxSVGFileDCImpl*)GetImpl())->SetBitmapHandler(handler); ((wxSVGFileDCImpl*)GetImpl())->SetBitmapHandler(handler);
} }
void wxSVGFileDC::SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode)
{
((wxSVGFileDCImpl*)GetImpl())->SetShapeRenderingMode(renderingMode);
}
// ---------------------------------------------------------- // ----------------------------------------------------------
// wxSVGFileDCImpl // wxSVGFileDCImpl
// ---------------------------------------------------------- // ----------------------------------------------------------
@@ -484,6 +512,8 @@ void wxSVGFileDCImpl::Init(const wxString &filename, int Width, int Height,
m_filename = filename; m_filename = filename;
m_graphics_changed = true; m_graphics_changed = true;
m_renderingMode = wxSVG_SHAPE_RENDERING_AUTO;
////////////////////code here ////////////////////code here
m_bmp_handler.reset(); m_bmp_handler.reset();
@@ -542,8 +572,8 @@ void wxSVGFileDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();
wxString s; wxString s;
s = wxString::Format(wxS(" <path d=\"M%d %d L%d %d\" %s/>\n"), s = wxString::Format(wxS(" <path d=\"M%d %d L%d %d\" %s %s/>\n"),
x1, y1, x2, y2, wxGetPenPattern(m_pen)); x1, y1, x2, y2, wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen));
write(s); 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); CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
} }
s += wxString::Format(wxS("\" style=\"fill:none\" %s/>\n"), s += wxString::Format(wxS("\" style=\"fill:none\" %s %s/>\n"),
wxGetPenPattern(m_pen)); wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen));
write(s); write(s);
} }
@@ -691,8 +721,9 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor
NumStr(-angle), NumStr(xRect), NumStr(yRect)); NumStr(-angle), NumStr(xRect), NumStr(yRect));
s = wxString::Format( s = wxString::Format(
wxS(" <rect x=\"%s\" y=\"%s\" width=\"%d\" height=\"%d\" %s %s/>\n"), wxS(" <rect x=\"%s\" y=\"%s\" width=\"%d\" height=\"%d\" %s %s %s/>\n"),
NumStr(xRect), NumStr(yRect), ww, hh, rectStyle, rectTransform); NumStr(xRect), NumStr(yRect), ww, hh,
wxRenderMode(m_renderingMode), rectStyle, rectTransform);
write(s); write(s);
} }
@@ -725,9 +756,9 @@ void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();
wxString s; wxString s;
s = wxString::Format(wxS(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" %s %s/>\n"), s = wxString::Format(wxS(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" %s %s %s/>\n"),
x, y, width, height, NumStr(radius), x, y, width, height, NumStr(radius),
wxGetPenPattern(m_pen), wxGetBrushFill(m_brush)); wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen), wxGetBrushFill(m_brush));
write(s); write(s);
@@ -751,8 +782,8 @@ void wxSVGFileDCImpl::DoDrawPolygon(int n, const wxPoint points[],
CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset); CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
} }
s += wxString::Format(wxS("\" %s %s style=\"fill-rule:%s;\"/>\n"), s += wxString::Format(wxS("\" %s %s %s style=\"fill-rule:%s;\"/>\n"),
wxGetPenPattern(m_pen), wxGetBrushFill(m_brush), wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen), wxGetBrushFill(m_brush),
(fillStyle == wxODDEVEN_RULE) ? wxS("evenodd") : wxS("nonzero")); (fillStyle == wxODDEVEN_RULE) ? wxS("evenodd") : wxS("nonzero"));
write(s); write(s);
@@ -808,8 +839,9 @@ void wxSVGFileDCImpl::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord
const double rw = width / 2.0; const double rw = width / 2.0;
wxString s; wxString s;
s = wxString::Format(wxS(" <ellipse cx=\"%s\" cy=\"%s\" rx=\"%s\" ry=\"%s\" %s"), s = wxString::Format(wxS(" <ellipse cx=\"%s\" cy=\"%s\" rx=\"%s\" ry=\"%s\" %s %s"),
NumStr(x + rw), NumStr(y + rh), NumStr(rw), NumStr(rh), wxGetPenPattern(m_pen)); NumStr(x + rw), NumStr(y + rh), NumStr(rw), NumStr(rh),
wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen));
s += wxS("/>\n"); s += wxS("/>\n");
write(s); 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); 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); write(s);
} }
@@ -962,16 +995,17 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();
wxString arcFill = arcPath; wxString arcFill = arcPath;
arcFill += wxString::Format(wxS(" L%s %s z\" %s/>\n"), arcFill += wxString::Format(wxS(" L%s %s z\" %s %s/>\n"),
NumStr(xc), NumStr(yc), wxGetPenPattern(m_pen)); NumStr(xc), NumStr(yc),
wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen));
write(arcFill); write(arcFill);
} }
wxDCBrushChanger setTransp(*GetOwner(), *wxTRANSPARENT_BRUSH); wxDCBrushChanger setTransp(*GetOwner(), *wxTRANSPARENT_BRUSH);
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();
wxString arcLine = wxString::Format(wxS("%s\" %s/>\n"), wxString arcLine = wxString::Format(wxS("%s\" %s %s/>\n"),
arcPath, wxGetPenPattern(m_pen)); arcPath, wxRenderMode(m_renderingMode), wxGetPenPattern(m_pen));
write(arcLine); write(arcLine);
} }
@@ -1078,13 +1112,18 @@ void wxSVGFileDCImpl::SetBitmapHandler(wxSVGBitmapHandler* handler)
m_bmp_handler.reset(handler); m_bmp_handler.reset(handler);
} }
void wxSVGFileDCImpl::SetShapeRenderingMode(wxSVGShapeRenderingMode renderingMode)
{
m_renderingMode = renderingMode;
}
void wxSVGFileDCImpl::SetBrush(const wxBrush& brush) void wxSVGFileDCImpl::SetBrush(const wxBrush& brush)
{ {
m_brush = brush; m_brush = brush;
m_graphics_changed = true; m_graphics_changed = true;
wxString pattern = wxCreateBrushFill(m_brush); wxString pattern = wxCreateBrushFill(m_brush, m_renderingMode);
if ( !pattern.IsEmpty() ) if ( !pattern.IsEmpty() )
{ {
NewGraphicsIfNeeded(); NewGraphicsIfNeeded();