py-pdf/fpdf2

SVG rendering

Closed this issue · 4 comments

I'm rendering a .svg image (attached). In 2.7.6 this worked fine, in 2.7.7 it broke and in 2.7.8 the result is incorrect.

Version 2.7.6:
Renders OK:
image

Version 2.7.7:
Fails with

  File "C:\python\venvs\work11\Lib\site-packages\fpdf\svg.py", line 870, in handle_defs
    self.build_clipping_path(child_, clip_id)
  File "C:\python\venvs\work11\Lib\site-packages\fpdf\svg.py", line 968, in build_clipping_path
    clipping_path_shape = getattr(ShapeBuilder, shape_tags[shape.tag])(shape, True)
                                                ~~~~~~~~~~^^^^^^^^^^^
KeyError: '{http://www.w3.org/2000/svg}path'

Version fpdf2-2.7.8 (including current master branch): Renders incorrectly
image

Minimal code

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()


fname = f"overflow1.svg"    # this is the .svg below
pdf.image(fname, w=pdf.epw )

pdf.output("report.pdf")

Environment
Please provide the following information: Windows 11, Python 3.11

Reference SVG:
overflow1

I don't know much about SVG but taking a quick look I believe the problem is the clipping path being painted.
Looking how ClippingPath() works setting paint_rule to PathPaintRule.DONT_PAINT at init, I tried doing the same for path and it seems to work.

    def build_clipping_path(self, shape, clip_id):
        if shape.tag in shape_tags:
            shape_builder = getattr(ShapeBuilder, shape_tags[shape.tag])
            clipping_path_shape = shape_builder(shape, True)
        elif shape.tag in xmlns_lookup("svg", "path"):
            clipping_path_shape = PaintedPath()
            apply_styles(clipping_path_shape, shape)
            clipping_path_shape.paint_rule = PathPaintRule.DONT_PAINT  # line added
            svg_path = shape.attrib.get("d")
            if svg_path is not None:
                svg_path_converter(clipping_path_shape, svg_path)
        else:
            LOGGER.warning(
                "Ignoring unsupported <clipPath> child tag: <%s> (contributions are welcome to add support for it)",
                without_ns(shape.tag),
            )
            return
        self.update_xref(clip_id, clipping_path_shape)

@Lucas-C can you please check if it makes sense?

hi @andersonhc , thank for looking into this. Do you have a fork/branch that I can check out to have a look?

Hey @RubendeBruin

Here is the branch I created:
https://github.com/andersonhc/fpdf2/tree/svg

Is it OK using your file on a unit test?
I will start a PR soon

Hi @andersonhc ,
"Is it OK using your file on a unit test?": Yes
FYI: it is the measured waves somewhere in the north-sea.