Why are there missing spaces in SVG text in some browsers? - svg

I'm drawing a graphic in CorelDRAW (2021) and then exporting it to SVG.
In CorelDRAW, one of the artistic text objects contains text in different font weights. For example:
Garfield sat on the mat
Problem: Some browsers, such as Chrome and Edge, display that text in the SVG as:
Garfieldsat on the mat
That is, with the bold "Garfield" abutting the normal "sat", with no space.
In other browsers, such as Firefox, the same SVG displays as expected, with a space.
Example SVG (exported from CorelDRAW: not a truly minimal example, but I've stripped some of the excess markup):
<?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">
<!-- Creator: CorelDRAW 2021.5 -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="3.44562in" height="0.247335in" version="1.1" viewBox="0 0 18928.2 1358.7">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#373435}
.fnt1 {font-weight:normal;font-size:1831.1px;font-family:'Arial'}
.fnt0 {font-weight:bold;font-size:1831.1px;font-family:'Arial'}
]]>
</style>
</defs>
<text x="-87.9" y="1334.9" class="fil0 fnt0">Garfield</text>
<text x="6831.7" y="1334.9" class="fil0 fnt1"> sat on the mat</text>
</svg>

Chrome and Edge, and possibly other browsers, ignore leading spaces inside the SVG <text> element.
Here's a snippet of the SVG:
<text ... class="fil4 fnt0">Garfield</text>
<text ... class="fil4 fnt1"> sat on the mat</text>
(where "..." indicates elided attributes)
Note:
CorelDRAW has split the original single text object into two SVG <text> elements. Understandable, because of the different font weights (.fnt0 is bold, .fnt1 is normal).
The content of the second <text> element begins with a space.
Workaround: In CorelDRAW, don't mix font weights in a single text object.
More generally, whatever application you use to create SVG: if you notice a missing space when the SVG is rendered (say, in a browser), check whether the content of the corresponding SVG <text> element begins with a leading space. If so, rework your artwork in the original application to avoid that SVG output.

Usually for html2pdf, in common with many apps, heavy weight texts tend to "stretch" into a following void, or in this case the leading space is not defined. One way to enforce whitespace is try in standard html see the enforced spacing in https://stackoverflow.com/a/74297349/10802527
<?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">
<!-- Creator: CorelDRAW 2021.5 -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="3.44562in" height="0.247335in" version="1.1" viewBox="0 0 18928.2 1358.7">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#373435}
.fnt1 {font-weight:normal;font-size:1831.1px;font-family:'Arial'}
.fnt0 {font-weight:bold;font-size:1831.1px;font-family:'Arial'}
]]>
</style>
</defs>
<text x="-87.9" y="1334.9" class="fil0 fnt0">Garfield</text>
<text x="6831.7" y="1334.9" class="fil0 fnt1"> sat on the mat</text>
</svg>

Related

ImageMagick SVG with Windows symbol font (private use unicode character)

I'm using MagickNet (ImageMagick for .NET) to read the SVG code below, which contains a valid character from the "Symbol" true type font on Windows. The character is UF0B7 (uniF0B7 in the cmap table of the symbol.ttf font). This is a filled circle. The image I get using ImageMagick contains a rectangle with F0B7 written inside.
Here is my SVG file containing this special character. It is inside the text XML element (you might see it as a small square on your browser):
<?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 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="main1" width="960" height="720">
<g transform="matrix(1.3333334 0 0 1.3333334 0 0)">
<path stroke="none" fill="#FFFFFF" fill-rule="evenodd" d="M0 0L720 0L720 540L0 540z" transform="matrix(1 0 0 1 0 0)" />
<text style="fill:#000000;font-family:Symbol;" font-size="32" transform="matrix(1 0 0 1 43.08661 129.5433)" fill-opacity="1" x="0.028347015" y="29.952" letter-spacing="-0.01"></text>
</g>
</svg>
Here is my C# code:
byte[] imageData = File.ReadAllBytes(#"F:\test.svg");
using MagickImage image = new MagickImage(imageData);
image.Write(#"F:\test.jpg");
Is there a way to make ImageMagick use the system's Symbol font with such private use characters (according to the unicode standard) ? This character and others of the same kind are often used by Powerpoint software for bullets. I need, in my own software, to convert pptx slides to svgs using available libraries, and then rework them, isolate paragraphs in separate SVGs, to produce slide animation. In order to convert the final SVGs to images, I could also use other libraries like SVG.Net, but this one has other problems too. Up to now, MagickNet is the most precise one, except for this problem.

Is there a blend mode to replace black and keep other colors (i.e. white)?

I want to create a dynamically colored map marker in flutter_svg
<?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">
<svg style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;" height="100%" version="1.1" viewBox="0 0 24 24" width="100%" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
<g transform="matrix(1,0,0,1,4,0)">
<path style="fill:rgb(0,0,0);" d="M8.25,0C3.689,0 0,3.756 0,8.4C0,14.7 8.25,24 8.25,24C8.25,24 16.5,14.7 16.5,8.4C16.5,3.756 12.811,0 8.25,0Z"/>
<path style="fill:rgb(255,255,255);" d="M8.25,11.4C6.624,11.4 5.304,10.056 5.304,8.4C5.304,6.744 6.624,5.4 8.25,5.4C9.876,5.4 11.196,6.744 11.196,8.4C11.196,10.056 9.876,11.4 8.25,11.4Z"/>
</g>
</svg>
which looks like this:
I am experimenting with Blend Modes.
If I use this:
SvgPicture.asset(
"assets/images/to_marker.svg",
package: "trufi_core",
color: const Color(0xff27ae60),
colorBlendMode: BlendMode.difference,
)
the white color becomes transparent:
Is there even a blend mode which just replaces black by the color, and leaves white intact or do I have to use some color replacing?
Is there another way to replace a color in flutter_svg, maybe with CSS?
By brute forcing (trying all the modes) I found out, that BlendMode.screen works for this case

custom embedded SVG glyphs not rendering

I'm trying to create my own SVG font but it's not rendering. Using code from Mozilla's example here https://developer.mozilla.org/en-US/docs/Web/SVG/Element/glyph I wrote this:
<?xml version="1.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" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="640" height="346" viewBox="0 0 640 346">
<defs>
<font id="arial-hollow" horiz-adv-x="640">
<font-face font-family="Arial-Hollow" font-weight="bold" font-style="normal" units-per-em="500" cap-height="300" x-height="200" ascent="350" descent="150" alphabetic="0" mathematical="175" ideographic="200" hanging="250">
<font-face-src>
<font-face-name name="Arial-Hollow"/>
</font-face-src>
</font-face>
<glyph unicode="y" d="m 290.15467,345.00314 c -0.99838,-0.61637 -1.69965,-2.23572 -1.69965,-3.92482 0,-2.50765 0.35204,-2.8755 2.75182,-2.8755 1.5135,0 3.00684,-0.25593 3.31854,-0.56873 0.31171,-0.3128 -1.14514,-4.69641 -3.23743,-9.74136 -2.09229,-5.04495 -3.80416,-9.63645 -3.80416,-10.20334 0,-0.62947 1.9525,-0.91602 5.01577,-0.7361 4.94555,0.29048 5.03101,0.34919 6.1032,4.19319 1.15832,4.15281 1.83946,3.86929 2.92681,-1.21831 0.6524,-3.05249 0.85066,-3.1676 5.45598,-3.1676 2.62843,0 4.77897,0.41075 4.77897,0.9128 0,1.98567 -8.87091,24.97605 -10.12123,26.23077 -1.72468,1.73076 -9.29262,2.4547 -11.48862,1.099 z m 8.59567,-2.67299 c 1.58402,-1.06141 2.89916,-3.88879 6.66531,-14.32958 3.3272,-9.22389 3.35387,-9.41498 1.27187,-9.11243 -1.65647,0.24074 -2.46706,1.49296 -3.66669,5.66456 -2.14643,7.46397 -4.05584,7.47746 -6.29846,0.0446 -1.50399,-4.98488 -2.11995,-5.88738 -4.01815,-5.88738 l -2.24187,0 3.36686,8.01125 c 4.23089,10.06712 4.30363,12.27085 0.45319,13.72934 -1.60253,0.60702 -2.91369,1.44611 -2.91369,1.86464 0,0.96151 5.95103,0.97365 7.38163,0.015 z">
</glyph>
</font>
</defs>
<text x="100" y="100" font-family="Arial-Hollow">
y u no render??
</text>
</svg>
https://codepen.io/anon/pen/YvdBzp
The Mozilla developer page you linked states right at the top that <glyph> is deprecated. In fact, the whole concept of a SVG font is no longer working in current browsers, with the exception of Safari.

SVG position from x="0" y="0"

I try to write a text element in an SVG from x="50%" y="0".
My text is not appears and I don't know why.
Here is my SVG
<?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">
<svg width="900px" height="706" viewBox="0 0 900 706" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
<text x="50%" y="0" text-anchor="middle" fill="#f00" text-anchor="middle" style="font-family: DINPro; font-size: 28px;">xxxx</text>
</svg>
I am not know the font-size it will be dynamically. If I am give y="20" then my text appears. But why is it?
As I read here, the 0 0 it the left top corner of the SVG.
Why is it? As you see, the the with and the height and the viewBox is the same.
Do I miss something?
Add an dominant-baseline attribute to your text element and set to hanging.
<?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">
<svg width="900px" height="706" viewBox="0 0 900 706" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
<text x="50%" y="0" fill="#f00" text-anchor="middle" style="font-family: DINPro; font-size: 28px;" dominant-baseline="hanging">xxxx</text>
</svg>
You have three options to change this:
dominant-baseline – used to determine or re-determine a scaled-baseline-table
alignment-baseline – specifies which baseline is to be aligned with the
corresponding baseline of the parent
baseline-shift – allows repositioning of the dominant-baseline relative to the dominant-baseline of the parent
See this post for more information about this: http://vanseodesign.com/web-design/svg-text-baseline-alignment/
Per the SVG specification
The Y coordinate of the bottom of a roman capital letter is usually zero. And the descenders on lowercase roman letters have negative coordinate values.
On a text element, y is the element bottom position.
In your case, the text printed outside of the viewbox.
Try to set your y to 20.

Why nest an <svg> element inside another <svg> element?

Why would a demo such as this: http://jsbin.com/ejorus/2/edit, have an <svg> element nested inside another <svg> element?
<svg class="graph">
<svg viewBox="0 0 1000 1000" preserveAspectRatio="none">
<g transform="translate(30,0)">
<!-- ... -->
</g>
</svg>
</svg>
The JS Bin is a modified version of the demo in this blog post: http://meloncholy.com/blog/making-responsive-svg-graphs/
Nesting SVG elements can be useful to group SVG shapes together, and
position them as a collection. All shapes nested inside an svg element
will be positioned (x, y) relative to the position (x, y) of its
enclosing svg element. By moving the x and y coordinates of the
enclosing svg element, you move all the nested shapes too.
Here is an example where two rectangles are nested inside two svg
elements. Except for the colors the two rectangles have the same
definitions for x, y, height, and width. The enclosing svg
elements have different x-values. Since the x-position of the
rectangles are interpreted relative to their enclosing svg elements
x-position, the two rectangles are displayed at different
x-positions.
- By Jakob Jenkov
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg x="10">
<rect x="10" y="10" height="100" width="100"
style="stroke:#ff0000; fill: #0000ff"/>
</svg>
<svg x="200">
<rect x="10" y="10" height="100" width="100"
style="stroke:#009900; fill: #00cc00"/>
</svg>
</svg>
Credits
You're right (as you say in Mr. Alien's answer) that both SVG elements have the same relative positions, and indeed the graph displays fine without the outer SVG.
The reason I added it is because the JavaScript (which I needed to stop the labels getting squished) uses the SVG element's transform matrix (caused by the applied viewBox attribute) to unscale the text.
Unfortunately the returned matrix doesn't take account of transformations applied to the SVG element itself, so I needed to get the transform matrix relative to an outer element that used the initial coordinate system instead. Hope that helps.
You can define a new viewport & viewbox. With this option, you can use relative positions like as css. For more information, you can see this online article.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Nested SVG</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<svg width="100%" height="100%">
<rect x="25%" y="25%" width="50%" height="50%" style="fill: dodgerblue;" />
<svg x="25%" y="25%" width="50%" height="50%">
<rect x="25%" y="25%" width="50%" height="50%" style="fill: tomato;" />
</svg>
</svg>
</body>
</html>
I am about to do this for an entirely different reason: website implementation efficiency.
I have several SVG files that I insert into my web page after downloading them via AJAX. I want to consolidate them into one file because that's better for downloading. I could do this with a text file and then insert the SVG text into a web page element's innerHTML property, but .svg files offer two additional advantages over .txt files:
1) The standard .svgz format allows you to store pre-zipped files on the web server, no need for mod_deflate. SVG files zip very efficiently, I'm seeing 70-85% compression.
2) The web browser parses the SVG outside of my javascript code, hopefully more efficiently. To insert the svg element into the HTML, I use the parent element's insertBefore or appendChild method instead of innerHTML.

Resources