- From: Cyril Concolato <cyril.concolato@enst.fr>
- Date: Mon, 04 Sep 2006 09:38:18 +0200
- To: SVG WG <w3c-svg-wg@w3.org>, www-svg <www-svg@w3.org>
[resending since the previous post did not get through] 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: <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 : <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:36:52 UTC