Remove SVG and PS post processing code
Remove Extend class from svgutil
This commit is contained in:
parent
fddf78fcc3
commit
9e08691e15
|
@ -20,26 +20,6 @@ import tempfile
|
||||||
import os
|
import os
|
||||||
from boxes.drawing import SVGSurface, PSSurface, Context
|
from boxes.drawing import SVGSurface, PSSurface, Context
|
||||||
|
|
||||||
class PSFile:
|
|
||||||
def __init__(self, filename):
|
|
||||||
self.filename = filename
|
|
||||||
|
|
||||||
def adjustDocumentMedia(self):
|
|
||||||
return
|
|
||||||
with open(self.filename, "r+") as f:
|
|
||||||
s = f.read(1024)
|
|
||||||
m = re.search(r"%%BoundingBox: (\d+) (\d+) (\d+) (\d+)", s)
|
|
||||||
|
|
||||||
if not m:
|
|
||||||
raise ValueError("%%BoundingBox in Postscript file not found")
|
|
||||||
|
|
||||||
x1, y1, x2, y2 = m.groups()
|
|
||||||
m = re.search(r"%%DocumentMedia: \d+x\d+mm ((\d+) (\d+)) 0 \(", s)
|
|
||||||
f.seek(m.start(1))
|
|
||||||
media = "%i %i" % (int(x1) + int(x2), int(y1) + int(y2))
|
|
||||||
f.write(media + " " * (len(m.group(1)) - len(media)))
|
|
||||||
|
|
||||||
|
|
||||||
class Formats:
|
class Formats:
|
||||||
|
|
||||||
pstoedit = "/usr/bin/pstoedit"
|
pstoedit = "/usr/bin/pstoedit"
|
||||||
|
@ -101,13 +81,6 @@ class Formats:
|
||||||
|
|
||||||
def convert(self, filename, fmt, metadata=None):
|
def convert(self, filename, fmt, metadata=None):
|
||||||
|
|
||||||
if fmt in ['svg', 'svg_Ponoko']:
|
|
||||||
svg = svgutil.SVGFile(filename)
|
|
||||||
svg.fix(metadata)
|
|
||||||
else:
|
|
||||||
ps = PSFile(filename)
|
|
||||||
ps.adjustDocumentMedia()
|
|
||||||
|
|
||||||
if fmt not in self._BASE_FORMATS:
|
if fmt not in self._BASE_FORMATS:
|
||||||
fd, tmpfile = tempfile.mkstemp(dir=os.path.dirname(filename))
|
fd, tmpfile = tempfile.mkstemp(dir=os.path.dirname(filename))
|
||||||
cmd = [self.pstoedit] + self.formats[fmt] + [filename, tmpfile]
|
cmd = [self.pstoedit] + self.formats[fmt] + [filename, tmpfile]
|
||||||
|
|
198
boxes/svgutil.py
198
boxes/svgutil.py
|
@ -20,199 +20,6 @@ from xml.etree import cElementTree as ElementTree
|
||||||
ElementTree.register_namespace("","http://www.w3.org/2000/svg")
|
ElementTree.register_namespace("","http://www.w3.org/2000/svg")
|
||||||
ElementTree.register_namespace("xlink", "http://www.w3.org/1999/xlink")
|
ElementTree.register_namespace("xlink", "http://www.w3.org/1999/xlink")
|
||||||
|
|
||||||
class Extend:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.minx = None
|
|
||||||
self.maxx = None
|
|
||||||
self.miny = None
|
|
||||||
self.maxy = None
|
|
||||||
|
|
||||||
def __add__(self, v):
|
|
||||||
x, y = v
|
|
||||||
res = Extend()
|
|
||||||
if self.minx is not None:
|
|
||||||
res.minx = self.minx + x
|
|
||||||
if self.maxx is not None:
|
|
||||||
res.maxx = self.maxx + x
|
|
||||||
if self.miny is not None:
|
|
||||||
res.miny = self.miny + y
|
|
||||||
if self.maxy is not None:
|
|
||||||
res.maxy = self.maxy + y
|
|
||||||
return res
|
|
||||||
|
|
||||||
def addPoint(self, x, y):
|
|
||||||
if x is not None:
|
|
||||||
if self.minx is None or self.minx > x:
|
|
||||||
self.minx = x
|
|
||||||
if self.maxx is None or self.maxx < x:
|
|
||||||
self.maxx = x
|
|
||||||
if y is not None:
|
|
||||||
if self.miny is None or self.miny > y:
|
|
||||||
self.miny = y
|
|
||||||
if self.maxy is None or self.maxy < y:
|
|
||||||
self.maxy = y
|
|
||||||
|
|
||||||
def addExtend(self, extend, x, y):
|
|
||||||
extend = extend + (x, y)
|
|
||||||
self.addPoint(extend.minx, extend.miny)
|
|
||||||
self.addPoint(extend.maxx, extend.maxy)
|
|
||||||
|
|
||||||
class SVGFile(object):
|
|
||||||
pathre = re.compile(r"[MCL]? *((-?\d+(\.\d+)?) (-?\d+(\.\d+)?) *)+")
|
|
||||||
transformre = re.compile(r"matrix\(" + ",".join([r"(-?\d+(\.\d+)?)"] * 6) + "\)")
|
|
||||||
|
|
||||||
def __init__(self, filename):
|
|
||||||
self.filename = filename
|
|
||||||
self.minx = self.maxx = self.miny = self.maxy = None
|
|
||||||
self.tree = ElementTree.parse(filename)
|
|
||||||
self.symbol_extends = {}
|
|
||||||
|
|
||||||
def fix(self, metadata=None):
|
|
||||||
return
|
|
||||||
#print("Optimizations:",
|
|
||||||
self.optimize(self.tree.getroot())
|
|
||||||
self.getEnvelope()
|
|
||||||
self.moveOrigin()
|
|
||||||
self.addMetadata(metadata)
|
|
||||||
self.rewriteViewPort()
|
|
||||||
|
|
||||||
def getExtend(self, element, extend):
|
|
||||||
if element.tag.endswith("}path"):
|
|
||||||
minx = maxx = miny = maxy = None
|
|
||||||
m = self.transformre.match(element.attrib.get("transform", ""))
|
|
||||||
|
|
||||||
if m:
|
|
||||||
matrix = [float(m.group(i)) for i in range(1, 12, 2)]
|
|
||||||
else:
|
|
||||||
matrix = [1, 0,
|
|
||||||
0, 1,
|
|
||||||
0, 0]
|
|
||||||
|
|
||||||
for m in self.pathre.findall(element.attrib.get("d", "")):
|
|
||||||
x = float(m[1])
|
|
||||||
y = float(m[3])
|
|
||||||
tx = matrix[0] * x + matrix[2] * y + matrix[4]
|
|
||||||
ty = matrix[1] * x + matrix[3] * y + matrix[5]
|
|
||||||
|
|
||||||
extend.addPoint(tx, ty)
|
|
||||||
elif element.tag.endswith("}use"):
|
|
||||||
x, y = float(element.attrib["x"]), float(element.attrib["y"])
|
|
||||||
s = self.symbol_extends[element.attrib["{http://www.w3.org/1999/xlink}href"][1:]]
|
|
||||||
extend.addExtend(s, x, y)
|
|
||||||
|
|
||||||
for e in element:
|
|
||||||
if e.tag.endswith("}symbol"):
|
|
||||||
self.symbol_extends[e.attrib["id"]] = self.getExtend(e, Extend())
|
|
||||||
else:
|
|
||||||
self.getExtend(e, extend)
|
|
||||||
return extend
|
|
||||||
|
|
||||||
def getEnvelope(self):
|
|
||||||
self.tags = []
|
|
||||||
root = self.tree.getroot()
|
|
||||||
self.extend = self.getExtend(root, Extend())
|
|
||||||
|
|
||||||
|
|
||||||
def _moveElement(self, e, dx, dy):
|
|
||||||
if e.tag.endswith("}symbol"):
|
|
||||||
return
|
|
||||||
if e.tag.endswith("}path"):
|
|
||||||
minx = maxx = miny = maxy = None
|
|
||||||
m = self.transformre.match(e.attrib.get("transform", ""))
|
|
||||||
|
|
||||||
if m:
|
|
||||||
matrix = [float(m.group(i)) for i in range(1, 12, 2)]
|
|
||||||
else:
|
|
||||||
matrix = [1, 0,
|
|
||||||
0, 1,
|
|
||||||
0, 0]
|
|
||||||
matrix[4] += dx
|
|
||||||
matrix[5] += dy
|
|
||||||
e.attrib["transform"] = "matrix(%s)" % (",".join(("%.4f" % m for m in matrix)))
|
|
||||||
if e.tag.endswith("}use"):
|
|
||||||
e.attrib["x"] = "%.4f" % (float(e.attrib["x"])+dx)
|
|
||||||
e.attrib["y"] = "%.4f" % (float(e.attrib["y"])+dy)
|
|
||||||
|
|
||||||
for child in e:
|
|
||||||
self._moveElement(child, dx, dy)
|
|
||||||
|
|
||||||
def moveOrigin(self):
|
|
||||||
self._moveElement(self.tree.getroot(),
|
|
||||||
-self.extend.minx+10, -self.extend.miny+10)
|
|
||||||
self.extend.maxx -= self.extend.minx-20
|
|
||||||
self.extend.maxy -= self.extend.miny-20
|
|
||||||
self.extend.minx = self.extend.miny = 0.0
|
|
||||||
|
|
||||||
def rewriteViewPort(self):
|
|
||||||
"""
|
|
||||||
Modify SVG file to have the correct width, height and viewPort attributes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.extend.minx = self.extend.minx or 0
|
|
||||||
self.extend.miny = self.extend.miny or 0
|
|
||||||
self.extend.maxx = self.extend.maxx or (self.extend.minx + 10)
|
|
||||||
self.extend.maxy = self.extend.maxy or (self.extend.miny + 10)
|
|
||||||
|
|
||||||
if 0 <= self.extend.minx <= 50:
|
|
||||||
minx = 0
|
|
||||||
else:
|
|
||||||
minx = 10 * int(self.extend.minx // 10) - 10
|
|
||||||
|
|
||||||
maxx = 10 * int(self.extend.maxx // 10) + 10
|
|
||||||
miny = 10 * int(self.extend.miny // 10) - 10
|
|
||||||
maxy = 10 * int(self.extend.maxy // 10) + 10
|
|
||||||
|
|
||||||
root = self.tree.getroot()
|
|
||||||
root.set('width', "%imm" % (maxx-minx))
|
|
||||||
root.set('height', "%imm" % (maxy-miny))
|
|
||||||
root.set('viewBox', "%i %i %i %i" % (minx, miny, maxx - minx, maxy - miny))
|
|
||||||
|
|
||||||
self.tree.write(self.filename)
|
|
||||||
|
|
||||||
d = r"(\-?\d+(\.\d+)?)"
|
|
||||||
optimize_patterns = [
|
|
||||||
(re.compile(" " + d + " " + d + r" (M|L) \1 \3 "),
|
|
||||||
r" \1 \3 "), # remove useless moves
|
|
||||||
# compress L parts of paths into V and H
|
|
||||||
(re.compile(" " + d + " " + d + r" L " + d + r" \3 "),
|
|
||||||
r" \1 \3 H \5 "),
|
|
||||||
(re.compile(" " + d + " " + d + r" L \1 " + d + " "),
|
|
||||||
r" \1 \3 V \5 "),
|
|
||||||
(re.compile(r"H " + d + r" L \1 " + d + " "),
|
|
||||||
r"H \1 V \3 "),
|
|
||||||
(re.compile(r"V " + d + " L " + d + " \1 "),
|
|
||||||
r"V \1 H \3 "),
|
|
||||||
]
|
|
||||||
|
|
||||||
def optimize(self, element):
|
|
||||||
number = 0
|
|
||||||
if element.tag.endswith("}path"):
|
|
||||||
path = element.attrib.get("d", "")
|
|
||||||
while True:
|
|
||||||
old_number = number
|
|
||||||
for pattern, replacement in self.optimize_patterns:
|
|
||||||
path, n = pattern.subn(replacement, path)
|
|
||||||
number += n
|
|
||||||
if number == old_number:
|
|
||||||
break
|
|
||||||
element.attrib["d"] = path
|
|
||||||
for e in element:
|
|
||||||
number += self.optimize(e)
|
|
||||||
return number
|
|
||||||
|
|
||||||
def _addTag(self, parent, tag, text, first=False):
|
|
||||||
if first:
|
|
||||||
t = ElementTree.Element(tag)
|
|
||||||
else:
|
|
||||||
t = ElementTree.SubElement(parent, tag)
|
|
||||||
t.text = text
|
|
||||||
t.tail = '\n'
|
|
||||||
if first:
|
|
||||||
parent.insert(0, t)
|
|
||||||
return t
|
|
||||||
|
|
||||||
|
|
||||||
unit2mm = {"mm" : 1.0,
|
unit2mm = {"mm" : 1.0,
|
||||||
"cm" : 10.0,
|
"cm" : 10.0,
|
||||||
"in" : 25.4,
|
"in" : 25.4,
|
||||||
|
@ -277,8 +84,3 @@ def svgMerge(box, inkscape, output):
|
||||||
|
|
||||||
# write the xml file
|
# write the xml file
|
||||||
ElementTree.ElementTree(dest_root).write(output, encoding='utf-8', xml_declaration=True)
|
ElementTree.ElementTree(dest_root).write(output, encoding='utf-8', xml_declaration=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
svg = SVGFile("examples/box.svg")
|
|
||||||
svg.getEnvelope()
|
|
||||||
svg.rewriteViewPort()
|
|
||||||
|
|
Loading…
Reference in New Issue