aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--imagemap.py19
-rw-r--r--tests/data/refs/imagemap__--maptype__HTML__oob__svg.out1
-rw-r--r--tests/data/svg/oob.svg5
-rw-r--r--tests/test_imagemap_comparison.py1
4 files changed, 24 insertions, 2 deletions
diff --git a/imagemap.py b/imagemap.py
index 30d0399..9a6b9c7 100644
--- a/imagemap.py
+++ b/imagemap.py
@@ -2,6 +2,7 @@ import inkex
from inkex import bezier
from inkex.command import inkscape_command
from inkex.localization import inkex_gettext as _
+from lxml.builder import E
# (X)HTML stuff:
ESCAPE=str.maketrans({'&':'&amp;','<':'&lt;','>':'&gt;'})
@@ -54,9 +55,10 @@ 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, and be visually unaffected by `fill-rule`.
+ # 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
links=[]
+ rects=[]
svgIDs=[i.get_id() for i in self.svg.iterdescendants('{http://www.w3.org/2000/svg}svg')]
for a in self.svg.iterdescendants('{http://www.w3.org/2000/svg}a'):
# save link attributes because they get removed when flattening
@@ -70,11 +72,24 @@ class ImageMap(inkex.OutputExtension):
style['stroke']='none'
style['fill']='#000'
links += [link]
+
+ # for clipping out-of-bounds elements
+ newid=self.svg.get_unique_id('intersect')
+ rect=E('{http://www.w3.org/2000/svg}rect',
+ x=str(viewBox[0]),
+ y=str(viewBox[1]),
+ width='100%',
+ height='100%',
+ style='fill:#000;stroke:none',
+ id=newid)
+ self.svg.append(rect)
+ rects+=[newid]
+
if len(links)==0:
raise inkex.AbortExtension(_("Image has no hyperlinks.\nAdd a hyperlink to an object with right-click → \"{}\".").format(_("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-selector:[style~="{CSS_LINK_INDEX}-{i}"];object-stroke-to-path;selection-ungroup;path-union;object-set-attribute:style,{CSS_LINK_INDEX}:" {CSS_LINK_INDEX}-{i} ";' for i in range(len(links))) \
+ +''.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)
newbytes=inkscape_command(self.svg,actions=command)
diff --git a/tests/data/refs/imagemap__--maptype__HTML__oob__svg.out b/tests/data/refs/imagemap__--maptype__HTML__oob__svg.out
new file mode 100644
index 0000000..e62f2b7
--- /dev/null
+++ b/tests/data/refs/imagemap__--maptype__HTML__oob__svg.out
@@ -0,0 +1 @@
+<area shape=poly coords=50,25,0,58,0,75,75,75 href=http://example.com>
diff --git a/tests/data/svg/oob.svg b/tests/data/svg/oob.svg
new file mode 100644
index 0000000..d46ee63
--- /dev/null
+++ b/tests/data/svg/oob.svg
@@ -0,0 +1,5 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <a xlink:href="http://example.com">
+ <polyline points="50,25 75,75 -25,75"/>
+ </a>
+</svg>
diff --git a/tests/test_imagemap_comparison.py b/tests/test_imagemap_comparison.py
index 445f981..994bc95 100644
--- a/tests/test_imagemap_comparison.py
+++ b/tests/test_imagemap_comparison.py
@@ -8,6 +8,7 @@ class ImageMapComparisonTest(ComparisonMixin, TestCase):
'svg/fillstroke.svg',
'svg/image.svg',
'svg/intersect.svg',
+ 'svg/oob.svg',
'svg/overlap.svg',
'svg/rounding.svg',
'svg/text.svg',