Re: [svgwg] Update getNumberOfChars() definition

The spec reference to `.textContent` is new in SVG 2, so let's get rid
 of that and focus on the prose (# of renderable characters) and 
existing implementations.

The [SVG 1.1 definition 
was](https://www.w3.org/TR/SVG11/text.html#__svg__SVGTextContentElement__getNumberOfChars):

> Returns the total number of characters available for rendering 
within the current element, which includes referenced characters from 
‘tref’ reference, regardless of whether they will be rendered. 
Effectively, this is equivalent to the length of the Node::textContent
 attribute from DOM Level 3 Core ([DOM3], section 1.4), if that 
attribute also expanded ‘tref’ elements.

Removing the `<tref>` mentions and focusing on the normative text 
instead of the incorrect "Effectively..." sentence, we get:

> Returns the total number of characters available for rendering 
within the current element, regardless of whether they will be 
rendered.

An algorithmic definition thereof would look something like:

> Returns the sum of the renderable text length for all child nodes of
 this element, where the renderable text length is as follows:

> - For a text node, the length of its text content, after normalizing
 whitespace according to the value of CSS `white-space` property on 
this element;
> - For a text content element, `<a>` element, or `SVGUnknownElement`,
 the result of recursively calling this algorithm on that element;
> - For all other elements or nodes, 0.

However, since you need to compute CSS styles for `white-space`, 
there's no additional performance or utility impact of also making the
 function depend on `display: none`, to match the current behavior.

That could be introduced into the recursive algorithm by _either_ 
checking whether this element is rendered (and always returning 0 if 
it isn't), or by looking explicitly at the `display` property for each
 child element.  I'd prefer the second approach, so that you can still
 measure the usable text length of an element even when it's inside a 
`<defs>` or a `<symbol>` or such.

However, because there is a dependency on CSS, this algorithm would 
not be defined for an element that is currently detached from a 
document, unless we explicitly defined it to use the initial values of
 the properties.

Also, on the question of `display: none`, we probably need more 
explicit guidance on how character-by-character positioning attributes
 are assigned from a parent element if a nested element is not 
displayed.  The only guidance from SVG 1.1 was that elements with 
`display: none` "do not affect text layout".  SVG 2 explicitly defines
 ["addressable 
characters"](https://svgwg.org/svg2-draft/text.html#TermAddressableCharacter)
 to exclude those "discarded during layout", but it doesn't explicitly
 mention `display: none`.

E.g., for something like the following [JSBin 
demo](http://jsbin.com/qokafeyelo/1/edit?html,output):

    <text x="10 20 30 40 50">12<tspan style="display: 
none">34</tspan>5</text>

Chrome & Edge render it to match:

    <text x="10 20 30">125</text>

But Firefox renders it to match:

    <text x="10 20 50">125</text>

Assuming the Chrome/Edge behavior is deemed correct, so that `display:
 none` content is removed from per-character positioning, then it 
makes sense that those characters are also removed from 
`getNumberOfChars()`.

***But*** the same behavior would also have to be used for all the 
other character-count methods.  E.g., if `getNumberOfChars()` returns 
3, `getExtentOfChar(2)` better not return an empty box from one of the
 non-displayed characters.  

That behavior, of only counting, positioning, and querying the final 
rendered text after CSS processing, is consistent with the approach to
 whitespace (which is or isn't included in the count, based on current
 collapsing rules) and keeps us open to allowing `::before`/`::after` 
content.  In fact, if we define all SVG text positioning and 
interfaces to use the rendered text string, I see no reason not to 
allow CSS generated content now (as @tabatkins would support and 
@Tavmjong would disagree with, according to the last discussion in 
#125).

(Aside, this will get really fun when you throw a `text-transform: 
full-width` style on it. That would change the byte count of the 
rendered string!)

For backwards consistency (and consistency with existing 
implementations), text length must still be measured in UTF-16 code 
points, equivalent to String.length in JavaScript.  Once ECMAScript 
support for proper counting of mutli-byte characters is stable, we'll 
probably want to introduce parallel versions of the SVG methods that 
use those new rules, and an attribute or property on the elements to 
switch how x/y/dx/dy/rotate are counted.

-- 
GitHub Notification of comment by AmeliaBR
Please view or discuss this issue at 
https://github.com/w3c/svgwg/issues/200#issuecomment-232410340 using 
your GitHub account

Received on Wednesday, 13 July 2016 16:29:05 UTC