msspec_python3/msspec/msspecgui/scenegraph2d/xml/serializer.py

59 lines
1.7 KiB
Python
Raw Normal View History

2019-11-14 15:16:51 +01:00
# -*- coding: utf8 -*-
"""svg serialization"""
# serialization ##############################################################
_SVG_HEADER = """\
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
viewBox='%s %s %s %s'>"""
_SVG_FOOTER = """\
</svg>
"""
def _indent(s, level=1, tab="\t"):
"""indent blocks"""
indent = tab * level
return "\n".join("%s%s" % (indent, line) for line in s.split("\n"))
def serialize(*elems):
"""
serialization of elems into svg+xml.
:param elems: the elements that need to be output to svg
:type elems: scenegraph.Element
"""
defs = []
xml_elems = [_indent(elem._xml(defs)) for elem in elems]
xml_defs = set()
while defs:
elem = defs.pop()
xml_defs.add(_indent(elem._xml(defs), 2))
# compute the bounding box of the elements that need to be serialized
(x_min, y_min), (x_max, y_max) = (float("inf"), ) * 2, (float("-inf"), ) * 2
for elem in elems:
(ex_min, ey_min), (ex_max, ey_max) = elem.aabbox()
x_min, x_max = min(x_min, ex_min), max(x_max, ex_max)
y_min, y_max = min(y_min, ey_min), max(y_max, ey_max)
def xml_lines():
yield _SVG_HEADER % (x_min, y_min, x_max - x_min, y_max - y_min)
if xml_defs:
yield "\t<defs>"
for xml_def in xml_defs:
yield xml_def
yield "\t</defs>"
for xml_elem in xml_elems:
yield xml_elem
yield _SVG_FOOTER
return "\n".join(xml_lines())