I have some SVG icons I'm using which show up correctly in Firefox and Safari, like this:
...but they come out clipped at the edges like this in Chrome (both MacOS and Windows):
The source images are square (they have square viewBoxes, even if there's extra internal blank space), and my SVG markup treats them as square:
<image id="download" href="assets/download.svg" x="161.5" y="0.5" width="2.5" height="2.5"/>
<text id="low-battery-text" x="169" y="2.75" text-anchor="end"></text>
<image id="low-battery" href="assets/low-battery.svg" x="169.5" y="0.5" width="2.5" height="2.5"/>
If I make the specified height of these icons a bit taller then Chrome stops clipping them, but that changes the positioning and scaling of the images a bit too. And besides, it shouldn't be necessary.
I get the impression that Chrome is ignoring the viewBox values for the SVG images, it's finding the internal edges of the images, and scaling according to that (but that's just a guess). (No, that's not it.)
Here's what the SVG inside one of the SVG files looks like:
<?xml version="1.0" encoding="iso-8859-1"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<g>
<path fill="#0F0" d="M25.462,19.105v6.848H4.515v-6.848H0.489v8.861c0,1.111,0.9,2.012,2.016,2.012h24.967c1.115,0,2.016-0.9,2.016-2.012
v-8.861H25.462z"/>
<path fill="#0F0" d="M14.62,18.426l-5.764-6.965c0,0-0.877-0.828,0.074-0.828s3.248,0,3.248,0s0-0.557,0-1.416c0-2.449,0-6.906,0-8.723
c0,0-0.129-0.494,0.615-0.494c0.75,0,4.035,0,4.572,0c0.536,0,0.524,0.416,0.524,0.416c0,1.762,0,6.373,0,8.742
c0,0.768,0,1.266,0,1.266s1.842,0,2.998,0c1.154,0,0.285,0.867,0.285,0.867s-4.904,6.51-5.588,7.193
C15.092,18.979,14.62,18.426,14.62,18.426z"/>
</g>
</svg>
I can only find very different topics discussed when I try to Google for an answer to this problem, so I hoping someone who may have encountered a similar issue might have a suggestion for fixing it.
Update:
Interesting experiment - it isn't a good solution, but it's perhaps revealing of the underlying problem.
If I bypass using an SVG image file, and paste the content of the SVG file into my own SVG, the clipping problem goes away:
<svg viewBox="0 0 30 30" x="161.5" y="0.5" width="2.5" height="2.5">
<g>
<path fill="#0F0" d="M25.462,19.105v6.848H4.515v-6.848H0.489v8.861c0,1.111,0.9,2.012,2.016,2.012h24.967c1.115,0,2.016-0.9,2.016-2.012
v-8.861H25.462z"/>
<path fill="#0F0" d="M14.62,18.426l-5.764-6.965c0,0-0.877-0.828,0.074-0.828s3.248,0,3.248,0s0-0.557,0-1.416c0-2.449,0-6.906,0-8.723
c0,0-0.129-0.494,0.615-0.494c0.75,0,4.035,0,4.572,0c0.536,0,0.524,0.416,0.524,0.416c0,1.762,0,6.373,0,8.742
c0,0.768,0,1.266,0,1.266s1.842,0,2.998,0c1.154,0,0.285,0.867,0.285,0.867s-4.904,6.51-5.588,7.193
C15.092,18.979,14.62,18.426,14.62,18.426z"/>
</g>
</svg>
Is there some reason as to why Adobe Dreamweaver refuses to change the color of my SVG graphic when I copy and paste it into my HTML sheet?
It's the desired color when I create this in Adobe Illustrator, then I have it, then copy and paste the SVG code into my HTML sheet and it decides its going to be a different color....
Here is the SVG code:
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 842.89 125.04">
<defs>
<style>.cls-1{fill:#e0dddd;}</style>
</defs>
<path class="cls-1" d="M841.89,354.53H0V277.15c290.88,4.39,589-107.15,841.89,0Z" transform="translate(0.5 -229.99)"/>
</svg>
The result I get is as per the image.
I really do deal with some idiotic situations at times! In what universe is the hexadecimal color #E0DDDD a blue?
Basic needs:
I am working on a Qt application that replaces colors in an svg.
A nice implementation is to parse the svg xml, and replace the colors as found with a good color match.
Unfortunately, the application must run on a platform with very limited speed and memory, and loading the svg into the QSvgRenderer from an xml (or text string) is extremely slow.
So - my current implementation is to string replace the occurrences of hex known colors in the QByteArray loaded by the renderer.
A big limitation - if I want to replace a fill color with a pen color, and they match, I end up with a broken blob.
A second limitation: I can only have 2 defined colors, a fill and a pen.
What I would like:
I want to be able to create a "parameterized" svg, where I can replace "color1", "color2", "color3" defined at the top, with whatever colors the user chooses.
Note - the svg has to be loaded by the QSvgRenderer, so the parameter values can't be in an outside html or js.
The svg must be self-contained... with no outside caller requirement.
But I can replace in code the parameter value before load.
I just want to be able to replace parameters in a single location, instead of actual values inside the xml everywhere they occur.
What I have tried:
I have read in the svg documentation that it is possible to create parameterized values. This is from an example, as much as I understand it...
w3.org example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 110 40" width="100%" height="100%">
<title>Reusable Button</title>
<desc>Takes parameters from parent document's embedding element.</desc>
<defs>
<ref id="paramFill" param="color" default="blue"/>
<ref id="paramText" param="text-label">button</ref>
<ref id="paramStroke" param="outline" default="navy"/>
</defs>
<g>
<rect id="button_rect" x="5" y="5" width="100" height="30" rx="15" ry="15" fill="url(#paramFill)" stroke="url(#paramStroke)" />
<text id="button_label" x="55" y="30" text-anchor="middle" font-size="25" fill="black" font-family="Verdana">
<tref xlink:href="#paramText" />
</text>
</g>
</svg>
Unfortunately Qt doesn't load it and browsers show as error.
Second example: from S.O: Define color in SVG
<?xml version="1.0"?>
<svg width="704" height="702" xmlns="http://www.w3.org/2000/svg">
<style>
.myfill { fill:red }
</style>
<g fill="blue">
<rect x="0" y="0" width="704" height="702" class="myfill" />
</g>
</svg>
This loads in browser correctly as red, but Qt loads it with blue - so clearly it does not support the parameter value.
Is there any possible version of svg that uses parameters, that can be supported by Qt ?
Can somebody please help fix either of my examples or give a correct / better example ?
Thank you.
Qt version: 4.8
A long, long time ago, when some SVG renderers did not support style sheets, I solved this with XML entities:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY red "#ff0000">
]>
<svg width="704" height="702" xmlns="http://www.w3.org/2000/svg">
<g fill="blue">
<rect x="0" y="0" width="704" height="702" fill="&red;" />
</g>
</svg>
I am trying to make an svg that will be read in a QGraphicsSvgItem. I read some documentation, and it seems this is what I want:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!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="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100"
xml:space="preserve">
<rect fill="#437624" stroke="none" fill-opacity="1" x="0" y="0" width="100" height="100" />
<text y="50" transform="translate(50)">
<tspan x="0" text-anchor="middle">No</tspan>
<tspan x="0" text-anchor="middle" dy="15">Arrow</tspan>
</text>
</svg>
This creates a rectangle - and a multi-line text centered inside:
This is what it looks like in the browser.
In Qt though, when loaded in QGraphicsSvgItem, it looks like this:
I imagine that something is not supported by the Qt SVG renderer...
Even worse, setting the font size makes my Qt text completely disappear:
<text y="40" font-size="24" transform="translate(50)">
<tspan x="0" text-anchor="middle">No</tspan>
<tspan x="0" text-anchor="middle" dy="30">Arrow</tspan>
</text>
How can I make Qt get a multi-line centered text, as the first image, from the svg (what should I put in the SVG) ?
(Qt 4.7 to 5.5...)
Edit:
This worked (but still can't figure out how to do multi-line other than determining individual items)
<text x="0" y="40" font-size="24" transform="translate(50)" text-anchor="middle">No</text>
<text x="0" y="70" font-size="24" transform="translate(50)" text-anchor="middle">Arrow</text>
I find it puzzling that even copying svgs from tutorials, any svgs that contain tspan render correctly in browser but don't show in QGraphicsSvgItem - or perhaps they do but in a complete different location.
I believe the answer to your question is in the documentation for both QGraphicsSvg and the standard SVG Tiny 1.2.
Your library only support SVG Tiny and not the full SVG specification and while SVG Tiny does support "tspan", it also states this:
"positional attributes such as 'x', 'y', and 'rotate' are not available on 'tspan' in SVG Tiny 1.2."
See SVG Tiny 1.2: https://www.w3.org/TR/SVGTiny12/text.html#TSpanElement
See also Does QT support svg?
Background
I have a set of SVG icons that all have drop shadows. To make this work in Chrome, I can't just use filter:drop-shadow. I have to use filter:url(#drop-shadow), and define the drop shadow in my <defs> section.
I also have multiple instances of these icons on the page (they are filetype icons in a list of files), so I am using <use> to keep my page DRY.
Code
Exernal SVG File
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<filter id="drop-shadow">
<feGaussianBlur xmlns="http://www.w3.org/2000/svg" in="SourceAlpha" stdDeviation="4"/>
..... more filter lines, shortened for brevity
</filter>
</defs>
<symbol id="download-pdf">
<path filter="url(#drop-shadow)" d="" fill="">...</path>
</symbol>
<symbol id="download-zip">
..... another icon
</symbol>
... more icons
</svg>
Inline SVG on the Page
<svg>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="URL_OF_EXTERNAL_SVG"></use>
</svg>
See minimal working example here: http://h.andymercer.net/chrome-svg-bug/
Problem
The problem is that Chrome isn't finding the #drop-shadow link, and so is breaking the icons. Firefox, conversely, displays the icons perfectly.
Firefox:
Chrome:
If you notice, the Chrome screenshot DOES show some portion of the icon. It is displaying the portions that don't use the drop shadow filter.
I can't figure out why this is, because the drop shadow is in the <defs> that is on the same page as the <symbol>.
Question
Is there something I am missing, or is this a Chrome bug?
Edit
Per comments, I was asked for a MCVE. I hadn't done that because the problem inherently requires external URLs, which is typically frowned upon here. However, to demonstrate the problem, take a look at this:
http://h.andymercer.net/chrome-svg-bug/
In Firefox, you can see the icon. In Chrome, it is blank.
In Chrome, <defs> must be located inside the same <svg>.
In your case:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<filter id="drop-shadow">
<feGaussianBlur xmlns="http://www.w3.org/2000/svg" in="SourceAlpha" stdDeviation="4"/>
</filter>
</defs>
<symbol id="download-pdf">
<path filter="url(#drop-shadow)" d="" fill="">...</path>
</symbol>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#download-pdf"></use>
</svg>
Conforming to modern browsers capabilities, it's easier and cleaner to create different external svg files, one for each icon, then embed them using <object> or <img> tags.
<object> lets javascript access and modify SVG code via DOM, while <img> embed SVGs denying DOM access to them. So, in your case using <img> should be a better choice.