Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVG conversion to PNG ignores <style> variables #3502

Open
1 task done
rsodre opened this issue Dec 21, 2022 · 2 comments
Open
1 task done

SVG conversion to PNG ignores <style> variables #3502

rsodre opened this issue Dec 21, 2022 · 2 comments

Comments

@rsodre
Copy link

rsodre commented Dec 21, 2022

Possible bug

SVG conversion to PNG ignores <style> variables.

This issue limits compatibility with several of the assets I am using, and with 100% that I generate.

Maybe... this could be because of libvips, which uses librsvg. Acccording to this post, they still do not support style variables:
https://gitlab.gnome.org/GNOME/librsvg/-/issues/459

Even if the issue is because of a dependent package, it is important to track it until it is supported and be transparent to developers that use style variables.

Are you using the latest version of sharp?

  • I am using the latest version of sharp as reported by npm view sharp dist-tags.latest.

What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?

  System:
    OS: macOS 11.7
    CPU: (4) x64 Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
    Memory: 6.26 GB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.14.0 - /usr/local/bin/node
    npm: 8.15.1 - /usr/local/bin/npm
  npmPackages:
    sharp: ^0.31.2 => 0.31.2 

What are the steps to reproduce?

  • Convert the attached sample SVG to PNG

What is the expected behaviour?

  • Output should have a blue background, as defined in the --Bg variable, but the background is black.

Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem

This is a nextjs api endpoint:

const sharp = require('sharp');
const sharpOptions = {
	compressionLevel: 0,
	quality: 100,
}

export default async function handler(request, response) {
	const svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="600" viewBox="0 0 20 20"><defs><style>:root{--Bg:#0000FF;}.Bg{fill:var(--Bg);}.Rect{fill:#00ff00;}</style></defs><g><rect class="Bg" x="0" y="0" width="20" height="20"/><rect class="Rect" x="5" y="5" width="10" height="10"/></g></svg>';
			
	const svgBuffer = Buffer.from(svg);
	const png = sharp(svgBuffer).png(sharpOptions);
	const pngData = await png.toBuffer();

	response.statusCode = 200;
	response.setHeader('Content-Type', 'image/png');
	response.setHeader('Cache-Control', 'public, max-age=0, must-revalidate');
	response.end(pngData);
}

Please provide sample image(s) that help explain this problem

sample
output_BAD

@rsodre rsodre added the triage label Dec 21, 2022
@rsodre
Copy link
Author

rsodre commented Dec 21, 2022

As a fallback, I'm converting all variables to their actual value. My simple assets use color codes only, so other cases may need a more refined approach.

// match all: --varName:#ff00ff;
const regexp = /(--)[a-zA-Z]+:#[a-fA-F0-9]+;/g;
const vars = [..._svg.matchAll(regexp)];
for (const v of vars) {
	const parts = v[0].split(':');
	const name = parts[0]; // --varName
	const value = parts[1].split(';')[0]; // #ff00ff
	svg = svg.replaceAll(`var(${name})`, value);
}
@lovell
Copy link
Owner

lovell commented Dec 21, 2022

Yes, please subscribe to https://gitlab.gnome.org/GNOME/librsvg/-/issues/459 for updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment