SVG with 'svg' element embedded - svg

I've a problem with a complicated SVG image.
It works on Chrome and Firefox, but there is no way to convert it into a PNG image even using an online tool or GIMP and also with Inkscape.
I'm not sure where the problem is. Maybe because is it an image built with two other SVG images embedded.
Here is the SVG file.
To reproduce the problem: open the SVG file linked with a browser: it works.
Open it with GIMP and the image is empty.
An easier example with the same problem:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<!-- Some graphical objects to use -->
<defs>
<svg id="pippo" viewBox="0 0 10 10" >
<circle id="myCircle" cx="5" cy="5" r="5" />
</svg>
<linearGradient id="myGradient" gradientTransform="rotate(90)">
<stop offset="20%" stop-color="gold" />
<stop offset="90%" stop-color="red" />
</linearGradient>
</defs>
<!-- Using my graphical objects -->
<rect height="100%" width="100%" fill="#fc0" />
<use x="0" y="0" href="#pippo" fill="url('#myGradient')" />
</svg>

With SVG 1 you need to use the attribute xlink:href instead of href on the use element
<use x="0" y="0" xlink:href="#pippo" fill="url('#myGradient')" />
You will also need the xlink namespace on the <svg> element
<svg
viewBox="0 0 10 10"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
Since SVG 2, xlink: prefix is deprecated but SVG 2 is a W3C Candidate Recommendation and all its features are not yet supported by all browsers and editors.
Full SVG 1 example:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Some graphical objects to use -->
<defs>
<svg id="pippo" viewBox="0 0 10 10">
<circle id="myCircle" cx="5" cy="5" r="5" />
</svg>
<linearGradient id="myGradient" gradientTransform="rotate(90)">
<stop offset="20%" stop-color="gold" />
<stop offset="90%" stop-color="red" />
</linearGradient>
</defs>
<!-- using my graphical objects -->
<rect height="100%" width="100%" fill="#fc0" />
<use x="0" y="0" xlink:href="#pippo" fill="url('#myGradient')" />
</svg>

Workaround: SVG to PDF via the native browser feature "save to PDF" (print modal)
Since Firefox, Chromium, and WebKit have powerful built-in PDF export functionalities combined with way better SVG support than any "desktop" application, we can convert complex SVG images to a flattened, 'visually hardwired' vector file.
Ideal result
all vector data is retained (can also be opened in a vector application like Inkscape, Adobe Illustrator, Figma, etc.)
complexities like nested SVG images or <use> elements as well as transforms are repositioned to hardcoded vector x/y coordinates.
... but curb your enthusiasm: common issues
patterns and some complex gradients might be rasterized
you will lose structural data like layers, IDs and other editable features.
Manual SVG export optimisations
as #Yukulélé already pointed out: some syntax conventions and newer attributes might be too progressive
try to replace CSS-based styling with attributes – svgomg can be helpful
reusable elements defined in <defs> or as <symbols> might have quirky recursive dependencies
try to clean up unnecessary or invalid properties (e.g., hexadecimal RGBA) and fix incomplete SVG nestings (missing end tags)
document dimensions and aspect ratios can often be better retained (by a graphic application),
when the parent SVG element was added a viewBox and width/height attributes (at least in Adobe Illustrator)

Related

SVG patterns rasterised when printing to PDF

I'm trying to create a SVG file what when printed to PDF maintains all of its parts in vector. This file uses a pattern as a fill to a path, or in the example bellow as the fill to the rect element:
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
className="productWrapper"
>
<defs>
<pattern id="pattern" x="0" y="0" width="1" height="1">
<path
fill="#fcc"
d="[vector path here]"
/>
</pattern>
</defs>
<rect fill="url(#pattern)" stroke="black" width="200" height="200" />
</svg>
The issue I'm facing is that when printed to PDF the rect element or any path at the top level of the SVG file stays vector, but all vector content inside the pattern is rasterized.
A very minimal example of this can be found here:
https://6j8953j8rn.codesandbox.io/
Any way to get the SVG to render in vector when printing to PDF?
One tool that kept vector info after converting from SVG (including <pattern>) to PDF (I used it as CLI) is https://github.com/typst/svg2pdf
Some online converters also could do it while the most of other tools I tried make content inside <pattern> raster.

PNG inside SVG - not working in Firefox

I am trying to place a PNG image directly into the SVG file (using Base64). Here is a demo:
https://jsfiddle.net/bL11Lp8d/
<use href="#img1" transform="matrix(20,10,-5,20,50,50)" />
It works fine in Chrome, but does not work in Firefox. Do you know what is the problem?
The image has no width and height attributes. Firefox still requires them.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500">
<defs>
<image id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" width="5" height="5" />
</defs>
<use href="#img1" transform="matrix(20,10,-5,20,50,50)" />
</svg>
SVG 1.1 says they are mandatory, The SVG 2 specification says optional.

SVG symbol with stroke has wrong size in Illustrator

I'm generating an SVG file on a website and it's supposed to be imported in Ilustrator. I use <symbol /> element to store a shape definition and I reference it with the <use /> element on the "sheet". Users are able to set size of the shape and it's really crucial that it's exactly the same size when imported to Adobe Illustrator. It works unless I add a stroke.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="SvgjsSvg1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="210mm" height="297mm" viewBox="0 0 210 297" viewbox="0 0 210 297">
<defs id="SvgjsDefs1001">
<symbol id="shape_id70" preserveAspectRatio="xMinYMin meet" viewBox="0 0 27.841039657592773 12.2083101272583">
<path id="SvgjsPath1030" d="M26.4405 13.067C25.685728 11.72066 22.49458 8.90142 20.73442 7.678030000000001C22.99088 7.6388854 23.85819 7.6146637 28.738950000000003 7.456081C26.298620000000003 6.628644 23.737080000000002 5.904501 21.418080000000003 4.973881C23.937200000000004 4.5081560000000005 26.519460000000002 4.085806000000001 28.376120000000004 3.7947010000000008C28.376120000000004 3.7946453179000006 19.370760000000004 2.7013810000000005 8.358420000000002 4.414499000000001L9.412540000000002 1.364679000000001L6.497860000000001 3.520859000000001L4.442800000000001 0.858699000000001L4.324531000000001 4.464059000000001L0.897911000000001 5.542179000000001L4.249861000000001 6.913239000000001L4.236664300000001 10.198599000000002L6.192894300000001 7.622079000000001L9.099554300000001 8.802649L8.143547300000002 6.432539C12.463087300000002 6.813516 22.5756473 8.818239 26.440547300000002 13.067009Z" fill="none"></path>
</symbol>
</defs>
<use id="SvgjsUse1034" xlink:href="#shape_id70" x="0" y="0" width="50"></use>
</svg>
This is fine in both browser and Illustrator. But when I add attributes stroke-width="0.1" stroke="#000". In Illustrator, the size of the shape changesto 48.951. It's still 50 in browser though. I tried to add these attributes to the <symbol />, <path /> and <use /> elements with the same result.
I know that the SVG standard doesn't have any attribute that would control how to render the stroke. I know there is a discussion about the stroke-alignment attribute for future versions of SVG. But browsers don't support that yet, and neither Adobe Illustrator.
So my question is: Is there any way how to adjust the SVG so that Illustrator would render the shape with the size that is set by the width attribute in the <use /> element regardless of the stroke settings
The width value on your <use> should be having no effect on your <symbol> because your symbol has no viewBox attribute. Without a viewBox, only the x and y attributes of the <use> will be doing anything.
Also, be aware that we've seen a few questions on S.O. in the past, complaining about bugs in Illustrator's SVG import filter. If <symbol> is working, then that's great. However, in general, you may find that keeping your SVG structure simple, and avoiding the more advanced SVG features, might be a good idea.

How to reuse <image> tags in SVG <defs>?

I have a situation where to save on memory and loading, I am trying to reuse a single <image> tag in an SVG, instead of referencing the same xlink:href in several <image> tags.
My research has shown that <use> is the tag to reference a defined object.
However, when I try to reference an image, particularly inside a pattern (which is what I am trying to do), I get nothing, where using an image tag works fine.
What am I doing wrong? Is this even possible? I tried searching, but could not find any examples of the <use> tag with an image, just rects, paths, groups, etc.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 1024 600" >
<style type="text/css">
.fillme{fill:url(#tsmall)}
</style>
<defs>
<image id="texture" xlink:href="texture.tiny.png" />
<pattern id="tsmall" patternUnits="userSpaceOnUse" width="486" height="402">
<use xlink:href="#texture" x="0" y="0" width="486" height="402" />
</pattern>
<pattern id="tlarge" patternUnits="userSpaceOnUse" width="972" height="804">
<use xlink:href="#texture" x="0" y="0" width="972" height="804" />
</pattern>
</defs>
<rect x="0" y="0" width="1024" height="600" class="fillme"/>
</svg>
SVG image elements must have width and height attributes, yours doesn't.
An image is a graphics element and if you point a <use> at a graphics element the <use> width and height are ignored per the SVG specification (since it's not a symbol or an svg element it falls into the Otherwise case in the specification)

Is it possible to mask an image with an inline svg drawn with a path?

I'm needing to mask an image with an SVG element. I have a very detailed inline SVG element on my page, that I would like to use as a mask for an image that will be loaded. My SVG is drawn with a <path>. I would like to something similar to this example http://jsfiddle.net/pjgalbraith/cnLHE/. *I do notice that this example does not work in Chrome or IE9 for me though, only FF.
This is my basic structure.
<div>
<svg width="500" height="500">
<mask id="myMask'>
<g>
<path/>
</g>
</mask>
</svg>
<img src="http://myImage.jpg" style="mask:url(#myMask);">
</div>
I've tried adding a <mask> tag inside the SVG wrapping the group <g>, that did not work.
This makes my SVG graphic completely transparent though, so I assume it's trying to work, and the SVG is acting as a mask, but the image is not masked at all, just overlays the position. Does the <img> need to be inside of the <svg> or something like that?
Does anyone have SVG experience and would know how to do this? Every example I see uses simple rect or svg graphics to mask, but no paths. Maybe that's why? Thanks
You can get it to work pretty much everywhere if you put the image inside the svg, like this:
<svg width="220" height="220">
<mask maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox" id="m1">
<linearGradient id="g" gradientUnits="objectBoundingBox" y2="0.5" x2="1" y1="0.5" x1="0">
<stop stop-color="white" offset="0"/>
<stop stop-color="white" stop-opacity="0" offset="1"/>
</linearGradient>
<rect id="svg_1" height="1" width="1" y="0" x="0" stroke-width="0" fill="url(#g)"/>
</mask>
<image xlink:href="http://upload.wikimedia.org/wikipedia/en/thumb/0/08/DioHolyDiver.jpg/220px-DioHolyDiver.jpg" width="100%" height="100%" class="target"/>
</svg>
Here's the updated fiddle showing this: http://jsfiddle.net/cnLHE/34/
To answer the question about having paths in a mask, that's just fine and is supported by all svg-capable browsers AFAIK.

Resources