diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py
index ae1ec91c..ce2a90c0 100644
--- a/pyqtgraph/exporters/SVGExporter.py
+++ b/pyqtgraph/exporters/SVGExporter.py
@@ -23,7 +23,8 @@ class SVGExporter(Exporter):
#{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
#{'name': 'viewbox clipping', 'type': 'bool', 'value': True},
#{'name': 'normalize coordinates', 'type': 'bool', 'value': True},
- #{'name': 'normalize line width', 'type': 'bool', 'value': True},
+ {'name': 'scaling stroke', 'type': 'bool', 'value': False, 'tip': "If False, strokes are non-scaling, "
+ "which means that they appear the same width on screen regardless of how they are scaled or how the view is zoomed."},
])
#self.params.param('width').sigValueChanged.connect(self.widthChanged)
#self.params.param('height').sigValueChanged.connect(self.heightChanged)
@@ -49,7 +50,8 @@ class SVGExporter(Exporter):
## Qt's SVG generator is not complete. (notably, it lacks clipping)
## Instead, we will use Qt to generate SVG for each item independently,
## then manually reconstruct the entire document.
- xml = generateSvg(self.item)
+ options = {ch.name():ch.value() for ch in self.params.children()}
+ xml = generateSvg(self.item, options)
if toBytes:
return xml.encode('UTF-8')
@@ -69,10 +71,10 @@ xmlHeader = """\
Generated with Qt and pyqtgraph
"""
-def generateSvg(item):
+def generateSvg(item, options={}):
global xmlHeader
try:
- node, defs = _generateItemSvg(item)
+ node, defs = _generateItemSvg(item, options=options)
finally:
## reset export mode for all items in the tree
if isinstance(item, QtGui.QGraphicsScene):
@@ -94,7 +96,7 @@ def generateSvg(item):
return xmlHeader + defsXml + node.toprettyxml(indent=' ') + "\n\n"
-def _generateItemSvg(item, nodes=None, root=None):
+def _generateItemSvg(item, nodes=None, root=None, options={}):
## This function is intended to work around some issues with Qt's SVG generator
## and SVG in general.
## 1) Qt SVG does not implement clipping paths. This is absurd.
@@ -209,18 +211,8 @@ def _generateItemSvg(item, nodes=None, root=None):
## Get rid of group transformation matrices by applying
## transformation to inner coordinates
- correctCoordinates(g1, defs, item)
+ correctCoordinates(g1, defs, item, options)
profiler('correct')
- ## make sure g1 has the transformation matrix
- #m = (tr.m11(), tr.m12(), tr.m21(), tr.m22(), tr.m31(), tr.m32())
- #g1.setAttribute('transform', "matrix(%f,%f,%f,%f,%f,%f)" % m)
-
- #print "=================",item,"====================="
- #print g1.toprettyxml(indent=" ", newl='')
-
- ## Inkscape does not support non-scaling-stroke (this is SVG 1.2, inkscape supports 1.1)
- ## So we need to correct anything attempting to use this.
- #correctStroke(g1, item, root)
## decide on a name for this item
baseName = item.__class__.__name__
@@ -239,15 +231,10 @@ def _generateItemSvg(item, nodes=None, root=None):
## See if this item clips its children
if int(item.flags() & item.ItemClipsChildrenToShape) > 0:
## Generate svg for just the path
- #if isinstance(root, QtGui.QGraphicsScene):
- #path = QtGui.QGraphicsPathItem(item.mapToScene(item.shape()))
- #else:
- #path = QtGui.QGraphicsPathItem(root.mapToParent(item.mapToItem(root, item.shape())))
path = QtGui.QGraphicsPathItem(item.mapToScene(item.shape()))
item.scene().addItem(path)
try:
- #pathNode = _generateItemSvg(path, root=root).getElementsByTagName('path')[0]
- pathNode = _generateItemSvg(path, root=root)[0].getElementsByTagName('path')[0]
+ pathNode = _generateItemSvg(path, root=root, options=options)[0].getElementsByTagName('path')[0]
# assume for this path is empty.. possibly problematic.
finally:
item.scene().removeItem(path)
@@ -267,17 +254,18 @@ def _generateItemSvg(item, nodes=None, root=None):
## Add all child items as sub-elements.
childs.sort(key=lambda c: c.zValue())
for ch in childs:
- csvg = _generateItemSvg(ch, nodes, root)
+ csvg = _generateItemSvg(ch, nodes, root, options=options)
if csvg is None:
continue
cg, cdefs = csvg
childGroup.appendChild(cg) ### this isn't quite right--some items draw below their parent (good enough for now)
defs.extend(cdefs)
-
+
profiler('children')
return g1, defs
-def correctCoordinates(node, defs, item):
+
+def correctCoordinates(node, defs, item, options):
# TODO: correct gradient coordinates inside defs
## Remove transformation matrices from tags by applying matrix to coordinates inside.
@@ -382,6 +370,10 @@ def correctCoordinates(node, defs, item):
w = ((s[0]-s[1])**2).sum()**0.5
ch.setAttribute('stroke-width', str(w))
+ # Remove non-scaling-stroke if requested
+ if options.get('scaling stroke') is True and ch.getAttribute('vector-effect') == 'non-scaling-stroke':
+ ch.removeAttribute('vector-effect')
+
if removeTransform:
grp.removeAttribute('transform')