SVG export fixes
This commit is contained in:
parent
49e2177623
commit
51e88bd436
@ -166,7 +166,7 @@ def buildFileList(examples, files=None):
|
|||||||
buildFileList(val, files)
|
buildFileList(val, files)
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def testFile(name, f, exe, lib, graphicsSystem):
|
def testFile(name, f, exe, lib, graphicsSystem=None):
|
||||||
global path
|
global path
|
||||||
fn = os.path.join(path,f)
|
fn = os.path.join(path,f)
|
||||||
#print "starting process: ", fn
|
#print "starting process: ", fn
|
||||||
@ -194,8 +194,8 @@ except:
|
|||||||
print("test failed")
|
print("test failed")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
""" % (import1, import2, graphicsSystem)
|
""" % (import1, graphicsSystem, import2)
|
||||||
#print code
|
|
||||||
process = subprocess.Popen(['exec %s -i' % (exe)], shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
process = subprocess.Popen(['exec %s -i' % (exe)], shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
process.stdin.write(code.encode('UTF-8'))
|
process.stdin.write(code.encode('UTF-8'))
|
||||||
#process.stdin.close()
|
#process.stdin.close()
|
||||||
|
@ -171,10 +171,10 @@ def _generateItemSvg(item, nodes=None, root=None):
|
|||||||
doc = xml.parseString(xmlStr)
|
doc = xml.parseString(xmlStr)
|
||||||
else:
|
else:
|
||||||
childs = item.childItems()
|
childs = item.childItems()
|
||||||
if isinstance(root, QtGui.QGraphicsScene):
|
tr = itemTransform(item, root)
|
||||||
tr = item.sceneTransform()
|
|
||||||
else:
|
#print item, pg.SRTTransform(tr)
|
||||||
tr = item.itemTransform(root)
|
|
||||||
#tr.translate(item.pos().x(), item.pos().y())
|
#tr.translate(item.pos().x(), item.pos().y())
|
||||||
#tr = tr * item.transform()
|
#tr = tr * item.transform()
|
||||||
arr = QtCore.QByteArray()
|
arr = QtCore.QByteArray()
|
||||||
@ -248,7 +248,7 @@ def _generateItemSvg(item, nodes=None, root=None):
|
|||||||
if isinstance(root, QtGui.QGraphicsScene):
|
if isinstance(root, QtGui.QGraphicsScene):
|
||||||
path = QtGui.QGraphicsPathItem(item.mapToScene(item.shape()))
|
path = QtGui.QGraphicsPathItem(item.mapToScene(item.shape()))
|
||||||
else:
|
else:
|
||||||
path = QtGui.QGraphicsPathItem(item.mapToItem(root, item.shape()))
|
path = QtGui.QGraphicsPathItem(root.mapToParent(item.mapToItem(root, item.shape())))
|
||||||
pathNode = _generateItemSvg(path, root=root).getElementsByTagName('path')[0]
|
pathNode = _generateItemSvg(path, root=root).getElementsByTagName('path')[0]
|
||||||
## and for the clipPath element
|
## and for the clipPath element
|
||||||
clip = name + '_clip'
|
clip = name + '_clip'
|
||||||
@ -306,6 +306,7 @@ def correctCoordinates(node, item):
|
|||||||
ch.setAttribute('d', newCoords)
|
ch.setAttribute('d', newCoords)
|
||||||
elif ch.tagName == 'text':
|
elif ch.tagName == 'text':
|
||||||
removeTransform = False
|
removeTransform = False
|
||||||
|
## leave text alone for now. Might need this later to correctly render text with outline.
|
||||||
#c = np.array([
|
#c = np.array([
|
||||||
#[float(ch.getAttribute('x')), float(ch.getAttribute('y'))],
|
#[float(ch.getAttribute('x')), float(ch.getAttribute('y'))],
|
||||||
#[float(ch.getAttribute('font-size')), 0],
|
#[float(ch.getAttribute('font-size')), 0],
|
||||||
@ -319,31 +320,81 @@ def correctCoordinates(node, item):
|
|||||||
else:
|
else:
|
||||||
print('warning: export not implemented for SVG tag %s (from item %s)' % (ch.tagName, item))
|
print('warning: export not implemented for SVG tag %s (from item %s)' % (ch.tagName, item))
|
||||||
|
|
||||||
|
## correct line widths if needed
|
||||||
|
if removeTransform and ch.getAttribute('vector-effect') != 'non-scaling-stroke':
|
||||||
|
w = float(grp.getAttribute('stroke-width'))
|
||||||
|
s = pg.transformCoordinates(tr, np.array([[w,0], [0,0]]), transpose=True)
|
||||||
|
w = ((s[0]-s[1])**2).sum()**0.5
|
||||||
|
ch.setAttribute('stroke-width', str(w))
|
||||||
|
|
||||||
if removeTransform:
|
if removeTransform:
|
||||||
grp.removeAttribute('transform')
|
grp.removeAttribute('transform')
|
||||||
|
|
||||||
|
|
||||||
def correctStroke(node, item, root, width=1):
|
def itemTransform(item, root):
|
||||||
#print "==============", item, node
|
## Return the transformation mapping item to root
|
||||||
if node.hasAttribute('stroke-width'):
|
## (actually to parent coordinate system of root)
|
||||||
width = float(node.getAttribute('stroke-width'))
|
|
||||||
if node.getAttribute('vector-effect') == 'non-scaling-stroke':
|
|
||||||
node.removeAttribute('vector-effect')
|
|
||||||
if isinstance(root, QtGui.QGraphicsScene):
|
|
||||||
w = item.mapFromScene(pg.Point(width,0))
|
|
||||||
o = item.mapFromScene(pg.Point(0,0))
|
|
||||||
else:
|
|
||||||
w = item.mapFromItem(root, pg.Point(width,0))
|
|
||||||
o = item.mapFromItem(root, pg.Point(0,0))
|
|
||||||
w = w-o
|
|
||||||
#print " ", w, o, w-o
|
|
||||||
w = (w.x()**2 + w.y()**2) ** 0.5
|
|
||||||
#print " ", w
|
|
||||||
node.setAttribute('stroke-width', str(w))
|
|
||||||
|
|
||||||
for ch in node.childNodes:
|
if item is root:
|
||||||
if isinstance(ch, xml.Element):
|
tr = QtGui.QTransform()
|
||||||
correctStroke(ch, item, root, width)
|
tr.translate(*item.pos())
|
||||||
|
tr = tr * item.transform()
|
||||||
|
return tr
|
||||||
|
|
||||||
|
|
||||||
|
if int(item.flags() & item.ItemIgnoresTransformations) > 0:
|
||||||
|
pos = item.pos()
|
||||||
|
parent = item.parentItem()
|
||||||
|
if parent is not None:
|
||||||
|
pos = itemTransform(parent, root).map(pos)
|
||||||
|
tr = QtGui.QTransform()
|
||||||
|
tr.translate(pos.x(), pos.y())
|
||||||
|
tr = item.transform() * tr
|
||||||
|
else:
|
||||||
|
## find next parent that is either the root item or
|
||||||
|
## an item that ignores its transformation
|
||||||
|
nextRoot = item
|
||||||
|
while True:
|
||||||
|
nextRoot = nextRoot.parentItem()
|
||||||
|
if nextRoot is None:
|
||||||
|
nextRoot = root
|
||||||
|
break
|
||||||
|
if nextRoot is root or int(nextRoot.flags() & nextRoot.ItemIgnoresTransformations) > 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
if isinstance(nextRoot, QtGui.QGraphicsScene):
|
||||||
|
tr = item.sceneTransform()
|
||||||
|
else:
|
||||||
|
tr = itemTransform(nextRoot, root) * item.itemTransform(nextRoot)[0]
|
||||||
|
#pos = QtGui.QTransform()
|
||||||
|
#pos.translate(root.pos().x(), root.pos().y())
|
||||||
|
#tr = pos * root.transform() * item.itemTransform(root)[0]
|
||||||
|
|
||||||
|
|
||||||
|
return tr
|
||||||
|
|
||||||
|
|
||||||
|
#def correctStroke(node, item, root, width=1):
|
||||||
|
##print "==============", item, node
|
||||||
|
#if node.hasAttribute('stroke-width'):
|
||||||
|
#width = float(node.getAttribute('stroke-width'))
|
||||||
|
#if node.getAttribute('vector-effect') == 'non-scaling-stroke':
|
||||||
|
#node.removeAttribute('vector-effect')
|
||||||
|
#if isinstance(root, QtGui.QGraphicsScene):
|
||||||
|
#w = item.mapFromScene(pg.Point(width,0))
|
||||||
|
#o = item.mapFromScene(pg.Point(0,0))
|
||||||
|
#else:
|
||||||
|
#w = item.mapFromItem(root, pg.Point(width,0))
|
||||||
|
#o = item.mapFromItem(root, pg.Point(0,0))
|
||||||
|
#w = w-o
|
||||||
|
##print " ", w, o, w-o
|
||||||
|
#w = (w.x()**2 + w.y()**2) ** 0.5
|
||||||
|
##print " ", w
|
||||||
|
#node.setAttribute('stroke-width', str(w))
|
||||||
|
|
||||||
|
#for ch in node.childNodes:
|
||||||
|
#if isinstance(ch, xml.Element):
|
||||||
|
#correctStroke(ch, item, root, width)
|
||||||
|
|
||||||
def cleanXml(node):
|
def cleanXml(node):
|
||||||
## remove extraneous text; let the xml library do the formatting.
|
## remove extraneous text; let the xml library do the formatting.
|
||||||
@ -359,4 +410,5 @@ def cleanXml(node):
|
|||||||
if hasElement:
|
if hasElement:
|
||||||
for ch in nonElement:
|
for ch in nonElement:
|
||||||
node.removeChild(ch)
|
node.removeChild(ch)
|
||||||
|
elif node.tagName == 'g': ## remove childless groups
|
||||||
|
node.parentNode.removeChild(node)
|
||||||
|
56
tests/svg.py
56
tests/svg.py
@ -6,26 +6,40 @@ import pyqtgraph as pg
|
|||||||
app = pg.mkQApp()
|
app = pg.mkQApp()
|
||||||
|
|
||||||
class SVGTest(test.TestCase):
|
class SVGTest(test.TestCase):
|
||||||
def test_plotscene(self):
|
#def test_plotscene(self):
|
||||||
pg.setConfigOption('foreground', (0,0,0))
|
#pg.setConfigOption('foreground', (0,0,0))
|
||||||
w = pg.GraphicsWindow()
|
#w = pg.GraphicsWindow()
|
||||||
w.show()
|
#w.show()
|
||||||
p1 = w.addPlot()
|
#p1 = w.addPlot()
|
||||||
p2 = w.addPlot()
|
#p2 = w.addPlot()
|
||||||
p1.plot([1,3,2,3,1,6,9,8,4,2,3,5,3], pen={'color':'k'})
|
#p1.plot([1,3,2,3,1,6,9,8,4,2,3,5,3], pen={'color':'k'})
|
||||||
p1.setXRange(0,5)
|
#p1.setXRange(0,5)
|
||||||
p2.plot([1,5,2,3,4,6,1,2,4,2,3,5,3], pen={'color':'k', 'cosmetic':False, 'width': 0.3})
|
#p2.plot([1,5,2,3,4,6,1,2,4,2,3,5,3], pen={'color':'k', 'cosmetic':False, 'width': 0.3})
|
||||||
app.processEvents()
|
#app.processEvents()
|
||||||
app.processEvents()
|
#app.processEvents()
|
||||||
|
|
||||||
ex = pg.exporters.SVGExporter.SVGExporter(w.scene())
|
#ex = pg.exporters.SVGExporter.SVGExporter(w.scene())
|
||||||
ex.export(fileName='test.svg')
|
#ex.export(fileName='test.svg')
|
||||||
|
|
||||||
#def test_simple(self):
|
|
||||||
|
def test_simple(self):
|
||||||
|
scene = pg.QtGui.QGraphicsScene()
|
||||||
#rect = pg.QtGui.QGraphicsRectItem(0, 0, 100, 100)
|
#rect = pg.QtGui.QGraphicsRectItem(0, 0, 100, 100)
|
||||||
|
#scene.addItem(rect)
|
||||||
|
#rect.setPos(20,20)
|
||||||
#rect.translate(50, 50)
|
#rect.translate(50, 50)
|
||||||
#rect.rotate(30)
|
#rect.rotate(30)
|
||||||
#grp = pg.ItemGroup()
|
#rect.scale(0.5, 0.5)
|
||||||
|
|
||||||
|
#rect1 = pg.QtGui.QGraphicsRectItem(0, 0, 100, 100)
|
||||||
|
#rect1.setParentItem(rect)
|
||||||
|
#rect1.setFlag(rect1.ItemIgnoresTransformations)
|
||||||
|
#rect1.setPos(20, 20)
|
||||||
|
#rect1.scale(2,2)
|
||||||
|
|
||||||
|
#el1 = pg.QtGui.QGraphicsEllipseItem(0, 0, 100, 100)
|
||||||
|
#el1.setParentItem(rect1)
|
||||||
|
##grp = pg.ItemGroup()
|
||||||
#grp.setParentItem(rect)
|
#grp.setParentItem(rect)
|
||||||
#grp.translate(200,0)
|
#grp.translate(200,0)
|
||||||
##grp.rotate(30)
|
##grp.rotate(30)
|
||||||
@ -40,8 +54,16 @@ class SVGTest(test.TestCase):
|
|||||||
#el.scale(0.5,2)
|
#el.scale(0.5,2)
|
||||||
#el.setParentItem(rect2)
|
#el.setParentItem(rect2)
|
||||||
|
|
||||||
#ex = pg.exporters.SVGExporter.SVGExporter(rect)
|
grp2 = pg.ItemGroup()
|
||||||
#ex.export(fileName='test.svg')
|
scene.addItem(grp2)
|
||||||
|
grp2.scale(100,100)
|
||||||
|
|
||||||
|
rect3 = pg.QtGui.QGraphicsRectItem(0,0,2,2)
|
||||||
|
rect3.setPen(pg.mkPen(width=1, cosmetic=False))
|
||||||
|
grp2.addItem(rect3)
|
||||||
|
|
||||||
|
ex = pg.exporters.SVGExporter.SVGExporter(scene)
|
||||||
|
ex.export(fileName='test.svg')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user