[svg] avoid mutating the original library
This commit is contained in:
parent
5c1050b0ff
commit
27e1c23c33
1 changed files with 19 additions and 14 deletions
|
|
@ -45,6 +45,10 @@ def _make_svg_ids(names: Mapping[str, Pattern]) -> dict[str, str]:
|
||||||
return svg_ids
|
return svg_ids
|
||||||
|
|
||||||
|
|
||||||
|
def _detached_library(library: Mapping[str, Pattern]) -> dict[str, Pattern]:
|
||||||
|
return {name: pat.deepcopy() for name, pat in library.items()}
|
||||||
|
|
||||||
|
|
||||||
def writefile(
|
def writefile(
|
||||||
library: Mapping[str, Pattern],
|
library: Mapping[str, Pattern],
|
||||||
top: str,
|
top: str,
|
||||||
|
|
@ -53,13 +57,12 @@ def writefile(
|
||||||
annotate_ports: bool = False,
|
annotate_ports: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Write a Pattern to an SVG file, by first calling .polygonize() on it
|
Write a Pattern to an SVG file, by first calling .polygonize() on a detached
|
||||||
|
materialized copy
|
||||||
to change the shapes into polygons, and then writing patterns as SVG
|
to change the shapes into polygons, and then writing patterns as SVG
|
||||||
groups (<g>, inside <defs>), polygons as paths (<path>), and refs
|
groups (<g>, inside <defs>), polygons as paths (<path>), and refs
|
||||||
as <use> elements.
|
as <use> elements.
|
||||||
|
|
||||||
Note that this function modifies the Pattern.
|
|
||||||
|
|
||||||
If `custom_attributes` is `True`, a non-standard `pattern_layer` attribute
|
If `custom_attributes` is `True`, a non-standard `pattern_layer` attribute
|
||||||
is written to the relevant elements.
|
is written to the relevant elements.
|
||||||
|
|
||||||
|
|
@ -71,19 +74,21 @@ def writefile(
|
||||||
prior to calling this function.
|
prior to calling this function.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
pattern: Pattern to write to file. Modified by this function.
|
library: Mapping of pattern names to patterns.
|
||||||
|
top: Name of the top-level pattern to render.
|
||||||
filename: Filename to write to.
|
filename: Filename to write to.
|
||||||
custom_attributes: Whether to write non-standard `pattern_layer` attribute to the
|
custom_attributes: Whether to write non-standard `pattern_layer` attribute to the
|
||||||
SVG elements.
|
SVG elements.
|
||||||
annotate_ports: If True, draw an arrow for each port (similar to
|
annotate_ports: If True, draw an arrow for each port (similar to
|
||||||
`Pattern.visualize(..., ports=True)`).
|
`Pattern.visualize(..., ports=True)`).
|
||||||
"""
|
"""
|
||||||
pattern = library[top]
|
detached = _detached_library(library)
|
||||||
|
pattern = detached[top]
|
||||||
|
|
||||||
# Polygonize pattern
|
# Polygonize pattern
|
||||||
pattern.polygonize()
|
pattern.polygonize()
|
||||||
|
|
||||||
bounds = pattern.get_bounds(library=library)
|
bounds = pattern.get_bounds(library=detached)
|
||||||
if bounds is None:
|
if bounds is None:
|
||||||
bounds_min, bounds_max = numpy.array([[-1, -1], [1, 1]])
|
bounds_min, bounds_max = numpy.array([[-1, -1], [1, 1]])
|
||||||
logger.warning('Pattern had no bounds (empty?); setting arbitrary viewbox', stacklevel=1)
|
logger.warning('Pattern had no bounds (empty?); setting arbitrary viewbox', stacklevel=1)
|
||||||
|
|
@ -96,10 +101,10 @@ def writefile(
|
||||||
# Create file
|
# Create file
|
||||||
svg = svgwrite.Drawing(filename, profile='full', viewBox=viewbox_string,
|
svg = svgwrite.Drawing(filename, profile='full', viewBox=viewbox_string,
|
||||||
debug=(not custom_attributes))
|
debug=(not custom_attributes))
|
||||||
svg_ids = _make_svg_ids(library)
|
svg_ids = _make_svg_ids(detached)
|
||||||
|
|
||||||
# Now create a group for each pattern and add in any Boundary and Use elements
|
# Now create a group for each pattern and add in any Boundary and Use elements
|
||||||
for name, pat in library.items():
|
for name, pat in detached.items():
|
||||||
svg_group = svg.g(id=svg_ids[name], fill='blue', stroke='red')
|
svg_group = svg.g(id=svg_ids[name], fill='blue', stroke='red')
|
||||||
|
|
||||||
for layer, shapes in pat.shapes.items():
|
for layer, shapes in pat.shapes.items():
|
||||||
|
|
@ -158,21 +163,21 @@ def writefile_inverted(
|
||||||
box and drawing the polygons with reverse vertex order inside it, all within
|
box and drawing the polygons with reverse vertex order inside it, all within
|
||||||
one `<path>` element.
|
one `<path>` element.
|
||||||
|
|
||||||
Note that this function modifies the Pattern.
|
|
||||||
|
|
||||||
If you want pattern polygonized with non-default arguments, just call `pattern.polygonize()`
|
If you want pattern polygonized with non-default arguments, just call `pattern.polygonize()`
|
||||||
prior to calling this function.
|
prior to calling this function.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
pattern: Pattern to write to file. Modified by this function.
|
library: Mapping of pattern names to patterns.
|
||||||
|
top: Name of the top-level pattern to render.
|
||||||
filename: Filename to write to.
|
filename: Filename to write to.
|
||||||
"""
|
"""
|
||||||
pattern = library[top]
|
detached = _detached_library(library)
|
||||||
|
pattern = detached[top]
|
||||||
|
|
||||||
# Polygonize and flatten pattern
|
# Polygonize and flatten pattern
|
||||||
pattern.polygonize().flatten(library)
|
pattern.polygonize().flatten(detached)
|
||||||
|
|
||||||
bounds = pattern.get_bounds(library=library)
|
bounds = pattern.get_bounds(library=detached)
|
||||||
if bounds is None:
|
if bounds is None:
|
||||||
bounds_min, bounds_max = numpy.array([[-1, -1], [1, 1]])
|
bounds_min, bounds_max = numpy.array([[-1, -1], [1, 1]])
|
||||||
logger.warning('Pattern had no bounds (empty?); setting arbitrary viewbox', stacklevel=1)
|
logger.warning('Pattern had no bounds (empty?); setting arbitrary viewbox', stacklevel=1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue