Making RSVG properly display text with a fractional size - librsvg

I'm using librsvg 2.39.0 to render the following SVG file to PNG. Inkscape and Firefox render it without any issues:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200" viewBox="0 0 20 10" version="1.1">
<rect width="100%" height="100%" fill="#ffffff" />
<text style="font-family: Helvetica;" stroke="none" x="7" y="5" font-size="1.6" fill="black">
This is some text
</text>
</svg>
However, it looks like, with librsvg, the text characters get aligned to the user coordinate grid, and the kerning is completely broken:
The issue can be replicated in the console by installing the librsvg2-tools package and running rsvg-convert < input.svg > output.png.
Is there something wrong with the file? The W3C validator shows it as valid. How do I teach librsvg to accept a fractional font-size in user coordinates?

This works fine now with rsvg-convert 2.40.20

Related

Embedded <image> not rendered when using SVG as background-image

I have an SVG image with an illustration of a cloud.
The cloud is going to be used in several weather icons. I have another SVG file that embeds the cloud illustration and adds another graphical element, a circle.
Now, this main SVG file shows up fine when I open it directly in the browser:
However, when I use the file as a background-image, the cloud is not rendered:
Here's a JSFiddle.
What the heck?
It shouldn't be a relative path issue because the image shows up fine when I call the main SVG in the browser (and I tried using an absolute path to no avail)
It's not a clipping issue - if you change the background-size property in the JSFiddle, you'll see the entire image area is rendered, just without the cloud.
The cloud was generated by Adobe Illustrator and not optimized yet, but seems to look ok.
This is the main SVG's markup:
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="-0" r="30" style="fill:red" />
<image x="12" y="12" width="20" height="40" xlink:href="elements/cloud.svg" />
</svg>
What am I doing wrong?
I've tested this in Safari 9.1.2 and latest Chrome on OS X, with the same result.
All SVGs that are inserted as images (through the img tag or as a background-image) cannot reference external files. So if you have an external CSS stylesheet, a custom font, or as in your case an external image, it won't work.
The solution would be to embed the image data within the xlink:href attribute:
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="0" cy="-0" r="30" style="fill:red" />
<image x="12" y="12" width="20" height="40" xlink:href="data:image/svg+xml,%0A%3Csvg%20id%3D%22Ebene_1%22%20data-name%3D%22Ebene%201%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20viewBox%3D%220%200%20284%20179%22%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill%3Anone%3B%7D.cls-2%7Bclip-path%3Aurl(%23clip-path)%3B%7D.cls-3%7Bfill%3A%23508f9e%3B%7D%3C%2Fstyle%3E%3CclipPath%20id%3D%22clip-path%22%20transform%3D%22translate(-278.44%20-208.09)%22%3E%3Crect%20class%3D%22cls-1%22%20x%3D%22279.44%22%20y%3D%22207.09%22%20width%3D%22284%22%20height%3D%22179%22%2F%3E%3C%2FclipPath%3E%3C%2Fdefs%3E%3Ctitle%3Ecloud%3C%2Ftitle%3E%3Cg%20class%3D%22cls-2%22%3E%3Cg%20id%3D%22TK6tin%22%3E%3Cpath%20class%3D%22cls-3%22%20d%3D%22M562.44%2C302.09c-4.19%2C9-7.71%2C18.44-13.39%2C26.63-9.1%2C13.12-21.26%2C22.65-35.52%2C30.06C497.65%2C367%2C481%2C372.3%2C463.34%2C373.68c-17%2C1.33-32.1-3.68-43.58-16.9-3-3.43-4.87-2.72-7.56-.06-6%2C5.92-11.9%2C11.83-19.1%2C16.52-9.22%2C6-19.37%2C9.45-29.58%2C13a4.17%2C4.17%2C0%2C0%2C0-1.09.89h-19c-7.91-2.63-15.56-5.83-21.8-11.53a10%2C10%2C0%2C0%2C0-6.55-2.63c-15.38-1.29-32.37-10.18-35.09-28.87-0.38-2.61.39-5.62-1.56-8v-5c2.09-3.79%2C1.2-8.2%2C2.85-12.26%2C2.87-7.07%2C8.91-9.62%2C15-11.45%2C5.41-1.62%2C9.87-3%2C11.87-9%2C3.9-11.71%2C12.39-17.5%2C24.66-17.08%2C5.43%2C0.18%2C7.92-1.18%2C10.39-6.77%2C4.51-10.24%2C12-18.52%2C21.06-25.77A171.48%2C171.48%2C0%2C0%2C1%2C398.75%2C227c20.39-9.63%2C41.2-17.45%2C64.13-17.83%2C1%2C0%2C2%2C.11%2C2.55-1.06h7c2.35%2C2.26%2C5.3.64%2C7.93%2C1.21%2C13%2C2.81%2C25.88%2C6.08%2C37.28%2C13.42%2C8.3%2C5.35%2C17.12%2C10.07%2C23.36%2C18a94%2C94%2C0%2C0%2C1%2C10.57%2C17.12c4.56%2C9.4%2C9.31%2C18.73%2C10.86%2C29.24v15ZM318.12%2C365.24c1.49%2C0.13%2C1.71%2C1.24%2C2.29%2C2a37.42%2C37.42%2C0%2C0%2C0%2C25.1%2C14.71c15%2C2%2C28.63-2.48%2C41.61-9.82C397.41%2C366.3%2C405%2C357.4%2C413.92%2C350c2.08-1.74%2C3.65-2.89%2C5.66-.08%2C12.35%2C17.29%2C30.17%2C21.51%2C49.68%2C19a127.56%2C127.56%2C0%2C0%2C0%2C54.87-21c16.7-11.17%2C26.73-27.07%2C33.68-45.37%2C0.68-1.8.5-3.59%2C0.63-5.41%2C1.16-16.58-6.55-30.39-13.88-44.3a39.91%2C39.91%2C0%2C0%2C0-7.73-10.86c-13.58-12.69-28.91-22-47.27-26.37-15.43-3.68-30.69-3.42-46.1-.72-15.69%2C2.75-30.25%2C8.85-44.45%2C15.69-23.79%2C11.46-45.28%2C25.58-54.66%2C52.22a3.16%2C3.16%2C0%2C0%2C1-3.27%2C2.38c-3.81.17-7.6%2C0.73-11.42%2C1-9.24.54-15.85%2C4.7-17.71%2C13.68-1.27%2C6.13-4.13%2C9-9.56%2C10.64-1.3.39-2.6%2C0.42-3.85%2C0.75-5.69%2C1.52-11.51%2C3.66-13.65%2C9.54-4.64%2C12.77-2.74%2C26.7%2C6.27%2C37.43%2C6%2C7.19%2C14.75%2C9.64%2C23.74%2C10.93%2C0.84%2C0.12%2C1.74%2C1.26%2C2.8.06C317.92%2C368%2C316.87%2C366.61%2C318.12%2C365.24Z%22%20transform%3D%22translate(-278.44%20-208.09)%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E" />
</svg>
Please follow the explanation in this link:
https://css-tricks.com/using-svg/
You need to enter the full svg code. you can get it from photoshop or online tools like this:
.background-img {
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='30'><circle cx='15' cy='15' r='10' /></svg>") no-repeat;
height: 30px;
width: 30px;
}

svg icons in IE9 do not display correctly

Our svg icons included using the img tag are getting incorrectly resized, cut off, or completely hidden when displayed in IE9.
The solution in https://gist.github.com/larrybotha/7881691 (setting the viewBox, removing width and height) does not help and neither does including the images as background.
When included using the tag, the SVGs display properly (but then they do not display in some modern browsers like chrome)
One of the icons we use has the following source:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generated by IcoMoon.io -->
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 640 640">
<metadata id="metadata167">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<path id="path161" fill="#c6c6c6" d="m227.88,640.44c-19.924,0-38.795-9.298-50.887-25.329l-163.69-216.1c-21.298-28.12-15.756-68.15,12.367-89.45,28.169-21.34,68.155-15.76,89.456,12.37l107.68,142.17,270.79-434.72c18.64-29.909,58.03-39.07,87.98-20.428,29.91,18.596,39.07,58.032,20.39,87.942l-319.85,513.45c-11.13,17.909-30.321,29.131-51.345,30.047-0.96187,0.0458-1.9237,0.0458-2.8856,0.0458z" stroke="#c6c6c6"/>
</svg>
Any idea on what we could do to make SVG render properly in IE9?
I can't be sure that this will answer your question without seeing the specific code you're having problems with, Jakub. But I always include the following attributes in every SVG element, as a minimum. This always gives me a good level of cross-browser consistency, back to IE9:
<svg height="40" version="1.1" viewBox="0 0 40 40" width="40" xmlns="http://www.w3.org/2000/svg">
If that doesn't help, could you share your code?
Wrapping the svg into a div and giving that a width seems to work fine for me.
http://codepen.io/anon/pen/qONXzz
.svg-test{
width: 50px;
}
It seems that the only method for embedding and resizing an external xml file that works correctly in all browsers is the one described in http://edutechwiki.unige.ch/en/Using_SVG_with_HTML5_tutorial
So instead of
<img src="./images/icons/icons-complete.svg" style="width: 11px;height:11px;"/>
you can use
<svg height="11" width="11"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="scale(0.0172)">
<image x="0" y="0" height="640" width="640" xlink:href="/images/icons/icons-complete.svg"/>
</g>
</svg>

SVG Namespace prefix xlink for href on textpath is not defined

So I'm trying to make a simple textpath .svg that would be a vertical line with some text. The problem I am getting is that the <defs> tags seem to throw everything off. I think it has something to do with my xlink:href but I can't seem to pin down what exactly.
<svg version="1.1"
baseProfile="full"
width="20" height="600"
xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="testPath" d="M 10 10 L 10 600 z"
stroke="black" stroke-width="3" />
</defs>
<text>
<textpath xlink:href="#testPath">
teeeest
</textpath>
</text>
</svg>
Any help would be appreciated.
Your sample will work fine inlined in a browser, because the browser knows about the xlink namespace.
If your SVG is an external file, then more strict XML parsing is performed and all namespaces used have to be defined.
All you need to do is add a definition for the xlink namespace to your outermost <svg> element.
<svg version="1.1"
baseProfile="full"
width="20" height="600"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
SVG is a case sensitive language so textpath actually needs to be written as textPath.
If you embed the SVG in html then you don't need namespaces as html doesn't support them (unlike xhtml). If you have your SVG standalone you'll also need xmlns:xlink="http://www.w3.org/1999/xlink" on the root <svg> element.

How to render svg elements with crisp edges while still keeping anti-aliasing?

Is there a way to render svg elements with crisp edges while still keeping anti-aliasing?
I'm creating a browser-based tool that works in modern browsers.
Playing around with the shape-rendering attribute doesn't give me the results I'm looking for.
I want my elements to have nice anti-aliasing so that the paths look smooth like below with shape-rendering: auto:
But I also want elements that don't require anti-aliasing, like the start box to look sharp and crisp, such as when rendered with shape-rendering: crispEdges:
Is this possible? Am I looking to have my cake and eat it too?
Perhaps you set shape-rendering property for root svg element.
You should set shape-rendering property for each shape elements, like this.
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" width="150" height="20" shape-rendering="crispEdges"
fill="none" stroke="black"/>
<path d="M80,30l100,100" shape-rendering="optimizeQuality"
stroke="black" stroke-width="5"/>
</svg>
If you want your boxes to appear sharp without any blurring due to antialiasing, and without using crispEdges mode, make sure the line edges are on pixel boundaries. So, for example, if your lines are an odd number of pixels wide, give them coordinates that are at 0.5 of a pixel.
<rect x="10.5" y="10.5" width="150" height="20"
stroke-width="1px" fill="none" stroke="black"/>
And on the boundary if the stroke width is even.
<rect x="10" y="10" width="150" height="20"
stroke-width="2px" fill="none" stroke="black"/>
Of course, this only really works if your SVG is being rendered at 1:1. That is, it's not being rescaled by the browser. And only for lines that are horizontal and vertical.
[I'm posting this as an answer rather than a comment, because I want to post a picture. Otherwise, this is a comment on the useful post by #defghi1977 . +1 to him, by the way.]
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="10" y="10" width="150" height="20" shape-rendering="crispEdges"
fill="none" stroke="black" />
<rect x="10" y="50" width="150" height="20" shape-rendering="auto"
fill="none" stroke="black" />
<path d="M40,30l100,100" shape-rendering="crispEdges"
stroke="black" stroke-width="5" />
<path d="M80,30l100,100" shape-rendering="auto"
stroke="black" stroke-width="5" />
</svg>
Produced
This was rendered by Firefox 38.0.5 .
In Internet Explorer 11, both shape-rendering setting produces the same result with anti-aliasing and not crisp.

Svg with image inside is not showing in safari

Inside my website, I am embeding a few svgs. They all seem to work just fine in Chrome, Firefox, IE(9+) and in Safari. Howvere as soon as there is image included in the svg, safari does not render the image.
Based on the previous similar topic I have tried the following:
SVG <image> elements not displaying in Safari - enclosing
<use>
tag like this <use></use>
SVG Image dosen't appear in Safari - I dont find this very usefull,cause this is deleting aprt of the svg.
Not able to render SVG image in Safari - Added
<meta http-equiv="Content-Type" content="application/xhtml+xml"> in header.
And beyond that, I dont really know what else to try. Maybe one more interesting thing to note is that inside my page, image is not displayed, but I can open svg file in safari(just the file) and it will be renderd correctly. Further more, after it's opened in the browser as a file, it renders inside the page as well. And I embed the svg to the page with img tag.
<img src="mysvg.svg" class="center-block"/>
This is my svg:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="328px" height="328px" viewBox="0 0 328 328" enable-background="new 0 0 328 328" xml:space="preserve">
<g>
<defs>
<polygon id="SVGID_1_" points="1.414,164.001 164,326.586 326.586,164.001 164,1.414 "/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" overflow="visible"></use>
</clipPath>
<g id="DSC_x5F_0112-2.psd" clip-path="url(#SVGID_2_)">
<g id="DSC_x5F_0112-2.psd_1_" enable-background="new ">
<image overflow="visible" width="338" height="532" id="DSC_x5F_0112-2" xlink:href="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABkAAD/4QNhaHR0cDov
.....SLKPF+7j+acOZPZjmsw4Q0f0L/6k1fu3WFvY/wDEB5o0d7H7/wD7SPFgPzVE54J9/wBI/qez5vei
r/fdeaS//9k=" transform="matrix(0.9818 0 0 0.9818 -2.7197 -11.064)">
</image>
</g>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M164,328.001L0,164.002L164,0.001l164,164.001L164,328.001z M1.414,164.002L164,326.587l162.586-162.585
L164,1.415L1.414,164.002z"/>
</g>
</svg>
I have reduced base64 image string, to shorten the code. Full svg can be found here.
UPDATE: Just to be clear, svg shows in the browser(safari) but image is missing (I can see just border).
It looks like this WebKit bug is responsible for the problem: https://bugs.webkit.org/show_bug.cgi?id=99677
The workaround we use in our application is to have a script which finds all img elements displaying SVG images and add hidden object elements loading the same SVGs (<object style="position: fixed; width: 0; height: 0;" data="image.svg" type="image/svg+xml"></object>).
The reason it works is that the object tag properly loads the embedded images into the image cache, so that they are visible within the SVGs loaded using the img tags.
The advantage of this approach is that the images are still displayed using the img tag, so that the workaround can be applied (and later removed cleanly when the browsers are eventually patched) without affecting the rest of the application/website.
The disadvantage is the creation of an extra object tag for each SVG image.
This solution works for me when displaying an embedded SVG image in Safari.
replace
<img src="image.svg">
with
<object data="image.svg" type="image/svg+xml"></object>
I ran into this problem where I was using Ajax to load the svg spritesheet onto the page. If I had a on the page before the spritesheet was loaded, it would fail and would not resolve once the spritesheet was avaialble. Any added to the dom after the spritesheet was loaded were fine. I had to delay putting the items in the dom until after the spritesheet finished loading.
This only affected IOS. All other browsers didn't care about the order.
It seems that answer from this question works: What could make Safari skip clip-path AND mask with SVG?. See instructions in link from answer.
You have to recreate your clip path to make it visible. And </clippath> tag is not pushed after </image> tag.
Here is the little changed code (link to my image inserted so you will have to change it):
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="328px" height="328px" viewBox="0 0 328 328" enable-background="new 0 0 328 328" xml:space="preserve" >
<g>
<clipPath id="SVGID_2_">
<!--use xlink:href="#SVGID_1_" overflow="visible"></use-->
<polygon id="SVGID_1_" points="1.414,164.001 164,326.586 326.586,164.001 164,1.414" />
</clipPath>
<defs>
<polygon id="SVGID_1_" points="1.414,164.001 164,326.586 326.586,164.001 164,1.414"/>
</defs>
</g>
<image clip-path='url(#SVGID_2_)' overflow="visible" width="338" height="532" id="DSC_x5F_0112-2" xlink:href="images/banner_03.jpg" transform="matrix(0.9818 0 0 0.9818 -2.7197 -11.064)">
</image>
<g>
<path fill="#FFFFFF" d="M164,328.001L0,164.002L164,0.001l164,164.001L164,328.001z M1.414,164.002L164,326.587l162.586-162.585
L164,1.415L1.414,164.002z"/>
</g>
</svg>
So Anto Jurković pointed out, there are some known issues with Safari and clipPath. What Safari likes is if you dont define polygon but put it straight in to clippPath. Also you must then group clipPath separately.
But I still could not get svg to render the image if I used img tag for svg - <img src="svg"/>. So at the end I have embeded it like this:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="328px" height="328px" viewBox="0 0 328 328" enable-background="new 0 0 328 328" xml:space="preserve">
<g>
<clipPath id="SVGID_2_">
<polygon id="SVGID_1_" points="1.414,164.001 164,326.586 326.586,164.001 164,1.414 "/>
</clipPath>
</g>
<image clip-path="url(#SVGID_2_)" overflow="visible" width="338" height="532" id="DSC_x5F_0112-2" xlink:href="data:image/jpeg;base64,/9j/.....r/fdeaS//9k=">
</image>
<g>
<path fill="#FFFFFF" d="M164,328.001L0,164.002L164,0.001l164,164.001L164,328.001z M1.414,164.002L164,326.587l162.586-162.585
L164,1.415L1.414,164.002z"/>
</g>
</svg>
I can confirm that this renders correctly in mobile safari(on ipad and iphone, windows safari and mac safari - latest versions).
So to sum it up...I have this svgs in separate html file and render them when needed.