dompdf / php-svg-lib

SVG file parsing / rendering library
GNU Lesser General Public License v3.0
1.39k stars 77 forks source link

Incorrect fill of groups with clipPath #119

Open UCIS opened 3 months ago

UCIS commented 3 months ago

The changes to "Improve color parsing" appear to break the rendering of one of the SVG images included in a PDF document we use. Some groups that were invisible before the change (which seems correct and matching other applications) are rendered as a solid black rectangle after the change.

Reverting just the changes in src/Svg/DefaultStyle.php seems to fix the rendering issue.

I have isolated one of the problematic groups and removed everything else. The minimal test document is included below. This should render as a blank page, but instead renders a black box. In the original document there were filled paths inside the group which are now hidden by the filled group.

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Laag_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 595.3 841.9">
   <g>
      <defs>
         <rect id="SVGID_1_" x="56.7" y="56.7" width="122.4" height="46.2"/>
      </defs>
      <clipPath id="SVGID_2_">
         <use xlink:href="#SVGID_1_"  style="overflow:visible;"/>
      </clipPath>
   </g>
</svg>
bsweeney commented 3 months ago

Which version of SvgLib were you using before?

bsweeney commented 3 months ago

The real issue appears to be that clipPath is not handled correctly to begin with. A clipping path is intended for masking, the elements should not be rendered. SvgLib, however, does not treat it significantly different from a group (g), and so it renders the contained elements. The color parsing update only exposed the problem by making the contained elements visible where they previously were not.

The following renders the same regardless of whether you use the current version of SvgLib or a version prior to the implementation of the color parsing improvements (e.g., 0.4.1):

<svg
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  viewBox="0 0 200 200">
  <clipPath id="cut-off-bottom">
    <rect x="0" y="0" width="200" height="100" fill="red" />
  </clipPath>

  <circle cx="100" cy="100" r="100" clip-path="url(#cut-off-bottom)" fill="black" />
</svg>

Until SvgLib correctly handles the clipPath element you'll need to exclude clipping paths from you SVG document or take steps to mitigate the issue. I recommend placing clipPath elements inside a defs element to ensure its contents are not rendered.

UCIS commented 3 months ago

Thanks for your quick response. We were using a pretty old version of DOMPDF (1.2.2) with SvgLib 0.4.1 before.

The clipPath did indeed seem to contribute to the issue. The original SVG file was pretty big and exported from another program so not trivial to modify, but after ungrouping everything and exporting an "optimized" SVG file via InkScape it appears to render correctly. This did indeed move all the clipPaths into a defs element.