[svg] fix duplicate svg ids
This commit is contained in:
parent
28be89f047
commit
a82365ec8c
2 changed files with 47 additions and 3 deletions
|
|
@ -30,6 +30,21 @@ def _ref_to_svg_transform(ref) -> str:
|
|||
return f'matrix({a:g} {b:g} {c:g} {d:g} {e:g} {f:g})'
|
||||
|
||||
|
||||
def _make_svg_ids(names: Mapping[str, Pattern]) -> dict[str, str]:
|
||||
svg_ids: dict[str, str] = {}
|
||||
seen_ids: set[str] = set()
|
||||
for name in names:
|
||||
base_id = mangle_name(name)
|
||||
svg_id = base_id
|
||||
suffix = 1
|
||||
while svg_id in seen_ids:
|
||||
suffix += 1
|
||||
svg_id = f'{base_id}_{suffix}'
|
||||
seen_ids.add(svg_id)
|
||||
svg_ids[name] = svg_id
|
||||
return svg_ids
|
||||
|
||||
|
||||
def writefile(
|
||||
library: Mapping[str, Pattern],
|
||||
top: str,
|
||||
|
|
@ -81,10 +96,11 @@ def writefile(
|
|||
# Create file
|
||||
svg = svgwrite.Drawing(filename, profile='full', viewBox=viewbox_string,
|
||||
debug=(not custom_attributes))
|
||||
svg_ids = _make_svg_ids(library)
|
||||
|
||||
# Now create a group for each pattern and add in any Boundary and Use elements
|
||||
for name, pat in library.items():
|
||||
svg_group = svg.g(id=mangle_name(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 shape in shapes:
|
||||
|
|
@ -123,11 +139,11 @@ def writefile(
|
|||
continue
|
||||
for ref in refs:
|
||||
transform = _ref_to_svg_transform(ref)
|
||||
use = svg.use(href='#' + mangle_name(target), transform=transform)
|
||||
use = svg.use(href='#' + svg_ids[target], transform=transform)
|
||||
svg_group.add(use)
|
||||
|
||||
svg.defs.add(svg_group)
|
||||
svg.add(svg.use(href='#' + mangle_name(top)))
|
||||
svg.add(svg.use(href='#' + svg_ids[top]))
|
||||
svg.save()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,3 +68,31 @@ def test_svg_ref_mirroring_changes_affine_transform(tmp_path: Path) -> None:
|
|||
|
||||
assert_allclose(plain_transform, (0, 2, -2, 0, 3, 4), atol=1e-10)
|
||||
assert_allclose(mirrored_transform, (0, 2, 2, 0, 3, 4), atol=1e-10)
|
||||
|
||||
|
||||
def test_svg_uses_unique_ids_for_colliding_mangled_names(tmp_path: Path) -> None:
|
||||
lib = Library()
|
||||
first = Pattern()
|
||||
first.polygon("1", vertices=[[0, 0], [1, 0], [0, 1]])
|
||||
lib["a b"] = first
|
||||
|
||||
second = Pattern()
|
||||
second.polygon("1", vertices=[[0, 0], [2, 0], [0, 2]])
|
||||
lib["a-b"] = second
|
||||
|
||||
top = Pattern()
|
||||
top.ref("a b")
|
||||
top.ref("a-b", offset=(5, 0))
|
||||
lib["top"] = top
|
||||
|
||||
svg_path = tmp_path / "colliding_ids.svg"
|
||||
svg.writefile(lib, "top", str(svg_path))
|
||||
|
||||
root = ET.fromstring(svg_path.read_text())
|
||||
ids = [group.attrib["id"] for group in root.iter(f"{SVG_NS}g")]
|
||||
hrefs = [use.attrib[XLINK_HREF] for use in root.iter(f"{SVG_NS}use")]
|
||||
|
||||
assert ids.count("a_b") == 1
|
||||
assert len(set(ids)) == len(ids)
|
||||
assert "#a_b" in hrefs
|
||||
assert "#a_b_2" in hrefs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue