Browser difference in displaying SVG RTL text with bidi-override and text-anchor="end" - svg

I'm noting a difference between browsers in displaying text forced right-to-left and also using text-anchor="end".
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" >
<text x="10" y="50" font-size="30" font-family="sans-serif" writing-mode="rl" direction="rtl" unicode-bidi="bidi-override" text-anchor="end" stroke="green" fill="green">
Force RTL
</text>
</svg>
In Chrome(v 27.0.1453.93 m) and I.E.(v 9.0.8112.16421), the text is shown as I would expect, with glyph stroking starting from the end point of the text and progressing to the left. With the example above, it is displayed in the upper left corner of the browser.
In Firefox (v 20.0.1) glyph stroking, with text-anchor="end", is starting from the start point of the text and the display is off the page. If I remove the text-anchor attribute, Firefox displays as Chrome and I.E. do with the text-anchor.
My questions are
Does anyone understand what's happening here? Or is this a FF bug?
If there's no work-around, how can I switch between user-agents in the SVG so for Firefox, I can avoid using the text-anchor?
Thanks very much

It's a bug in Firefox. Fortunately it will be fixed reasonably soon (not sure exactly when) as we're revamping/rewriting text support in SVG. If you want to see it working properly, download a Firefox nightly type about:config in the URL bar and set svg.text.css-frames.enabled to true. So be careful about user agent tests because this will get fixed before too long.

Related

Why does text appear in browsers but not appear in image viewers?

I am trying to render a chart but encounter a problem: The <text> elements appear in browsers (Chrome, Firefox) but not in traditional image viewers (Eyes of GNOME, GIMP, Inkscape).
Code
At first, I thought that it was because image viewers are incapable of rendering fonts, until I came across an asciinema's thumbnail, which is displayed perfectly by Eyes of GNOME:
Question: Why does this happen and how to fix this?
The reason is in nested SVGs:
<?xml version="1.0" encoding="utf-8" ?>
<svg ... >
<rect ... />
<svg ... >
<text ... >pdu --quantity=blksize tmp.sample</text>
</svg>
...
</svg>
Move your text elements to the root svg and you will be able to see them in the image viewers / editors (tested with Inkscape and GNOME image viewer)

SVG Mask is pixelated on retina displays

I have a simple cut-out rectangle with text in the middle.
<svg>
<defs>
<mask id="mytext">
<rect width='100%' height='100%' fill='white'/>
<text>Welcome</text>
</mask>
</defs>
<rect width='100%' height='100%' fill='blue' mask="url(#mytext)"/>
</svg>
However when viewing from a retina display the text edges become pixelated.
It does't happen if I only use text without masking it, but as soon the mask is used it breaks everything out.
EDIT: By Retina Display I mean, iOS and OSX both latest versions. All Browsers. I believe it might be a pixel density issue.
The interesting is while having
<text fill='url(#mypattern)'>Welcome</text>
The text is rendered sharply perfect. The problem lies only with masks being applied.
Here it is a jsfiddle sample (please make sure to test on your retina display enabled device).
And here is a screenshot displaying the difference on iPhone (note that the edges of the text below and how pixelated it looks).

Chrome SVG: Reusing animation element with fill="freeze" does not work as expected

I am supporting some old SVG graphics that we have in our application. I am having some issues with animating the fill color of a rectangle, and I am wondering if anyone else has seen the same issue.
We setup an animate element on the rec which ends up looking like this:
<svg id="svgEle" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect id="rect"
width="100" height="100"
style="fill:#008000; stroke:#000000;">
<animate id="animate" fill="freeze"
attributeName="fill" attributeType="CSS"
begin="indefinite" dur="1s"></animate>
</rect>
</svg>
And then, depending on values from a webservice result, we change the color of the rect and attempt to animate the color change. Currently it seems as if Chrome is the only native SVG render that supports the beginElement function. The animation works perfect on the first run, but all subsequent attempts to update the animation do not behave as expected. They always seem to revert to the first animation's fill color.
I have created the following example to show what I mean: http://jsfiddle.net/ssawchenko/ARXbs/
In Chrome the rectangle SHOULD cycle through all 4 colors via an animation when you click on the button, but it does not. In IE9 animation is not supported, so the fill color is just changed directly.
I am ok with IE9 simply setting the fill, however, in Chrome the colors are completely busted. Does anyone know if this is a bug, or if there is a work around?
Thanks!
This bug also exhibits in SVG Edit.
<animate attributeName="opacity" begin="indefinite" dur="1" fill="freeze">
</animate>
If you draw rectangles on top of each other you will see they seem semitransparent when they should be fully opaque. I've seen that Chrome Canary doesn't exhibit this behaviour, so it might be fixed in the next release.
I think this filed bug is related.

Using a clipping path with a positioned object in Webkit

Consider this simple SVG file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink"
viewBox="0 0 353 150">
<defs>
<clipPath id="walk0"><rect width="44" height="70" /></clipPath>
<image id="img" x:href="http://phrogz.net/tmp/walking-girl2.png"
width="353" height="70" />
</defs>
<use x:href="#img" clip-path="url(#walk0)" />
<use x:href="#img" y="80" clip-path="url(#walk0)" />
</svg>
The intent is to have two copies of the spritesheet clipped to the same region, with the second copy 80 units lower down. This works as intended in Firefox (the clipping path is applied before the y offset). In Chrome and Safari, however, the second image is not shown. (The clipping path is applied using global SVG unit space, and hence shows an empty area of the image.)
1) Which one of these browsers is correct?, or
2) What is the simplest, standards-based way to achieve this goal?
I can work around the problem by using wrapping <g> elements with transforms; this works in both Firefox and Chrome. But I'm hoping that there's a simpler way to achieve the same results in a correct and cross-browser manner.
FWIW, I also tried setting clipPathUnits="objectBoundingBox" on the clipPath, but this always produced an unclipped image. This was true even when I wrapped the <image> in a <symbol> with an explicit viewBox, height and width and referenced that with the <use> instead of the <image>. Either I don't understand how objectBoundingBox is supposed to work, or support for it is currently broken. It is certainly possible that the answer is the former instead of the latter. ;)
The easiest, standards-compliant way to differentiate between these is to use the SVG test suite provided by W3.org. This suite provides tests for use structs that you can play with to determine compliance, among many others.
The problem is how your y value is being parsed, which is causing your figure to translate out of the second frame, but only in some browsers. This is the correct, cross-browser way to specify the desired translation:
<use x:href="#img" clip-path="url(#walk0)"transform="translate(0,80)"/>
I would assume the dubious parsing with respect to the current clipping pane is a regression.

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