deeplook/svglib

Transform on clipPath does not work

Opened this issue · 2 comments

When clipPaths contain a path with a transform, the path is ignored and discarded with the error message Unsupported shape type Group for clipping.

The svg I am testing with is the following:

<svg namespace="http://www.w3.org/XML/1998/namespace" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <clipPath id="clip-1">
            <path transform="scale(0.5, 0.5)" d="M 50, 50 m -50, 0 a 50,50 0 1,0 100,0 a 50,50 0 1,0 -100,0"/>
        </clipPath>
    </defs>
    <g>
        <g clip-path="url(#clip-1)">
            <path d="M25,25h-50v-50h50V25z"/>
        </g>
    </g>
</svg>

I don't believe this was happening with earlier versions so I decided to do some digging and narrowed the problem down.

The error that is displayed starts here, when the detected shape from the node is neither a Path or a Rect despite the svg using a path element.

svglib/svglib/svglib.py

Lines 655 to 656 in 9a43d4f

elif shape:
logging.error("Unsupported shape type %s for clipping", shape.__class__.__name__)

This is caused from the convertShape function where, if there is a transform, then it will add the shape to a group and apply the transform to the group instead of the shape.

svglib/svglib/svglib.py

Lines 895 to 916 in 9a43d4f

class Svg2RlgShapeConverter(SvgShapeConverter):
"""Converter from SVG shapes to RLG (ReportLab Graphics) shapes."""
def convertShape(self, name, node, clipping=None):
method_name = f"convert{name.capitalize()}"
shape = getattr(self, method_name)(node)
if not shape:
return
if name not in ('path', 'polyline', 'text'):
# Only apply style where the convert method did not apply it.
self.applyStyleOnShape(shape, node)
transform = node.getAttribute("transform")
if not (transform or clipping):
return shape
else:
group = Group()
if transform:
self.applyTransformOnGroup(transform, group)
if clipping:
group.add(clipping)
group.add(shape)
return group

I did a quick test and applied the transform directly on the path element and everything seemed to work fine, however I'm not sure if there are any unintended side effects from doing it this way. Is this an intended feature or could I work on a patch to add an optional argument to apply the transformation directly for this use case?

Edit: I doubled checked the output and the transformed path was not placed or transformed correctly so additional work may be needed with this part.

Thank you for raising your first issue! Your help to improve svglib is much appreciated!

I don't remember if the fact to apply transforms only on shapes was a conveniency, or if it was required. Feel free to experiment and suggest changes if they are successful.