Center a character in svg - svg

I'm looking to produce a SVG file containing a single ascii character (say 'g' or 'W') from an arbitrary font centered within a 100 x 100 window. This is the closest I've got, but it's not quite right...
<?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 100 100"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<text x="50" y="50" font-size="100px"
text-anchor="middle" alignment-baseline="middle">g</text>
</svg>

SVG does not have automatic vertical layout capabilities on its own; you need something else to compute the height of the box, like JavaScript or…
Looks like you're embedding this inside of a web browser. If so, then you can use the automatic layout capabilities of HTML to do this for you, using <foreignObject> to embed an HTML snippet inside your SVG with display:table-cell; vertical-align:middle on the content.

There is no general way to centre text vertically in SVG.
The best you can to is work out where the baseline (<text> y attribute) should go for a particular font and group of characters (eg. all capitals).

Related

How to get rid of space before the first glyph in a SVG <text> element?

As you can see, the <text> element has the xattribute set to 0mm, yet there is a gap between the first glyph (H) and the edge of the document.
I don't know what this is caused by, but if I select just the first glyph:
The box does extend to x=0, as well as slightly beyond it - which makes me think that this is a limitation of (SVG's model of) variable-width text layout perhaps?
In either case, Inkscape does show the discrepancy in the positioning - it shows the text's X coordinate at 0.635mm:
Which, on the other hand, makes me think that it is possible to determine somehow.
Of course, if all that was needed was just to align the text, I could enter 0 in the dialog, but I am generating the SVG programatically, so I either need a way to say "align the first glyph at the very edge of the <text> box" or to calculate the gap (so it can be put in the dx attribute).
A minimal test-case which illustrates this is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="150mm" version="1.1" width="150mm" xmlns="http://www.w3.org/2000/svg"
xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<text x="0mm" y="75mm">Hello</text>
</svg>

SVG file not rendered

I have a trouble opening an SVG file under my machine Linux:
Gave this svg file:
<?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 width="1000px" height="707px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="MyPath" d="M 599,455 A 244,244 0 0,1 723,578" />
</defs>
<use xlink:href="#MyPath" fill="none" stroke="red" />
<text font-family="Verdana" font-size="42.5" fill="blue" >
<textPath xlink:href="#MyPath">
We go up, then we go down, then up again
</textPath>
</text>
</svg>
If I open it with firefox I can see it, but If I open it with gimp for example, I can see nothing.
What part of that file is creating this issue?
You are saying you see no error, so I don't know if this is right:
If you built GIMP yourself, our are not using the system's GIMP for some
reason, there is a chance the devel-files for the SVG libs
were not present when GIMP was built. If taht is the case, it won't be able to
read the SVG file itself.
You didn't say anything about error, so your might be another issue
(for example, the "Verdana" font might not be available for
GIMP, and it being replaced by a font with no visible glyphs)
In any case, the workaround would be to open the SVG file
in Inkscape, and export it as a raster PNG file for you
to work with it in GIMP>

Slanted text in SVG

In SVG is it possible to slant text to specified angle? This is of course different from rotate or putting on a path etc. One of things I want to do is to have a parallelogram with embedded text, with text tilted to the angle of the parallelogram.
Thank you.
Yes. You need to use the transform attribute.
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="100">
<text font-size="50" transform="translate(20,50) skewX(20)">Skewed text</text>
</svg>
Note that the transform applies to the text position (x and y attributes) as well. That's why I have used a translate to set the text position instead.

Why svg font is mirrored?

I have SVG file with element <path d="..." />
I'm converted that file to SVG font:
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<font id="somefont" horiz-adv-x="1000">
<font-face font-family="somefont" units-per-em="1000"/>
<glyph unicode="a" d="..."/>
</font>
</defs>
</svg>
Attribute d isn't changed, but font is mirrored by x axis.
Why that happens and how to fix it?
"Unlike standard graphics in SVG, where the initial coordinate system has the y-axis pointing downward (see The initial coordinate system), the design grid for SVG fonts, along with the initial coordinate system for the glyphs, has the y-axis pointing upward for consistency with accepted industry practice for many popular font formats."
Source: http://www.w3.org/TR/SVG/fonts.html
Can be converted to right glyphs with that script:
#!/usr/bin/env fontforge
Open("source.svg")
Generate("converted.svg")

How can I make text automatically scale down in an SVG?

I've got an SVG element that I've created with Inkscape. I then take that SVG and put in as part of an XSL-FO stylesheet that is used to transform XML data and then passed through the IBEX renderer to create a pdf (which is usually then printed). As an example, I have elements in the svg/stylesheet that look like this (extra noise due to the Inkscape export):
<text x="114" x="278.36218" id="id1" xml:space="preserve" style="big-long-style-string-from-inkscape">
<tspan x="114" y="278.36218" id="id2" style="style-string">
<xsl:value-of select="Alias1"/>
</tspan>
</text>
My problem lies in the fact that I don't know how big this text area is going to be. For this particular one, I've got an image to the right of the text in the SVG. However, if this string is the maximum allowed number of W's, it's way too long and goes over the image. What I'd like (in a perfect world) is a way to tell it how many pixels wide I want the text block to be and then have it automatically make the text smaller until it fits in that area. If I can't do that, truncating the text would also work. As a last ditch resort, I'm going to use a fixed width font and do the string truncation myself in the XML generation, although that creates something both less usable and less pretty.
I've poked around the SVG documentation and looked into flowRegions a bit as well as paths, but neither seem to be be quite what I want (maybe they are though). If it helps, here's that style string that Inkscape generates:
"font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
Thanks in advance for the help.
You have text of arbitrary line length (in terms of characters) and you want to scale it to fit inside a fixed amount of space? The only way I can think of to rescale text to a fixed size is to place it inside an svg element and then scale the SVG to that size:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Resizing Text</title>
<defs>
<svg id="text-1" viewBox="0 0 350 20">
<text id="text-2" x="0" y="0" fill="#000" alignment-baseline="before-edge">It's the end of the world as we know it, and I feel fine!</text>
</svg>
</defs>
<rect x="500" y="100" width="200" height="40" fill="#eee" />
<use x="510" y="110" width="180" height="20" xlink:href="#text-1" />
</svg>
However, as seen above, the viewBox on the encapsulating svg element needs to be set to the width of the text, which you presumably don't know.
If you're referencing this SVG inside a user agent with scripting available (e.g. a web browser) then you could easily write a script to capture the width of the text or tspan element and set the viewBox accordingly.

Resources