sharp icon indicating copy to clipboard operation
sharp copied to clipboard

SVG not hiding viewBox overflow in symbol reference

Open x-sheep opened this issue 3 years ago • 2 comments

I'm trying to make a server endpoint using Sharp that converts a given paper puzzle to PNG. The codebase generates SVGs, and uses a tileset for certain graphical elements. The tileset is a single image which is referenced by multiple symbol tags, each with a given viewBox for the desired tile. However, when referencing these symbol tags, it seems that the viewBox property is not preserved.

Input svg:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" font-size="10px" font-family="sans-serif" width="159" height="159" viewBox="-4.5 -4.5 159 159">
    <defs>
        <image id="img0" width="128" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABABAMAAAAg+GJMAAAAMFBMVEUAAACtAADv97X/a/f//wD///////////////////////////////////////////81EdaHAAAAEHRSTlP///8A////////////////8M8+MgAAAk5JREFUeJzF10FywyAMBdDvuNmTG2RyAmZ8gS56AG96/6sUAYIPCDduOymbJLb1ImSCFWy/HPgzAC2F9STgW8A/BXg0AIeAPGAyz/ilBbi0AH0E7HQ8GMDlDj73IOBmCwgnChAiGuDyuBPgrEkASws86CJcyMMtCEMKPsQTECKOAGMSiIc7QMoiYwv5PBpgmERMgAGJoNEDveBjAg0Q466fMsKbSw90ZfDpIAF3jZaxSw4VWNLF0BlCj7kCyKlPHqDllwHHU9SsFOjjYw5NvWMKi77RpNYMeM6/Eu18aTglFRjDG0G/eXS2BHgY8SKssxRqAgJ4M4FYya4KXXzKXk7b8UFYFTAEp8A0gQqYKeT8MKtAqkK7GscKCDBPgFMwgHzmYAY1Bes+VGAeH1J4AigJIC3oHbSwFTCW0gCAgetJYIcAlPk1HTsE1grA+DHFfPYDwCmAazPrUn9RnwG2uHcM92IHP5IOgfRUHID4S2sA1J0FDORiWkAZEXAfH2knTK8OJwDkwHd5ffspECLfQ6R7S87tPOB0M19+CJhL8e+Abini5YDvge3lAL4HXP5FOOs2vh4AWqBbCHsHxMXHAM4CQhBQW6YZ0HV10sIsBFD7Ud4099FqLEuH4hZqGxnIW2vYDrsaFiED3HaWKz0DuwFob9j1jBXgIpiAPORdLCafpf8VhyVIl8S7p9vpAHCjeQjgCcCMD+2ay/8SLKA2CrME5Ckf62ADmz4hp3+ycpvQ7TX8vjbTk2Gc5k/+u/h0RTu/g6snQlefk8A4/h/4AjUhvQ8aixc0AAAAAElFTkSuQmCC"/>
        <symbol id="symimg0" viewBox="0 0 64 64">
            <use xlink:href="#img0"/>
        </symbol>
        <symbol id="symimg1" viewBox="64 0 64 64">
            <use xlink:href="#img0"/>
        </symbol>
    </defs>
    <g shape-rendering="crispEdges">
        <path fill="white" stroke="none" d="M -0.5 -0.5 L 150.5 -0.5 150.5 150.5 -0.5 150.5 z"/>
    </g>
    <g shape-rendering="crispEdges"/>
    <g shape-rendering="crispEdges">
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 30 0 L 30 150" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 60 0 L 60 150" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 90 0 L 90 150" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 120 0 L 120 150" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 0 30 L 150 30" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 0 60 L 150 60" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 0 90 L 150 90" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
        <path fill="none" stroke="rgb(160, 160, 160)" d="M 0 120 L 150 120" stroke-width="1" stroke-dasharray="2.34375 2.8125 4.6875 2.8125 4.6875 2.8125 4.6875 2.8125 2.34375 0"/>
    </g>
    <g shape-rendering="crispEdges"/>
    <g shape-rendering="auto">
        <use x="0" y="0" width="30" height="30" xlink:href="#symimg0"/>
        <use x="60" y="0" width="30" height="30" xlink:href="#symimg1"/>
        <use x="90" y="0" width="30" height="30" xlink:href="#symimg1"/>
        <use x="120" y="0" width="30" height="30" xlink:href="#symimg1"/>
        <use x="30" y="30" width="30" height="30" xlink:href="#symimg0"/>
        <use x="60" y="30" width="30" height="30" xlink:href="#symimg0"/>
        <use x="120" y="30" width="30" height="30" xlink:href="#symimg0"/>
        <use x="30" y="60" width="30" height="30" xlink:href="#symimg1"/>
        <use x="90" y="60" width="30" height="30" xlink:href="#symimg1"/>
        <use x="0" y="90" width="30" height="30" xlink:href="#symimg0"/>
        <use x="60" y="90" width="30" height="30" xlink:href="#symimg0"/>
        <use x="90" y="90" width="30" height="30" xlink:href="#symimg1"/>
        <use x="0" y="120" width="30" height="30" xlink:href="#symimg0"/>
        <use x="30" y="120" width="30" height="30" xlink:href="#symimg0"/>
        <use x="60" y="120" width="30" height="30" xlink:href="#symimg1"/>
        <use x="120" y="120" width="30" height="30" xlink:href="#symimg0"/>
    </g>
    <g shape-rendering="auto">
        <path fill="black" stroke="none" d="M 34.5 30.125 A 4.5 4.5 0 1 1 34.5 30 z"/>
        <path fill="black" stroke="none" d="M 124.5 30.125 A 4.5 4.5 0 1 1 124.5 30 z"/>
        <path fill="black" stroke="none" d="M 34.5 120.125 A 4.5 4.5 0 1 1 34.5 120 z"/>
        <path fill="black" stroke="none" d="M 124.5 120.125 A 4.5 4.5 0 1 1 124.5 120 z"/>
    </g>
    <g shape-rendering="auto"/>
    <g shape-rendering="crispEdges"/>
    <g shape-rendering="crispEdges">
        <path fill="black" stroke="none" d="M -1.5 -1.5 L 1.5 -1.5 1.5 151.5 -1.5 151.5 z"/>
        <path fill="black" stroke="none" d="M 148.5 -1.5 L 151.5 -1.5 151.5 151.5 148.5 151.5 z"/>
        <path fill="black" stroke="none" d="M -1.5 -1.5 L 151.5 -1.5 151.5 1.5 -1.5 1.5 z"/>
        <path fill="black" stroke="none" d="M -1.5 148.5 L 151.5 148.5 151.5 151.5 -1.5 151.5 z"/>
    </g>
    <g shape-rendering="crispEdges"/>
</svg>

Expected output: expected

Actual output: actual

I'm using version 0.29.1. I've tested this on Windows, macOS and Linux (hosted on AWS Lambda).

x-sheep avatar Oct 06 '21 12:10 x-sheep

This is probably https://gitlab.gnome.org/GNOME/librsvg/-/issues/92

You should be able to workaround it by setting overflow manually:

- <use x="0" y="0" width="30" height="30" xlink:href="#symimg0"/>
+ <use x="0" y="0" width="30" height="30" xlink:href="#symimg0" overflow="hidden"/>

lovell avatar Oct 06 '21 13:10 lovell

Setting overflow="hidden" on every use element works.

x-sheep avatar Oct 06 '21 16:10 x-sheep

The upstream bug has been fixed and I've just checked the latest sharp v0.32.4 and this now works as expected.

lovell avatar Jul 22 '23 10:07 lovell