dompdf / php-svg-lib

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

Changed the attribute merging logic of `<use/>` tags to better align with spec #87

Closed ssddanbrown closed 2 years ago

ssddanbrown commented 2 years ago

Change Detail

This PR changes the attribute merging logic of <use> tags to better align with the spec and other SVG renders.

Previously, <use> tag attributes would be directly merged to child items, with the tags of the use tag taking priority. This has been changed so that the child item attributes instead take priority. Relevant detail from MDN docs:

Most attributes on use do not override those already on the element referenced by use. [...] . Only the attributes x, y, width, height and href on the use element will override those set on the referenced element. However, any other attributes not set on the referenced element will be applied to the use element.

As per the above statement; width, height, x, y are handled different. These are essentially ignored during merge now. As far as I can see, we don't currently need to handle width and height (Apart from preventing application to child content), as these only are used when a new viewport is created which I don't think is yet an occurrence in this library (Would be during symbol/svg handling which are currently just treated as groups). Relevant detail from SVG spec:

The width and height properties on the ‘use’ element have no effect if the referenced element does not establish a new viewport.

For the x & y attributes, a surface translation was already being applied for these properties in the before function of the tag which aligns with the layout detail of the spec. Previously, these attributes would then be copied to children and cause a non-intended double offsetting on items that used x/y positioning attributes. This PR prevents this from occurring.

Related Issues

Testing Performed

Test PHP Script ```php loadFile($inputSvgFile); $surface = new SurfaceCpdf($doc); $doc->render($surface); $output = $surface->out(); file_put_contents($outputPdfFile, $output); ```

Notes