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.
Related
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>
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).
Consider the following SVG:
<?xml version="1.0" standalone="no"?>
<svg width="600" height="600" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id="Pattern0" patternTransform="skewX(5)" x="0" y="0" width="0.1" height="0.042">
<line x1="0" x2="1200" y1="0" y2="0" stroke-dasharray="25,25" style="stroke:#000000;stroke-width:1" />
</pattern>
</defs>
<rect fill="url(#Pattern0)" width="600" height="600" style="stroke:#0000FF;stroke-width:1" />
</svg>
Here's the fiddle to see it in action.
I'm trying to stagger the dashed lines in this pattern by some offset. The example above is a horizontal line, but the real lines may be rotated to any angle. The offset should be defined in the same units as the dasharray.
Adding a patternTransform="translate(x)" to the pattern doesn't work -- it just offsets the position of the entire repeated pattern instead of translating each repeated line in a cumulative fashion. Same goes for adding transform="translate(x)" to the line.
Adding a patternTransform="skewX(x)" works for horizontal lines and patternTransform="skewY(x)" works for vertical ones, but it doesn't work right at all for lines at other angles. Also, skewX/skewY require an angle as the argument, and I really need to move the lines based on the same units as the dashArray.
EDIT: Without boring anyone with the gory details, my ultimate goal is to translate AutoCAD hatch patterns into SVG files that I can use as background images in HTML. To see a little about how these patterns work, please see some of the examples here:
AutoCAD 2010 User Documentation (Note the three links on the left -- overview, dashed lines, and multiple lines).
I would love to use an SVG pattern to do this, but it's looking more and more like I'll have to return to previous attempts of using a loop to create individual lines. I was trying to avoid this because frankly I've forgotten way too much high school trig and getting enough lines (at an arbitrary angles) to fill the canvas is eluding me.
There isn't a short-cut way to create a staggered pattern. You'll need to draw out a set of staggered lines yourself, up to the point where you can get the effect you want with a repeating (possibly skewed or rotated) rectangular grid.
To get the effect of two dashed lines, with the dashes offset to each other, your repeating tile needs to have two lines.
<?xml version="1.0" standalone="no"?>
<svg width="600" height="600" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id="Pattern0" patternUnits="userSpaceOnUse"
x="0" y="0" width="100%" height="8.4%"
style="stroke:#000000;stroke-width:1;
stroke-dasharray:25,25; " >
<line x1="0" x2="100%" y1="1%" y2="1%" />
<line x1="0" x2="100%" y1="5.2%" y2="5.2%"
style="stroke-dashoffset:25" />
</pattern>
</defs>
<rect fill="url(#Pattern0)" width="600" height="600"
style="stroke:#0000FF;stroke-width:1" />
</svg>
Explanation of the changes:
I've changed to userSpaceOnUse units to define the pattern tile. This ensures that percentages defined when drawing the pattern are interpretted the same way as percentages drawn when defining the size of the tile. (User space is default for patternContentUnits.) The rectangle in your sample was the same size as the user space, so it wasn't making a difference, but it does if you change the size of the rectangle.
If you really wanted the spacing of the lines to be proportional to the size of the rectangle being filled, this is a problem. You could change both patternUnits and patternContentUnits to objectBoundingBox (the default for patternUnits), but then you have to define all your stroke properties relative to the rectangle size as well.
I've doubled the height of the tile, so that it is equivalent to two of your original tiles. One tile now includes two horizontal lines.
I've offset the first line slightly so it doesn't get cut off by the edge of the tile (you were only getting a half-pixel stroke width displayed, and the difference becomes obvious if the second line isn't similarly clipped).
I've added the second line, with the dash pattern offset, at a vertical position that is half the tile height below the first line (1% + 8.4%/2 = 5.2%).
Like #Robert Longson, I'm not 100% certain I understand what you're asking, so if this isn't the effect you want please post a drawing of what you're trying to achieve.
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")
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.