[SVG Tiny 1.2 CR Comment] On the efficiency of display='none'

Dear all,

This mail is a feedback from an implementation of SVG Tiny 1.2 in [1].
It discusses the design of the rendering tree and the efficiency of 
setting display='none' on grouping elements.

The specification says in section "11.9 Controlling visibility and 
rendering" [2]:
"When applied to a container element , setting 'display' to none causes 
the container and all of its children to be excluded from the rendering 
tree".
(As a side note, the second bullet in that section should read 'When the 
'display' property is set to none on graphics elements, ...", shouldn't it?)
We understand this as: the meaning of display='none' is to reduce the 
number of elements to traverse during rendering, thus the processing 
required to render the document. We analyzed which are the elements that 
display='none' allows not traversing or partial traversing.

We investigated the consequences of setting display to 'none' on the 
different kinds of SVG elements:
• Animation elements:
We based our implementation on the fact that 'inherit' values in 
animation attributes ('from', 'to' and 'values') are resolved based on 
the location of the target element of the animation and not on the 
location of the animation element itself. Given that assumption, that we 
would like to be clarified (see [6]), we designed our implementation 
such that the timing part of the animation is evaluated before the 
rendering tree traversal and that the actual presentation value 
computation is done when the target element of the rendering tree is 
traversed.

This means two things:
- animation elements are not actually part of the rendering tree, and
- if the target of an animation is not part of the rendering tree, the 
part of the animation that computes the presentation value is switched 
off. Only the timing part and the resolution of events and the 
triggering of begin, end and repeat events is needed. So, with this 
design, display='none' indeed brings efficiency benefit.

• Media elements (audio, video, animation) :
The consequences are the same for media elements. We divided their 
handling in two parts: timing and rendering. Timing is evaluated 
beforehand so that even if the element is not part of the rendering 
tree, timed events are still fired and handled. This way, when display 
is set to 'none', we indeed switch off the big part of the processing.

• 'use' elements and inheritance
According to [3], inheritance of properties in elements referenced by a 
'use' element is based on the location of the 'use' element. So the 
target of a 'use' element has to be traversed, even if it is in a 
display='none' part of the DOM tree. There is no efficiency gain there. 
The only efficiency gain happens if the referencing element (the 'use') 
is in the switched off DOM subtree.

• 'listener', 'handler', 'discard', 'prefetch' and 'script' elements
To our opinion, these elements should also be listed in the list of 
elements not being part of the rendering tree because they do not have 
rendering. It should be clarified that: 'listener' elements should still 
listen to events, 'handler' elements should still handle events, 
'discard' elements should still discard, 'prefetch' elements should 
still prefetch resources, and 'script' elements should still be 
evaluated even if they are in a subtree where 'display' is 'none', 
according to their semantics, that their handling is in fact orthogonal 
to the rendering.
It is clear that setting 'display'='none' does not reduce the processing 
of the document in this respect, except for the fact that mouse events 
are not generated from that part of the DOM tree.

• Graphics elements
Here setting the 'display' to 'none' actually brings a lot because we 
switch off the rendering part and the animation interpolation part as 
described above.

• the 'font-face-uri' element
I'm not an expert in this element and we did not implement it yet. But 
the same argument as above applies. The referenced 'font' element should 
inherit from the the 'font-face-uri' element, if inheritance applies here.

• Focus navigation
The specification [7] explains that "The SVG User Agent must not 
navigate to an element which has display='none'." which means that when 
setting 'display' to 'none' on a group element, one must traverse the 
subtree to determine if there is an element in the focus ring to be 
removed, and the opposite when setting it to other value than 'none'. 
But is there another solution? We couldn't find any.

For these elements, we may have found a problem which would actually 
prevent us from optimizing.

• the 'mpath' element
It should be specified that:
- no property apply to the path motion, or
- when an 'mpath' element points to a 'path' element, the 'path' element 
inherits its properties from the 'mpath' element and not for its parent 
element. Otherwise, the ancestors of the 'path' element need to be 
processed to evaluate the 'stroke-dasharray' and 'stroke-dashoffset' 
properties which are inheritable and affect the path motion.

• Paint servers: 'linearGradient', 'radialGradient' and 'solidColor'
Even though these elements are not part of the rendering (we assume 
'solidColor' is not, even if not listed in the definition of rendering 
tree, we believe it's a mistake), section "11.16 Gradients" of [4] 
explains the following:
"Properties shall inherit into the 'linearGradient' [or 
'radialGradient'] element from its ancestors; properties shall not 
inherit from the element referencing the 'linearGradient' [or 
'radialGradient'] element."

We tried to understand what this actually meant. The allowed elements 
'into the gradient' according to the RNG (see 'GradientCommon.CM' in 
[5]) are: 'desc', 'metadata', the animation elements, 'discard' and 
'stop' elements. Since we assume animation elements inherit from the 
target element, the only inner gradient elements that could use 
properties are 'stop' elements. We searched for properties which apply 
to 'stop' elements and found: 'stop-color', 'stop-opacity' and 
potientally 'color'. Only 'color' is inheritable and would therefore 
inherit its value through the gradient element, possibly from the parent 
of the gradient element, to the stop color.
Except for 'color', the reasons for the sentences quoted above are not 
obvious. But the problem is clear. Just for 'color', this sentence 
forces the traversal of the display='none' subtree to retrieve the 
computed value for that property on the gradient element. This might 
imply computing animations at multiple levels of the display='none' 
subtree. Let's look at the following example (anim_gradient.svg):

<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect id="r1" fill="url(#MyGradient)" width="100" height="100" x="200" 
y="200"/>
<rect id="r2" fill="url(#MyGradient2)" width="100" height="100" x="200" 
y="500"/>
<g id="g1" display="none">
<g id="g2">
<animateColor id="a1" attributeName="stop-color" from="red" to="blue" 
dur="5" begin="0" additive="replace" accumulate="none" fill="freeze"/>
<animateColor id="a1" attributeName="color" from="red" to="blue" dur="5" 
begin="0" additive="replace" accumulate="none" fill="freeze"/>
<linearGradient id="MyGradient">
<stop offset="0" stop-color="green" />
<stop offset="1" stop-color="inherit" />
</linearGradient>
<linearGradient id="MyGradient2">
<stop offset="0" stop-color="green" />
<stop offset="1" stop-color="currentColor" />
</linearGradient>
</g>
</g>
</svg>

According to the current specification, since 'stop-color' is not 
inheritable, the value 'inherit' is not allowed and should be ignored, 
defaulting to the initial value of 'black'. Therefore, the top rectangle 
'r1' should show a linear gradient from 'green' to 'black'.
On the other hand, since 'currentColor' is specified in the stop color 
of the second gradient 'MyGradient2', one needs to get the computed 
value for the 'color' property. This forces the evaluation of the 
animation on the 'g' element called 'g2', which is actually not part of 
the rendering tree. This is quite inefficient for a not so particularly 
useful feature.

We tested the above example in different players:
- Adobe SVG Viewer 6.0 shows r1 correctly but for r2 shows a non 
animated gradient from green to red.
- Opera 9 and Osmo4 0.4.2 show the same result. r1 is correctly 
displayed (static, green-black gradient) but r2 uses a static gradient 
from green to black.
- Tinyline 1.10 shows two non animated gradients from green to red.
- eSVG Viewer 2.4 shows two non animated gradients from green to white.
- Renesis 0.1 shows non animated gradients, r1 is from green to white, 
r2 is from green to cyan.

We wanted to test static viewers as well, so we used the following 
example (gradient_inherit.svg) :
<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="g1" stop-color="blue">
<rect id="r1" fill="url(#MyGradient)" width="100" height="100" x="200" 
y="200"/>
</g>
<g id="g2" stop-color="red">
<linearGradient id="MyGradient">
<stop offset="0" stop-color="green" />
<stop offset="1" stop-color="inherit" />
</linearGradient>
</g>
</svg>

And the results are:
- ASV 6, Firefox 1.5.0.6, Batik 1.6 and Osmo4 0.4.2 show green to black
- Opera 9 shows green to red
- Renesis 0.1 and eSVG Viewer show green to white

We couldn't test mobile implementations, but these tests clearly show 
that there is no interoperability on this SVG 1.1 Feature. There is 
definitely a need for clarification.

We suggest removing the problematic sentences in 'linearGradient' and 
'radialGradient' and adding the following sentence instead, which should 
also be added to the 'solidColor' element, since as a paint server, it 
should behave like the gradient elements:
"Properties for this element, when inherited, shall inherit values from 
the referencing element."
This change would allow for possible optimizations, described above, 
when display='none' is specified on a subtree which contains gradients 
or solid colors definitions.

We suggest clariyfing the 'mpath' semantics.

We also suggest clarifying the property's definitions by removing the 
'inherit' value in properties which cannot be inherited. The following 
informative sentence would also help:
"If a property's definition indicates 'inherited: no', the value 
'inherit' is not allowed in the corresponding presentation attribute. If 
specified, the value shall be ignored and the initial value of the 
property shall be used."

Finally, we also suggest updating the definition of the rendering tree 
to exclude animation elements, 'mpath', 'listener', 'handler', 
'discard', 'prefetch' and 'script' elements.

Best regards,

Cyril Concolato

[1] http://gpac.sourceforge.net
[2] http://www.w3.org/TR/SVGMobile12/painting.html#VisibilityControl
[3] http://www.w3.org/TR/SVGMobile12/struct.html#UseElement
[4] http://www.w3.org/TR/SVGMobile12/painting.html#Gradients
[5] http://www.w3.org/Graphics/SVG/1.2/rng/Tiny-1.2/gradient-tiny.rng
[6] http://www.w3.org/mid/44FA8E22.4050000@enst.fr
[7] http://www.w3.org/TR/SVGMobile12/interact.html#navigationbehaviour

Received on Monday, 4 September 2006 07:37:03 UTC