From 90246c78b9b0a5c736c574d7d95159fbfe74c597 Mon Sep 17 00:00:00 2001 From: Viatrix Date: Mon, 16 Mar 2026 17:48:48 -0700 Subject: Clip-paths now work! --- imagemap.py | 19 +++++++++++++++-- .../imagemap__--maptype__HTML__clip-path__svg.out | 3 +++ tests/data/svg/clip-path.svg | 24 ++++++++++++++++++++++ tests/test_imagemap_comparison.py | 1 + 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/data/refs/imagemap__--maptype__HTML__clip-path__svg.out create mode 100644 tests/data/svg/clip-path.svg diff --git a/imagemap.py b/imagemap.py index 3595323..9eb4132 100644 --- a/imagemap.py +++ b/imagemap.py @@ -62,8 +62,7 @@ class ImageMap(inkex.OutputExtension): hscale=self.svg.viewport_height/viewBox[3] if viewBox[3]!=0 else 1 # preprocess shapes for our purposes. - # after this, the shapes within the image must: look the same as before (barring colour/alpha), not be clones, have no stroke, not intersect, be visually unaffected by `fill-rule`, and not go out of bounds. - # TODO pay attention to clip-path + # after this, the shapes within the image must: look the same as before (barring colour/alpha), not be clones, have no stroke, not intersect, be visually unaffected by `fill-rule`, not be clipped, and not go out of bounds. links=[] rects=[] svgIDs=[i.get_id() for i in self.svg.iterdescendants('{http://www.w3.org/2000/svg}svg')] @@ -92,13 +91,29 @@ class ImageMap(inkex.OutputExtension): self.svg.append(rect) rects+=[newid] + #clip-paths + clipped=[] + clippedpaths=set() + for clippedEl in self.svg.iterdescendants(): + if not isinstance(clippedEl,inkex.BaseElement): continue + if clippedEl.cascaded_style().get('clip-path','none')=='none': continue + clipped.append([clippedEl.get_id(),0]) + for el in clippedEl.descendants(): + if not isinstance(el,inkex.ShapeElement) or isinstance(el,inkex.elements._groups.GroupBase): + clipped[-1][1]+=1 # can overshoot number of groups but works + continue + clippedpaths.add((el.get_id(),el.cascaded_style().get(CSS_LINK_INDEX))) + if len(links)==0: raise inkex.AbortExtension(_("Image has no hyperlinks.\nAdd a hyperlink to an object with right-click → \"{}\".").format(_i("Create Anchor (Hyperlink)"))) command=\ ''.join(f'select-clear;select-by-id:{i};selection-ungroup;' for i in reversed(svgIDs)) \ + +''.join(f'select-clear;select-by-id:{i[0]};{"selection-ungroup;"*i[1]}' for i in reversed(clipped) if i[1]>0) \ + +''.join(f'select-clear;select-by-id:{i[0]};object-release-clip;unselect-by-id:{i[0]};selection-set-backup;select-clear;select-by-id:{i[0]};object-stroke-to-path;selection-ungroup;path-union;object-set-attribute:id,{i[0]};selection-restore-backup;select-by-id:{i[0]};path-intersection;object-set-attribute:style,{CSS_LINK_INDEX}:{i[1]};' for i in clippedpaths) \ +''.join(f'select-clear;select-by-selector:[style~="{CSS_LINK_INDEX}-{i}"];object-stroke-to-path;selection-ungroup;path-union;select-by-id:{rects[i]};path-intersection;object-set-attribute:style,{CSS_LINK_INDEX}:" {CSS_LINK_INDEX}-{i} ";' for i in range(len(links))) \ +'select-all;path-flatten;path-split' # (we re-set the existing style attribute in case it got unset on non-paths) + from lxml import etree newbytes=inkscape_command(self.svg,actions=command) self.svg=self.load(newbytes).getroot() # preprocessing done, now for map generation diff --git a/tests/data/refs/imagemap__--maptype__HTML__clip-path__svg.out b/tests/data/refs/imagemap__--maptype__HTML__clip-path__svg.out new file mode 100644 index 0000000..4cd2339 --- /dev/null +++ b/tests/data/refs/imagemap__--maptype__HTML__clip-path__svg.out @@ -0,0 +1,3 @@ + + + diff --git a/tests/data/svg/clip-path.svg b/tests/data/svg/clip-path.svg new file mode 100644 index 0000000..c3b6f7d --- /dev/null +++ b/tests/data/svg/clip-path.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_imagemap_comparison.py b/tests/test_imagemap_comparison.py index 4b734b8..e5b59a1 100644 --- a/tests/test_imagemap_comparison.py +++ b/tests/test_imagemap_comparison.py @@ -5,6 +5,7 @@ class ImageMapComparisonTest(ComparisonMixin, TestCase): effect_class = ImageMap compare_file = ( 'svg/alt.svg', + 'svg/clip-path.svg', 'svg/enclave.svg', 'svg/fillstroke.svg', 'svg/group.svg', -- cgit