summaryrefslogtreecommitdiffstats
path: root/tdehtml/DESIGN.html
diff options
context:
space:
mode:
Diffstat (limited to 'tdehtml/DESIGN.html')
-rw-r--r--tdehtml/DESIGN.html346
1 files changed, 346 insertions, 0 deletions
diff --git a/tdehtml/DESIGN.html b/tdehtml/DESIGN.html
new file mode 100644
index 000000000..861825141
--- /dev/null
+++ b/tdehtml/DESIGN.html
@@ -0,0 +1,346 @@
+<html>
+<head>
+<title>Internal design of tdehtml</title>
+<style>
+dt { font-weight: bold; }
+</style>
+<body bgcolor=white>
+<h1>Internal design of tdehtml</h1>
+
+<p>
+This document tries to give a short overview about the internal design of the tdehtml
+library. I've written this, because the lib has gotten quite big, and it is hard at first to find your
+way in the source code. This doesn't mean that you'll understand tdehtml after reading this
+document, but it'll hopefully make it easier for you to read the source code.
+</p>
+<p>
+The library is build up out of several different parts. Basically, when you use the lib, you
+create an instance of a KHTMLPart, and feed data to it. That's more or less all you need to
+know if you want to use tdehtml for another application. If you want to start hacking tdehtml,
+here's a sketch of the objects that will get constructed, when eg. running testtdehtml with
+a url argument.
+</p>
+<p>
+In the following I'll assume that you're familiar with all the buzzwords used in current web
+techology. In case you aren't here's a more or less complete list of references:
+</p>
+<blockquote>
+<p>
+<b>Document Object model (DOM):</b><br>
+<a href="http://www.w3.org/DOM/">DOM Level1 and 2</a><br>
+We support DOM Level2 except for the events model at the moment.
+</p>
+<p>
+<b>HTML:</b><br>
+<a href="http://www.w3.org/TR/html4/">HTML4 specs</a><br>
+<a href="http://www.w3.org/TR/xhtml1/">xhtml specs</a><br>
+We support almost all of HTML4 and xhtml.
+</p>
+<p>
+<b>Cascading style sheets (CSS):</b><br>
+<a href="http://www.w3.org/TR/REC-CSS2/">CSS2 specs</a><br>
+We support almost all of CSS1, and most parts of CSS2.
+</p>
+<p>
+<b>Javascript:</b><br>
+<a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/objects.asp">Microsoft javascript bindings</a><br>
+<a href="http://docs.sun.com/source/816-6408-10/index.html">Netscape javascript reference</a><br>
+Netscapes javascript bindings are outdated. We shouldn't follow them. Let's focus on getting the bindings
+compatible to IE.
+<a href="http://mozilla.org/docs/dom/domref/">Mozilla JS/DOM reference</a>
+</p>
+</blockquote>
+
+<p>
+<a href="tdehtml_part.h">KHTMLPart</a> creates one instance of a
+<a href="tdehtmlview.h">KHTMLView</a> (derived from TQScrollView),
+the widget showing the whole thing. At the same time a DOM tree
+is built up from the HTML or XML found in the specified file.
+<p>
+Let me describe this with an example.
+<p>
+tdehtml makes use of the document object model (DOM) for storing the document
+in a tree like structure. Imagine some html like
+<pre>
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;style&gt;
+ h1: { color: red; }
+ &lt;/style&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;H1&gt;
+ some red text
+ &lt;/h1&gt;
+ more text
+ &lt;p&gt;
+ a paragraph with an
+ &lt;img src="foo.png"&gt;
+ embedded image.
+ &lt;/p&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre>
+In the following I'll show how this input will be processed step by step to generate the visible output
+you will finally see on your screen. I'm describing the things as if they happen one after the other,
+to make the principle more clear. In reality, to get visible output on the screen as soon as possible,
+all these things (from tokenization to the build up and layouting of the rendering tree) happen
+more or less in parallel.
+
+<h2>Tokenizer and parser</h2>
+<p>
+The first thing that happens when you start parsing a new document is that a
+DocumentImpl* (for XML documents) or an HTMLDocumentImpl* object will get
+created by the Part (in tdehtml_part.cpp::begin()). A Tokenizer*
+object is created as soon as DocumentImpl::open() is called by the part, also
+in begin() (can be either an XMLTokenizer or an HTMLTokenizer).
+<p>
+The XMLTokenizer uses the QXML classes in Qt to parse the document, and it's SAX interface
+to parse the stuff into tdehtmls DOM.
+<p>
+For HTML, the tokenizer is located in tdehtmltokenizer.cpp. The tokenizer uses the contents
+of a HTML-file as input and breaks this contents up in a linked list of
+tokens. The tokenizer recognizes HTML-entities and HTML-tags. Text between
+begin- and end-tags is handled distinctly for several tags. The distinctions
+are in the way how spaces, linefeeds, HTML-entities and other tags are
+handled.
+<p>
+The tokenizer is completely state-driven on a character by character basis.
+All text passed over to the tokenizer is directly tokenized. A complete
+HTML-file can be passed to the tokenizer as a whole, character by character
+(not very efficient) or in blocks of any (variable) size.
+<p>
+The HTMLTokenizer creates an HTMLParser which
+interprets the stream of tokens provided by the tokenizer
+and constructs the tree of Nodes representing the document according
+to the Document Object Model.
+<p>
+
+<h2>The DOM in tdehtml</h2>
+<p>
+Parsing the document given above gives the following DOM tree:
+
+<pre>
+HTMLDocumentElement
+ |--> HTMLHeadElement
+ | \--> HTMLStyleElement
+ | \--> CSSStyleSheet
+ \--> HTMLBodyElement
+ |--> HTMLHeadingElement
+ | \--> Text
+ |--> Text
+ \--> HTMLParagraphElement
+ |--> Text
+ |--> HTMLImageElement
+ \--> Text
+</pre>
+<p>
+Actually, the classes mentioned above are the interfaces for accessing the
+DOM. The actual data is stored in *Impl classes, providing the implementation
+for all of the above mentioned elements. So internally we have a tree
+looking like:
+<pre>
+HTMLDocumentElementImpl*
+ |--> HTMLHeadElementImpl*
+ | \--> HTMLStyleElementImpl*
+ | \--> CSSStyleSheetImpl*
+ \--> HTMLBodyElementImpl*
+ |--> HTMLHeadingElementImpl*
+ | \--> TextImpl*
+ |--> TextImpl*
+ \--> HTMLParagraphElementImpl*
+ |--> TextImpl*
+ |--> HTMLImageElementImpl*
+ \--> TextImpl*
+</pre>
+<p>
+We use a refcounting scheme to assure that all the objects get deleted, in
+case the root element gets deleted (as long as there's no interface class
+holding a pointer to the Implementation).
+<p>
+The interface classes (the ones without the Impl) are defined in the <code>dom/</code>
+subdirectory, and are not used by tdehtml itself at all. The only place they are used are in the
+javascript bindings, which uses them to access the DOM tree. The big advantage of having this
+separation between interface classes and imlementation classes, is that we can have several
+interface objects pointing to the same implementation. This implements the requirement of
+explicit sharing of the DOM specs.
+<p>
+Another advantage is, that (as the implementation classes are not exported) it gives us a lot
+more freedom to make changes in the implementation without breaking binary compatibility.
+<p>
+You will find almost a one to one correspondence between the interface classes and the implementation
+classes. In the implementation classes we have added a few more intermediate classes, that can
+not be seen from the outside for various reasons (make implementation of shared features easier
+or to reduce memory consumption).
+<p>
+In C++, you can access the whole DOM tree from outside KHTML by using the interface classes.
+For a description see the <a href="http://developer.kde.org/documentation/library/kdeqt/trinityarch/tdehtml/index.html">introduction to tdehtml</a> on <a href="http://developer.kde.org/">developer.kde.org</a>.
+
+One thing that has been omitted in the discussion above is the style sheet defined inside the
+<code>&lt;style&gt;</code> element (as an example of a style sheet) and the image element
+(as an example of an external resource that needs to be loaded). This will be done in the following
+two sections.
+
+<h2>CSS</h2> The contents of the <code>&lt;style&gt;</code> element (in this
+case the <code>h1 { color: red; }</code> rule) will get passed to the
+<a href="html/html_headimpl.h">HTMLStyleElementImpl object</a>. This object creates an
+<a href="css/cssstylesheetimpl.h">CSSStyleSheetImpl object</a> and passes the
+data to it. The <a href="css/cssparser.h">CSS parser</a> will take
+the data, and parse it into a DOM structure for CSS (similar to the one for
+HTML, see also the DOM level 2 specs). This will be later on used to define the
+look of the HTML elements in the DOM tree.
+<p>
+Actually "later on" is relative, as we will see later, that this happens partly in parallel to
+the build up of the DOM tree.
+
+<h2>Loading external objects</h2>
+<p>
+Some HTML elements (as <code>&lt;img&gt;, &lt;link&gt;, &lt;object&gt;, etc.</code>) contain
+references to external objects, that have to be loaded. This is done by the
+Loader and related classes (misc/loader.*). Objects that might need to load external objects
+inherit from <a href="misc/loader_client.h">CachedObjectClient</a>, and can ask
+the <a href="misc/loader.h">loader</a> (that also acts as a memory cache) to
+download the object they need for them from the web.
+<p>
+Once the <a href="misc/loader.h">loader</a> has the requested object ready, it will notify the
+<a href="misc/loader_client.h">CachedObjectClient</a> of this, and the client can
+then process the received data.
+
+<h2>Making it visible</h2>
+
+Now once we have the DOM tree, and the associated style sheets and external objects, how
+do we get the stuff actually displayed on the screen?
+<p>
+For this we have a rendering engine, that is completely based on CSS. The first
+thing that is done is to collect all style sheets that apply to the document
+and create a nice list of style rules that need to be applied to the
+elements. This is done in the <a href="css/cssstyleselector.h">CSSStyleSelector</a> class.
+It takes the <a href="css/html4.css">default HTML style sheet</a> (defined in css/html4.css),
+an optional user defined style sheet, and all style sheets from the document,
+and combines them to a nice list of parsed style rules (optimised for fast
+lookup). The exact rules of how these style sheets should get applied to HTML
+or XML documents can be found in the CSS2 specs.
+<p>
+Once we have this list, we can get a <a
+href="rendering/render_style.h">RenderStyle object</a>
+for every DOM element from the <a
+href="css/cssstyleselector.h">CSSStyleSelector</a> by calling
+"styleForElement(DOM::ElementImpl *)".
+The style object describes in a compact form all the
+<a href="css/css_properties.in">CSS properties</a>
+that should get applied to the Node.
+<p>
+After that, a rendering tree gets built up. Using the style object, the
+<a href="xml/dom_nodeimpl.h">DOM Node</a> creates an appropriate render object
+(all these are defined in the rendering subdirectory) and adds it to the
+rendering tree. This will give another tree like structure, that resembles in
+it's general structure the DOM tree, but might have some significant
+differences too. First of all, so called
+ <a href="http://www.w3.org/TR/REC-CSS2/visuren.html#anonymous-block-level">anonymous boxes</a> - (see
+ <a href="http://www.w3.org/TR/REC-CSS2/">CSS specs</a>) that
+have no DOM counterpart might get inserted into the rendering tree to satisfy
+DOM requirements. Second, the display property of the style affects which type
+of rendering object is chosen to represent the current DOM object.
+
+<p>
+In the above example we would get the following rendering tree:
+<pre>
+RenderRoot*
+ \--> RenderBody*
+ |--> RenderFlow* (&lt;H1&gt;)
+ | \--> RenderText* ("some red text")
+ |--> RenderFlow* (anonymous box)
+ | \--> RenderText* ("more text")
+ \--> RenderFlow* (&lt;P&gt;)
+ |--> RenderText* ("a paragraph with an")
+ |--> RenderImage*
+ \--> RenderText* ("embedded image.")
+</pre>
+
+<p>
+A call to of <a href="rendering/render_root.cpp">layout()</a> on the
+<a href="rendering/render_root.h">RenderRoot </a> (the root of the rendering tree)
+object causes the rendering tree to layout itself into the available space
+(width) given by the the KHTMLView. After that, the drawContents() method of
+KHTMLView can call RenderRoot->print() with appropriate parameters to actually
+paint the document. This is not 100% correct, when parsing incrementally, but
+is exactly what happens when you resize the document.
+
+
+As you can see, the conversion to the rendering tree removed the head part of
+the HTML code, and inserted an anonymous render object around the string "more
+text". For an explanation why this is done, see the CSS specs.
+<p>
+
+<h2>Directory structure</h2>
+
+A short explanation of the subdirectories in tdehtml.
+<dl>
+<dt><a href="css/">css:</a>
+<dd>Contains all the stuff relevant to the CSS part of DOM Level2 (implementation classes only),
+the <a href="css/cssparser.h">CSS parser</a>, and the stuff to create
+RenderStyle object out of Nodes and the CSS style sheets.
+<dt><a href="dom/">dom: </a>
+<dd>Contains the external DOM API (the DOM interface classes) for all of the DOM
+<dt><a href="ecma/">ecma:</a>
+<dd>The javascript bindings to the DOM and tdehtml.
+<dt><a href="html/">html:</a>
+<dd>The html subpart of the DOM (implementation only), the HTML tokenizer and parser and a class
+that defines the DTD to use for HTML (used mainly in the parser).
+<dt><a href="java/">java:</a>
+<dd>Java related stuff.
+<dt><a href="misc/">misc:</a>
+<dd>Some misc stuff needed in tdehtml. Contains the image loader, some misc definitions and the
+decoder class that converts the incoming stream to unicode.
+<dt><a href="rendering">rendering:</a>
+<dd>Everything thats related to bringing a DOM tree with CSS declarations to the screen. Contains
+the definition of the objects used in the rendering tree, the layouting code, and the RenderStyle objects.
+<dt><a href="xml/">xml:</a>
+<dd>The XML part of the DOM implementation, the xml tokenizer.
+</dl>
+
+<h2>Exception handling</h2>
+To save on library size, C++-exceptions are only enabled in the dom/ subdirectory,
+since exceptions are mandated by the DOM API. In the rest of KHTML's code,
+we pass an error flag (usually called "exceptionCode"), and the class that
+is part of dom/* checks for this flag and throws the exception.
+
+<h2>Final words...</h2>
+<p>
+All the above is to give you a quick introduction into the way tdehtml brings an HTML/XML file to the screen.
+It is by no way complete or even 100% correct. I left out many problems, I will perhaps add either on request
+or when I find some time to do so. Let me name some of the missing things:
+<ul>
+<li>The decoder to convert the incoming stream to Unicode
+<li>interaction with konqueror/applications
+<li>javascript
+<li>dynamic reflow and how to use the DOM to manipulate tdehtmls visual output
+<li>mouse/event handling
+<li>real interactions when parsing incrementally
+<li>java
+</ul>
+
+Still I hope that this short introduction will make it easier for you to get a first hold of tdehtml and the way it works.
+<p>
+Now before I finish let me add a small <b>warning</b> and <b>advice</b> to all of you who plan hacking tdehtml themselves:
+<p>
+tdehtml is by now a quite big library and it takes some time to understand how it works. Don't let yourself get frustrated
+if you don't immediately understand how it works. On the other hand, it is by now one of the libraries that
+get used a lot, that probably has the biggest number of remaining bugs (even though it's sometimes hard to
+know if some behavior is really a bug).
+<blockquote>
+Some parts of it's code are however <b>extremely touchy</b> (especially the layouting algorithms),
+and making changes there (that might fix a bug on one web page) might introduce severe bugs.
+All the people developing tdehtml have already spend huge amounts of time searching for such bugs,
+that only showed up on some web pages, and thus were found only a week after the change that
+introduced the bug was made. This can be very frustrating for us, and we'd appreciate if people
+that are not completely familiar with tdehtml post changes touching these critical regions to kfm-devel
+for review before applying them.
+</blockquote>
+
+<div style="margin-top: 2em; font-size: large;">
+And now have fun hacking tdehtml.
+<div style="margin-left: 10em; margin-bottom: 1em;">Lars</div>
+</div>
+</body>
+</html>