sammycage / lunasvg

SVG rendering and manipulation library in C++
MIT License
906 stars 126 forks source link

href images with base64 encoded SVG data are not rendered #182

Closed CreatureSurvive closed 2 weeks ago

CreatureSurvive commented 1 month ago

I'm currently working on writing a wrapper for lunasvg in Swift for use on Apple platforms. One of my primary uses for this will be rendering badges from shields.io. I've managed to get everything working as far as rendering the bitmap data to native image layers. However, I noticed an issue with embedded SVGs wrapped in an image tag that is base64 encoded.

Image tags that are base64 encoded SVG are not handled. For example <image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,..."/> However, nested SVGs outside of an image tag are handled correctly. Would it be possible to decode the SVG within the image tag, and render it?

This is something readily reproducible in any shields.io badges that include a logo.

(lunasvg svg2png)

<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" width="114.25310813027257" height="20" role="img" aria-label="test: something">
    <title>test: something</title>
    <linearGradient id="s" x2="0" y2="100%">
        <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
        <stop offset="1" stop-opacity=".1"/>
    </linearGradient>
    <clipPath id="r">
        <rect width="114.25310813027257" height="20" rx="3" fill="#fff"/>
    </clipPath>
    <g clip-path="url(#r)">
        <rect width="47.253108130272565" height="20" fill="#555"/>
        <rect x="47.253108130272565" width="67" height="20" fill="#007ec6"/>
        <rect width="114.25310813027257" height="20" fill="url(#s)"/>
    </g>
    <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
        <image x="5" y="3" width="13.253108130272567" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPk1hc3RvZG9uPC90aXRsZT48cGF0aCBkPSJNMjMuMjY4IDUuMzEzYy0uMzUtMi41NzgtMi42MTctNC42MS01LjMwNC01LjAwNEMxNy41MS4yNDIgMTUuNzkyIDAgMTEuODEzIDBoLS4wM2MtMy45OCAwLTQuODM1LjI0Mi01LjI4OC4zMDlDMy44ODIuNjkyIDEuNDk2IDIuNTE4LjkxNyA1LjEyNy42NCA2LjQxMi42MSA3LjgzNy42NjEgOS4xNDNjLjA3NCAxLjg3NC4wODggMy43NDUuMjYgNS42MTEuMTE4IDEuMjQuMzI1IDIuNDcuNjIgMy42OC41NSAyLjIzNyAyLjc3NyA0LjA5OCA0Ljk2IDQuODU3IDIuMzM2Ljc5MiA0Ljg0OS45MjMgNy4yNTYuMzguMjY1LS4wNjEuNTI3LS4xMzIuNzg2LS4yMTMuNTg1LS4xODQgMS4yNy0uMzkgMS43NzQtLjc1M2EuMDU3LjA1NyAwIDAgMCAuMDIzLS4wNDN2LTEuODA5YS4wNTIuMDUyIDAgMCAwLS4wMi0uMDQxLjA1My4wNTMgMCAwIDAtLjA0Ni0uMDEgMjAuMjgyIDIwLjI4MiAwIDAgMS00LjcwOS41NDVjLTIuNzMgMC0zLjQ2My0xLjI4NC0zLjY3NC0xLjgxOGE1LjU5MyA1LjU5MyAwIDAgMS0uMzE5LTEuNDMzLjA1My4wNTMgMCAwIDEgLjA2Ni0uMDU0YzEuNTE3LjM2MyAzLjA3Mi41NDYgNC42MzIuNTQ2LjM3NiAwIC43NSAwIDEuMTI1LS4wMSAxLjU3LS4wNDQgMy4yMjQtLjEyNCA0Ljc2OC0uNDIyLjAzOC0uMDA4LjA3Ny0uMDE1LjExLS4wMjQgMi40MzUtLjQ2NCA0Ljc1My0xLjkyIDQuOTg5LTUuNjA0LjAwOC0uMTQ1LjAzLTEuNTIuMDMtMS42Ny4wMDItLjUxMi4xNjctMy42My0uMDI0LTUuNTQ1em0tMy43NDggOS4xOTVoLTIuNTYxVjguMjljMC0xLjMwOS0uNTUtMS45NzYtMS42Ny0xLjk3Ni0xLjIzIDAtMS44NDYuNzktMS44NDYgMi4zNXYzLjQwM2gtMi41NDZWOC42NjNjMC0xLjU2LS42MTctMi4zNS0xLjg0OC0yLjM1LTEuMTEyIDAtMS42NjguNjY4LTEuNjcgMS45Nzd2Ni4yMThINC44MjJWOC4xMDJjMC0xLjMxLjMzNy0yLjM1IDEuMDExLTMuMTIuNjk2LS43NyAxLjYwOC0xLjE2NCAyLjc0LTEuMTY0IDEuMzExIDAgMi4zMDIuNSAyLjk2MiAxLjQ5OGwuNjM4IDEuMDYuNjM4LTEuMDZjLjY2LS45OTkgMS42NS0xLjQ5OCAyLjk2LTEuNDk4IDEuMTMgMCAyLjA0My4zOTUgMi43NCAxLjE2NC42NzUuNzcgMS4wMTIgMS44MSAxLjAxMiAzLjEyeiIvPjwvc3ZnPg=="/>
        <text aria-hidden="true" x="327.5310813027256" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">test</text>
        <text x="327.5310813027256" y="140" transform="scale(.1)" fill="#fff" textLength="210">test</text>
        <text aria-hidden="true" x="797.5310813027256" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="570">something</text>
        <text x="797.5310813027256" y="140" transform="scale(.1)" fill="#fff" textLength="570">something</text>
    </g>
</svg>
sammycage commented 1 month ago

You’ve done a great job outlining the issue. Currently, embedded SVG images using base64 encoding within the <image> tag are not supported by lunasvg. However, this is a valuable feature, and it’s definitely something worth considering for future development. In the meantime, if possible, using direct SVG elements without embedding them as base64 might serve as a workaround.