Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

should textPath elements parented to tspans or other textPaths render? #580

Open
heycam opened this issue Nov 8, 2018 · 11 comments
Open

Comments

@heycam
Copy link
Contributor

heycam commented Nov 8, 2018

No browser renders nested <textPath>s or those that are parented to a <tspan>, but the spec doesn't disallow this. I'm not sure if the text layout algorithm handles this (or what the behavior should be) if it is meant to be allowed.

@tabatkins
Copy link
Member

Note that, per the CSS #3302 issue, the resolution of this issue has an effect on how we should specify display:contents to work on tspan. I was under the impression that tspan was "transparent", like g, so display:contents could "just work", but it looks like in current impls a textSpan is valid as a child of text but invalid as a child of tspan.

I'm gradually figuring out what an appropriate layout model should be for these text elements, based on fooling around a bit with them, but yeah, the current spec does not describe this sufficiently.

Note that the layout model of some definitely valid content isn't even specified, and browsers vary significantly: http://software.hixie.ch/utilities/js/live-dom-viewer/saved/6361

Chrome lays out the "bar" horizontally, starting from the point where the path would have laid out its next character. Firefox instead totally ignores the textPath, rendering the "bar" in exactly the position it would be in were the textPath's text just rendered normally by the text.

In other words, it looks like, in Firefox, text calculates positions for all of its descendant characters, then a nested textPath can override those positions for characters inside of it. In Chrome, the characters are instead laid out char-by-char, so text lays out "foo", then textPath takes over, then text lays out "bar" based on that information.

Notably, the dy information is reflected in the positioning of "bar" in Firefox, but is not in Chrome; that's apparently not part of the positioning data the textPath passes back up to its parent text.


So what I'm saying is, the entire text rendering system is underspecified when you do anything remotely weird, and definitely needs fixing. Might as well figure out a model that works well for mixing these things while we're at it.

@heycam
Copy link
Contributor Author

heycam commented Nov 10, 2018

So what I'm saying is, the entire text rendering system is underspecified when you do anything remotely weird, and definitely needs fixing. Might as well figure out a model that works well for mixing these things while we're at it.

I spent a bunch of time a few years ago to figure this out and come up with as consistent a model as I could for how positioning attributes, <textPath>, and so on all interact in cases like this, resulting in the long text layout algorithm that's in the spec right now. It's certainly possible that what I wrote down is buggy or isn't Web compatible though.

@tabatkins
Copy link
Member

I couldn't immediately find a description of what happens in my earlier example, where there's more text continuing after the textpath. Is it obvious and I'm missing something (likely)?

@fsoder
Copy link

fsoder commented Nov 13, 2018

I think that would be covered by (prose):

After positioning all characters within the ‘textPath’, the current text position is set to the end point of the path, after adjusting for the ‘startOffset’ in the case of paths that are a single closed loop. In other words, text that follows a ‘textPath’ element (but is still inside a ‘text’ element) that does not have explicit positioning information (‘x’ and ‘y’ attributes) is positioned from the end of the path.

(https://svgwg.org/svg2-draft/text.html#TextLayoutPath just before 11.9)

And also, maybe more importantly, part of the text layout algorithm (https://svgwg.org/svg2-draft/text.html#TextLayoutAlgorithm) where I think the words to look for are "after path" (referenced near the end).

@tabatkins
Copy link
Member

Ah, cool, that's exactly it. (And, as it turns out, nobody follows that: Chrome starts up the rendering right where it would have rendered the next character on the path, rather than at the end of the path; Firefox starts up the rendering at an x position where it would have rendered the next character in the path, and at a y position where it would have been without any textPath at all.)


Okay, so we have an answer. textPath definitely should have been a top-level rendering element rather than a text child, but it still has a clear definition of how it should render in concert with text. The only missing piece would be how it renders with a tspan parent; I submit that the two logical possibilities are:

  1. It ignores the tspan parent, and continues to just render on the path
  2. It renders the same as if the tspan were moved into the textPath element instead.

I'm not sure if either one is more obviously "correct" than the other.

@fsoder
Copy link

fsoder commented Nov 13, 2018

Option (1) sounds about like what I would expect - a bit depending on what "ignores" is supposed to encompass I guess. When you reach the textPath you start a new chunk and start positioning the glyphs where the path is essentially.

@tabatkins
Copy link
Member

Yup, exactly. Just render according to the path (and any descendant tspans), ignoring any positioning instructions coming from the text or tspan ancestors.

@dirkschulze
Copy link
Contributor

#274 seems to be related to this issue.

@AmeliaBR
Copy link
Contributor

Wow. I had no idea no one supported textPath inside tspan. That does make things more annoying.

As for @tabatkins example of cross-browser inconsistencies when text follows the end of a textPath: The undefined/inconsistent behavior was noted and a result specified two years ago, it's just that no one has followed up to get browsers to implement the specified version. See #104
@Tavmjong made the edits, so might have more comments.

@Tavmjong
Copy link
Contributor

Tavmjong commented Dec 3, 2018

I only edited what the group agreed to... I wasn't the one pushing for text outside of a textPath to be rendered (it never occurred to me that it would be until the issue was brought up).

@css-meeting-bot
Copy link
Member

The SVG Working Group just discussed should textPath elements parented to tspans or other textPaths render?, and agreed to the following:

  • RESOLVED: textPath is invalid as a child of tspan or textPath
The full IRC log of that discussion <AmeliaBR> Topic: should textPath elements parented to tspans or other textPaths render?
<AmeliaBR> github: https://github.com//issues/580
<AmeliaBR> Dirk: This issue discussion is bigger than the title, but let's focus on that specific question.
<AmeliaBR> ... based on browser testing, textPath that is a child of tspan is not rendered.
<AmeliaBR> ... so we'd need to change the content model of tspan to not include textPath. Also textPath could not have a textPath as a child.
<AmeliaBR> ... textPath would only be valid as a child of text
<AmeliaBR> Amelia: Well, there are also link elements, which confuse up the content models.
<AmeliaBR> Chris: Yes, that sort of pass-through content model is difficult to define.
<AmeliaBR> Dirk: With that complication, do we agree on the change? Then we can figure out how to specify it.
<AmeliaBR> Amelia: I agree that we should change the spec to match reality, even if that's not the most logical model.
<AmeliaBR> RESOLVED: textPath is invalid as a child of tspan or textPath
<AmeliaBR> Amelia: And then we need some testing for the `a` element to see if it correctly behaves as a transparent content model.
<AmeliaBR> rrsagent, publish minutes
<RRSAgent> I have made the request to generate https://www.w3.org/2018/12/03-svg-minutes.html AmeliaBR
<krit> Thanks AmeliaBR for scribing!
<AmeliaBR> trackbot, end telcon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants