Re: SVG in HTML5 draft proposal

(Replying to a message from public-svg-wg:
http://lists.w3.org/Archives/Public/public-svg-wg/2008AprJun/att-0142/SVG-in-HTML-proposal.html
I gather that I'm not supposed to post there, so I'm posting to www- 
svg instead. CCed to public-html for HTML parsing relevance.)

> This document addresses some of the issues that need to be taken  
> into consideration when creating a hybrid design. It also proposes a  
> potential, high-level solutions for some of those problems.
>
> HTML/SVG Markup Integration Considerations
> 	• Interleaved Parsing of HTML/SVG
> 	• JavaScript context sharing
> 	• JavaScript node access
> 	• CSS integration
> 	• SVG Widgets
> 	• Focus Navigation
> 	• Unified API (IDL)

I think this list omits an important point: DOM tree sharing. In the  
top 3 browser engines that implement SVG (Gecko, WebKit and Presto),  
the layout engine contains an SVG renderer and a CSS formatter, and  
the SVG and CSS rendering contexts can nest using a single shared DOM  
tree as the source of the data to be formatted.
> As the reader is probably already aware, HTML and SVG are both  
> markup languages. SVG follows the strict XML rules and HTML allows  
> for a looser syntax, like tags not been closed, etc.
>
Considering the dominant design in browsers that support SVG natively,  
I think focusing on syntax differences isn't the crux of the matter  
but focusing on them both being DOM languages is.
> To accommodate the complexity of integrating both, SGML & XML type  
> languages, SVG WG proposes a use of a cascaded parser. Cascading  
> parser allows recursive nested invocations between SGML and XML  
> Content Handler.
>
I'd prefer references to HTML directly instead of references to SGML,  
since implementations don't implement HTML as an SGML language.
> Since XML already defines how XML languages from different  
> namespaces interact with each-other, it is valid to have one XML  
> language embedded in another.
>
More to the point, XML defines unambiguous parsing in that case, but  
doesn't specify interaction further than that.
> When embedding HTML inside SVG, the HTML markup must be well formed.
>
I think requiring HTML to be well-formed inside or outside SVG in text/ 
html is a bad requirement, since it would defeat a part of the value  
proposition that motivates SVG in text/html in the first place: that  
you add SVG without having to turn your HTML into well-formed XHTML as  
turning existing HTML into well-formed XHTML would be too expensive  
compared to the benefit of getting some added SVG.

> Cascading parser is combination of parsers, cascaded together to  
> process content of a different type – HTML and XML for example. The  
> individual parsers have their own rules, specific to the way the  
> markup language is structured. All of the individual parsers need to  
> also follow common rules of interactions with the other parsers.

The figure shows JavaScript and CSS parsers as examples of cascading  
parsers. I think SVG-in-HTML shouldn't be likened to CSS-in-HTML.

In the case of SVG-in-XHTML, there's one parser that produces one  
parse tree that contains both SVG and XHTML nodes. CSS-in-XHTML, on  
the other hand, goes through a second level of parsing through a CSS  
parsing. I think it would be natural to have the same kind of parsing  
layering in text/html: to handle SVG-in-HTML in one parser with shared  
DOM output and having a second level of parsing for CSS.
> A Content Handler is a logical component, which understands and  
> processes particular content type.
>
> Historically, the Content Handler are called Content plug-ins. The  
> interface is built for most plug-ins to only allow for content  
> inclusion by reference, i.e. no real content integration. For  
> example, displaying SVG from a plug-in in a WEB browser window, does  
> not make it integrated SVG Content Handler of HTML. Only if elements  
> of SVG can be interleaved with HTML content, then it can be  
> considered integrated. For example, it should be possible for an SVG  
> image and path elements to be displayed as elements of HTML table.  
> Another example is SVG text on path can be overplayed on top of HTML  
> Image object. From user visual perspective the content behaves as a  
> single markup language.
>
Considering that the dominant design for SVG support in browsers that  
support SVG out of the box is not based on a plug-in model, and those  
browser are three of the top four browsers, I think the design for SVG- 
in-HTML shouldn't assume a plug-in architecture but instead should  
assume the software architecture of Gecko, WebKit and Presto, where  
both the CSS formatter and the SVG renderer are built-in parts of the  
layout engine.

> Additionally, if the Content Handler supports progressive parsing,  
> it may process the content in a different way to that of a non- 
> progressive parser.

This is a rather un-specific statement.

I think it is desirable for the mapping from a byte stream to a tree  
not to depend on progressive rendering. So the input should get the  
same processing with or without incremental rendering, and the only  
exception should be that with incremental rendering intermediate tree  
states can be rendered.

> HTML and XML have a very similar way of tokenizing. However, the  
> tokeniser must maintain information about token casing.
>
Does this imply that HTML and SVG parts share the tokenizer? Earlier  
it seemed that the main objection to Hixie's SVG-in-HTML proposal was  
that it used the same tokenizer for both.

The parsing algorithm gets at least two nice properties when the  
tokenizer is not case-preserving as in Hixie's proposal:

  1) Being in an SVG subtree doesn't affect the matching of the start  
tag and end tag pair, so with bogus cargo cult input, the resulting  
tree shape remains closer to what an SVG-unaware HTML parser would  
produce.

  2) In the case of a well-known tag name, a tokenizer buffer range  
containing an element name can be mapped to a statically allocated pre- 
interned descriptor object in the tokenizer without regard to tree  
builder state and without intermediate string object creation. (Each  
camelCase name in known in advance and the descriptor objects hold  
also the camelCase name.)

> Element Identification
> Element identification is a very important step in the cascading  
> parser schema.
>
> Cascading parser maintains tables of:
>
> 	• Element tags – element constructor routines pairs (regular  
> parsers also have such table);
> 	• Reference to Content Handler, which maintains "Element tag -  
> Content Handler" pairs table;
> 	• Namespace mapping table (for XML based parsers);
> The correspondence between a tagname and a handler is not  
> necessarily one-to-one. For example: "font", "video", "a". The  
> context in which the tag is encountered is also responsible for  
> deciding which handler to use.

This means the mapping from nsURI,local pairs onto classes that  
implement the DOM nodes, right? (i.e. the table needed for  
createElementNS.)
> When a HTML parser encounters an unrecognized element during the  
> element identification step, it does the following:
>
> 	•
> Terminates the current element or attribute tag – For example it  
> terminates P, LI, TR, TH, etc. elements.
>
> This may not be entirely accurate. There are many quirks to how  
> broken content is repaired. This is suggesting that svg elements are  
> recognized and parsed anywhere inside HTML. It should be pointed out  
> that XML namespaces apply too. However, this does not solve the  
> element context problem. The DOM and ecma script contexts must be  
> the same, otherwise I see no gain compared to inclusion-by-reference  
> (i.e. <object data="some.svg">).

This part of the proposal seems to need more work.

> 	•
> If a Content Handler that can handle the element is found, the HTML  
> parser passes the control of the file or token stream to the Content  
> Handler. Based on the implementation. The HTML parser may also need  
> to pass JS context and DOM branch reference to the identified  
> Content Handler.
>
Why is the control of the token stream transferred here? Transferring  
the control of the token stream seems awfully complex compared to a  
solution where there is one tree builder and the representation of the  
token stream is a private implementation detail of the one tokenizer  
and the one tree builder.

"Based on implementation" seems dodgy.

Passing a reference to a DOM branch as opposed to the stack of the  
HTML parser is dangerous when scripts execute during parsing and can  
go changing branches of the DOM.

What happens if a script invokes document.write() on the JS script  
context when the SVG Content Handler is consuming tokens?

> 	•
> The newly identified Content Provider,
>
Content Provider?
> starts the processing of (SVG) elements until it encounters  
> unrecognized element error or a namespace, which it can not handle.  
> The SVG Content Handler invokes the initial Content Handler in an  
> attempt to identify the unrecognized element with another Content  
> Handler.
>
> What is "an unrecognized element"? This may not be clear enough.  
> Consider for example <fie:foo xmlns:fie="http://www.foo.com/fooml"/>.

Are well-known HTML elements that the SVG Content Handler itself can't  
handle and unknown elements which might be from a future version of  
SVG handled differently from each other?

> 	•
> If the embedded Content Handler returns with error and the content  
> state is not recognized, the HTML parser will thread the stream from  
> this point on as malformed element and should try to identify the  
> first valid HTML element or a valid token and recover the normal  
> parsing flow.
>
How?
> In cascaded parsing, when one Content Handler passes the JavaScript  
> context to next level below, it is up to the new Content Handler to  
> continue using the existing parent's JavaScript context or create a  
> new one.
>
> Additionally, the parent Content Handler may decide not to pass a  
> valid JavaScript context to the embedded Content Handler. In this  
> case the embedded Content Handler is forced to create a new  
> JavaScript context, if needed.
>
When would the parent not pass the context? When would the child  
handler create its own context even though it got a context from the  
parent?

Does a new script context mean having a window object that isn't the  
same window object as the one seen from HTML script elements? In the  
case of SVG-in-XHTML, all the scripts see the same window, right?
> If an unified DOM3 interface is exposed from the embedded Content  
> Handler, it would be possible for the parents JavaScript context to  
> traverse the child nodes of the embedded content. If this is not  
> supported, the parent's JavaScript content should be allowed to at  
> least see the top-level content node (SVG element for example and  
> its attributes in the SVG content provider case).
>
Surely a spec can't leave something as fundamental as access to the  
full DOM tree on the level of "if this is not supported" especially  
when in the SVG-in-XHTML case access to the full DOM already works.

> A particular implementation may decide to pass the CSS processing  
> rules to the child Content Handler. However, it is better to pass  
> this information during re-flow and rendering phase of the content  
> processing.
>
I'd expect CSS to propagate in the document tree in the same way it  
does with the SVG-in-XHTML case.

> <form> <table border="1" align="center"> <caption><em>A test table  
> with SVG elements</em></caption> <tr> <svg id="svgRoot"  
> version="1.2" baseProfile="tiny" viewBox="-160 -120 480 640"  
> width="480" height="640" stroke-miterlimit="2" zoomAndPan="enable"  
> xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink 
> " xmlns:xe="http://www.w3.org/2001/xml-events"> <g fill- 
> opacity="0.7" stroke="black" stroke-width="0.2"> <circle fill="red"  
> cx="100" cy="100" r="100"/> </g> </svg> </tr> <tr> <svg id="svgRoot"  
> version="1.2" baseProfile="tiny" viewBox="-160 -120 480 640"  
> width="480" height="640" stroke-miterlimit="2" zoomAndPan="enable"  
> xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink 
> " xmlns:xe="http://www.w3.org/2001/xml-events"> <g fill- 
> opacity="0.7" stroke="black" stroke-width="0.2"> <circle  
> fill="green" cx="100" cy="100" r="100"/> </g>       </svg> </tr>  
> <tr> <svg id="svgRoot" version="1.2" baseProfile="tiny"  
> viewBox="-160 -120 480 640" width="480" height="640" stroke- 
> miterlimit="2" zoomAndPan="enable" xml:space="preserve" xmlns="http://www.w3.org/2000/svg 
> " xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xe="http://www.w3.org/2001/xml-events 
> "> <g fill-opacity="0.7" stroke="black" stroke-width="0.2"> <circle  
> fill="blue" cx="100" cy="100" r="100"/> </g> </svg> </tr> </table> </ 
> form>
I think it doesn't make sense to put <svg> as a child of <tr> without  
a <td>.

> Example 4: SVG Widget Structure - svgDoc
>
Isn't this a new concept that goes beyond achieving SVG embeddability  
parity with XHTML?

> Remove hard coded table of case fixes for svg/mathml elements and  
> attributes (if still in the spec).
>
The tables make the algorithm more robust against bogus input, as </ 
TiTlE> closes <title> regardless of parser SVG-awareness. The only  
disadvantage of the case fixing tables is that supporting future SVG  
elements that have camelCase names require amendments to the table.

Amending the table is a much much smaller operation than implementing  
rendered support for a new feature, so implementation-wise avoiding  
future amendments to the table would be the wrong optimization as  
mitigating the undesirable performance impact of deferring case  
folding is a more complex implementation task than adding an entry for  
a new camelCase name. (Alternatively, of course, the SVG WG could  
simply decide to only introduce lower-case names from now on.)

> Create a new XML parser.
>
Putting an XML parser in there is pretty serious complexity. I very  
much against introducing this kind of complexity. The level of HTML  
parser complexity dictated by existing content is bad enough as it is.  
We *really* don't need new complexity where it can be avoided. Here it  
can be avoided by using the HTML tokenizer and making small amendments  
to the HTML tree builder.
> Set the encoding to the character encoding used by the HTML parser.
>

Making the HTML parser and the XML parser decode the byte stream  
independently would pretty much poison any performant buffering scheme.

-- 
Henri Sivonen
hsivonen@iki.fi
http://hsivonen.iki.fi/

Received on Monday, 23 June 2008 09:26:21 UTC