File indexing completed on 2024-05-05 12:14:29

0001 <html>
0002 <head>
0003 <title>Internal design of khtml</title>
0004 <style>
0005 dt { font-weight: bold; }
0006 </style>
0007 <body bgcolor=white>
0008 <h1>Internal design of khtml</h1>
0009 
0010 <p>
0011 This document tries to give a short overview about the internal design of the khtml
0012 library. I've written this, because the lib has gotten quite big, and it is hard at first to find your
0013 way in the source code. This doesn't mean that you'll understand khtml after reading this
0014 document, but it'll hopefully make it easier for you to read the source code.
0015 </p>
0016 <p>
0017 The library is build up out of several different parts. Basically, when you use the lib, you
0018 create an instance of a KHTMLPart, and feed data to it. That's more or less all you need to 
0019 know if you want to use khtml for another application. If you want to start hacking khtml,
0020 here's a sketch of the objects that will get constructed, when eg. running testkhtml with
0021 a url argument.
0022 </p>
0023 <p>
0024 In the following I'll assume that you're familiar with all the buzzwords used in current web 
0025 techology. In case you aren't here's a more or less complete list of references:
0026 </p>
0027 <blockquote>
0028 <p>
0029 <b>Document Object model (DOM):</b><br>
0030 <a href="https://www.w3.org/DOM/">DOM Level1 and 2</a><br>
0031 We support DOM Level2 except for the events model at the moment.
0032 </p>
0033 <p>
0034 <b>HTML:</b><br>
0035 <a href="https://www.w3.org/TR/html4/">HTML4 specs</a><br>
0036 <a href="https://www.w3.org/TR/xhtml1/">xhtml specs</a><br>
0037 We support almost all of HTML4 and xhtml.
0038 </p>
0039 <p>
0040 <b>Cascading style sheets (CSS):</b><br>
0041 <a href="https://www.w3.org/TR/CSS2/">CSS2 specs</a><br>
0042 We support almost all of CSS1, and most parts of CSS2.
0043 </p>
0044 <p>
0045 <b>Javascript:</b><br>
0046 <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/objects.asp">Microsoft javascript bindings</a><br>
0047 <a href="http://docs.sun.com/source/816-6408-10/index.html">Netscape javascript reference</a><br>
0048 Netscapes javascript bindings are outdated. We shouldn't follow them. Let's focus on getting the bindings
0049 compatible to IE.
0050 <a href="https://developer.mozilla.org/docs/Web">Mozilla JS/DOM reference</a>
0051 </p>
0052 </blockquote>
0053 
0054 <p>
0055 <a href="khtml_part.h">KHTMLPart</a> creates one instance of a
0056 <a href="khtmlview.h">KHTMLView</a> (derived from QScrollView),
0057 the widget showing the whole thing.  At the same time a DOM tree
0058 is built up from the HTML or XML found in the specified file.
0059 <p>
0060 Let me describe this with an example.
0061 <p>
0062 khtml makes use of the document object model (DOM) for storing the document
0063 in a tree like structure. Imagine some html like
0064 <pre>
0065 &lt;html&gt;
0066     &lt;head&gt;
0067         &lt;style&gt;
0068             h1: { color: red; }
0069         &lt;/style&gt;
0070     &lt;/head&gt;
0071     &lt;body&gt;
0072         &lt;H1&gt;
0073             some red text
0074         &lt;/h1&gt;
0075         more text
0076         &lt;p&gt;
0077             a paragraph with an
0078             &lt;img src="foo.png"&gt;
0079             embedded image.
0080         &lt;/p&gt;
0081     &lt;/body&gt;
0082 &lt;/html&gt;
0083 </pre>
0084 In the following I'll show how this input will be processed step by step to generate the visible output
0085 you will finally see on your screen. I'm describing the things as if they happen one after the other,
0086 to make the principle more clear. In reality, to get visible output on the screen as soon as possible,
0087 all these things (from tokenization to the build up and layouting of the rendering tree) happen
0088 more or less in parallel.
0089 
0090 <h2>Tokenizer and parser</h2>
0091 <p>
0092 The first thing that happens when you start parsing a new document is that a
0093 DocumentImpl* (for XML documents) or an HTMLDocumentImpl* object will get
0094 created by the Part (in khtml_part.cpp::begin()). A Tokenizer*
0095 object is created as soon as DocumentImpl::open() is called by the part, also
0096 in begin() (can be either an XMLTokenizer or an HTMLTokenizer).
0097 <p>
0098 The XMLTokenizer uses the QXML classes in Qt to parse the document, and it's SAX interface 
0099 to parse the stuff into khtmls DOM.
0100 <p>
0101 For HTML, the tokenizer is located in khtmltokenizer.cpp. The tokenizer uses the contents
0102 of a HTML-file as input and breaks this contents up in a linked list of
0103 tokens. The tokenizer recognizes HTML-entities and HTML-tags. Text between
0104 begin- and end-tags is handled distinctly for several tags. The distinctions
0105 are in the way how spaces, linefeeds, HTML-entities and other tags are
0106 handled.
0107 <p>
0108 The tokenizer is completely state-driven on a character by character basis.
0109 All text passed over to the tokenizer is directly tokenized. A complete
0110 HTML-file can be passed to the tokenizer as a whole, character by character
0111 (not very efficient) or in blocks of any (variable) size.
0112 <p>
0113 The HTMLTokenizer creates an HTMLParser which
0114 interprets the stream of tokens provided by the tokenizer
0115 and constructs the tree of Nodes representing the document according
0116 to the Document Object Model.
0117 <p>
0118 
0119 <h2>The DOM in khtml</h2>
0120 <p>
0121 Parsing the document given above gives the following DOM tree:
0122 
0123 <pre>
0124 HTMLDocumentElement
0125   |--> HTMLHeadElement
0126   |       \--> HTMLStyleElement
0127   |              \--> CSSStyleSheet
0128   \--> HTMLBodyElement
0129          |--> HTMLHeadingElement
0130          |      \--> Text
0131          |--> Text
0132          \--> HTMLParagraphElement
0133                 |--> Text
0134                 |--> HTMLImageElement
0135                 \--> Text
0136 </pre>
0137 <p>
0138 Actually, the classes mentioned above are the interfaces for accessing the 
0139 DOM. The actual data is stored in *Impl classes, providing the implementation
0140 for all of the above mentioned elements. So internally we have a tree 
0141 looking like:
0142 <pre>
0143 HTMLDocumentElementImpl*
0144   |--> HTMLHeadElementImpl*
0145   |       \--> HTMLStyleElementImpl*
0146   |              \--> CSSStyleSheetImpl*
0147   \--> HTMLBodyElementImpl*
0148          |--> HTMLHeadingElementImpl*
0149          |      \--> TextImpl*
0150          |--> TextImpl*
0151          \--> HTMLParagraphElementImpl*
0152                 |--> TextImpl*
0153                 |--> HTMLImageElementImpl*
0154                 \--> TextImpl*
0155 </pre>
0156 <p>
0157 We use a refcounting scheme to assure that all the objects get deleted, in
0158 case the root element gets deleted (as long as there's no interface class 
0159 holding a pointer to the Implementation).
0160 <p>
0161 The interface classes (the ones without the Impl) are defined in the <code>dom/</code>
0162 subdirectory, and are not used by khtml itself at all. The only place they are used are in the
0163 javascript bindings, which uses them to access the DOM tree. The big advantage of having this 
0164 separation between interface classes and imlementation classes, is that we can have several 
0165 interface objects pointing to the same implementation. This implements the requirement of
0166 explicit sharing of the DOM specs.
0167 <p>
0168 Another advantage is, that (as the implementation classes are not exported) it gives us a lot
0169 more freedom to make changes in the implementation without breaking binary compatibility.
0170 <p>
0171 You will find almost a one to one correspondence between the interface classes and the implementation
0172 classes. In the implementation classes we have added a few more intermediate classes, that can
0173 not be seen from the outside for various reasons (make implementation of shared features easier
0174 or to reduce memory consumption).
0175 <p>
0176 In C++, you can access the whole DOM tree from outside KHTML by using the interface classes. 
0177 For a description see the <a href="http://developer.kde.org/documentation/library/kdeqt/kde3arch/khtml/index.html">introduction to khtml</a> on <a href="http://developer.kde.org/">developer.kde.org</a>.
0178 
0179 One thing that has been omitted in the discussion above is the style sheet defined inside the 
0180 <code>&lt;style&gt;</code> element (as an example of a style sheet) and the image element 
0181 (as an example of an external resource that needs to be loaded). This will be done in the following
0182 two sections.
0183 
0184 <h2>CSS</h2> The contents of the <code>&lt;style&gt;</code> element (in this
0185 case the <code>h1 { color: red; }</code> rule) will get passed to the
0186 <a href="html/html_headimpl.h">HTMLStyleElementImpl object</a>.  This object creates an
0187 <a href="css/cssstylesheetimpl.h">CSSStyleSheetImpl object</a> and passes the
0188 data to it. The <a href="css/cssparser.h">CSS parser</a> will take
0189 the data, and parse it into a DOM structure for CSS (similar to the one for
0190 HTML, see also the DOM level 2 specs). This will be later on used to define the
0191 look of the HTML elements in the DOM tree.
0192 <p>
0193 Actually "later on" is relative, as we will see later, that this happens partly in parallel to 
0194 the build up of the DOM tree.
0195 
0196 <h2>Loading external objects</h2>
0197 <p>
0198 Some HTML elements (as <code>&lt;img&gt;, &lt;link&gt;, &lt;object&gt;, etc.</code>) contain
0199 references to external objects, that have to be loaded. This is done by the
0200 Loader and related classes (misc/loader.*). Objects that might need to load external objects
0201 inherit from <a href="misc/loader_client.h">CachedObjectClient</a>, and can ask
0202 the <a href="misc/loader.h">loader</a> (that also acts as a memory cache) to
0203 download the object they need for them from the web.
0204 <p>
0205 Once the <a href="misc/loader.h">loader</a> has the requested object ready, it will notify the
0206 <a href="misc/loader_client.h">CachedObjectClient</a> of this, and the client can
0207 then process the received data.
0208 
0209 <h2>Making it visible</h2>
0210 
0211 Now once we have the DOM tree, and the associated style sheets and external objects, how
0212 do we get the stuff actually displayed on the screen?
0213 <p>
0214 For this we have a rendering engine, that is completely based on CSS. The first
0215 thing that is done is to collect all style sheets that apply to the document
0216 and create a nice list of style rules that need to be applied to the
0217 elements. This is done in the <a href="css/cssstyleselector.h">CSSStyleSelector</a> class.
0218 It takes the <a href="css/html4.css">default HTML style sheet</a> (defined in css/html4.css),
0219 an optional user defined style sheet, and all style sheets from the document,
0220 and combines them to a nice list of parsed style rules (optimised for fast
0221 lookup). The exact rules of how these style sheets should get applied to HTML
0222 or XML documents can be found in the CSS2 specs.
0223 <p>
0224 Once we have this list, we can get a <a
0225 href="rendering/render_style.h">RenderStyle object</a>
0226 for every DOM element from the <a
0227 href="css/cssstyleselector.h">CSSStyleSelector</a> by calling
0228 "styleForElement(DOM::ElementImpl *)".
0229 The style object describes in a compact form all the
0230 <a href="css/css_properties.in">CSS properties</a>
0231 that should get applied to the Node.
0232 <p>
0233 After that, a rendering tree gets built up. Using the style object, the
0234 <a href="xml/dom_nodeimpl.h">DOM Node</a> creates an appropriate render object
0235 (all these are defined in the rendering subdirectory) and adds it to the
0236 rendering tree.  This will give another tree like structure, that resembles in
0237 it's general structure the DOM tree, but might have some significant
0238 differences too. First of all, so called
0239  <a href="https://www.w3.org/TR/CSS2/visuren.html#anonymous-block-level">anonymous boxes</a> - (see
0240  <a href="https://www.w3.org/TR/CSS2/">CSS specs</a>) that
0241 have no DOM counterpart might get inserted into the rendering tree to satisfy
0242 DOM requirements. Second, the display property of the style affects which type
0243 of rendering object is chosen to represent the current DOM object.
0244 
0245 <p>
0246 In the above example we would get the following rendering tree:
0247 <pre>
0248 RenderRoot*
0249   \--> RenderBody*
0250          |--> RenderFlow* (&lt;H1&gt;)
0251          |      \--> RenderText* ("some red text")
0252          |--> RenderFlow* (anonymous box)
0253          |      \--> RenderText* ("more text")
0254          \--> RenderFlow* (&lt;P&gt;)
0255                 |--> RenderText* ("a paragraph with an")
0256                 |--> RenderImage*
0257                 \--> RenderText* ("embedded image.")
0258 </pre>
0259 
0260 <p>
0261 A call to of <a href="rendering/render_root.cpp">layout()</a> on the
0262 <a href="rendering/render_root.h">RenderRoot </a> (the root of the rendering tree)
0263 object causes the rendering tree to layout itself into the available space
0264 (width) given by the KHTMLView. After that, the drawContents() method of
0265 KHTMLView can call RenderRoot->print() with appropriate parameters to actually
0266 paint the document. This is not 100% correct, when parsing incrementally, but
0267 is exactly what happens when you resize the document.
0268 
0269 
0270 As you can see, the conversion to the rendering tree removed the head part of
0271 the HTML code, and inserted an anonymous render object around the string "more
0272 text". For an explanation why this is done, see the CSS specs.
0273 <p>
0274 
0275 <h2>Directory structure</h2>
0276 
0277 A short explanation of the subdirectories in khtml.
0278 <dl>
0279 <dt><a href="css/">css:</a>
0280 <dd>Contains all the stuff relevant to the CSS part of DOM Level2 (implementation classes only), 
0281 the <a href="css/cssparser.h">CSS parser</a>, and the stuff to create
0282 RenderStyle object out of Nodes and the CSS style sheets.
0283 <dt><a href="dom/">dom: </a>
0284 <dd>Contains the external DOM API (the DOM interface classes) for all of the DOM
0285 <dt><a href="ecma/">ecma:</a>
0286 <dd>The javascript bindings to the DOM and khtml.
0287 <dt><a href="html/">html:</a>
0288 <dd>The html subpart of the DOM (implementation only), the HTML tokenizer and parser and a class
0289 that defines the DTD to use for HTML (used mainly in the parser).
0290 <dt><a href="java/">java:</a>
0291 <dd>Java related stuff.
0292 <dt><a href="misc/">misc:</a>
0293 <dd>Some misc stuff needed in khtml. Contains the image loader, some misc definitions and the
0294 decoder class that converts the incoming stream to unicode.
0295 <dt><a href="rendering">rendering:</a>
0296 <dd>Everything thats related to bringing a DOM tree with CSS declarations to the screen. Contains
0297 the definition of the objects used in the rendering tree, the layouting code, and the RenderStyle objects.
0298 <dt><a href="xml/">xml:</a>
0299 <dd>The XML part of the DOM implementation, the xml tokenizer.
0300 </dl>
0301 
0302 <h2>Exception handling</h2>
0303 To save on library size, C++-exceptions are only enabled in the dom/ subdirectory,
0304 since exceptions are mandated by the DOM API. In the rest of KHTML's code,
0305 we pass an error flag (usually called "exceptionCode"), and the class that
0306 is part of dom/* checks for this flag and throws the exception.
0307   
0308 <h2>Final words...</h2>
0309 <p>
0310 All the above is to give you a quick introduction into the way khtml brings an HTML/XML file to the screen.
0311 It is by no way complete or even 100% correct. I left out many problems, I will perhaps add either on request
0312 or when I find some time to do so. Let me name some of the missing things:
0313 <ul>
0314 <li>The decoder to convert the incoming stream to Unicode
0315 <li>interaction with konqueror/applications
0316 <li>javascript
0317 <li>dynamic reflow and how to use the DOM to manipulate khtmls visual output
0318 <li>mouse/event handling
0319 <li>real interactions when parsing incrementally
0320 <li>java
0321 </ul>
0322 
0323 Still I hope that this short introduction will make it easier for you to get a first hold of khtml and the way it works.
0324 <p>
0325 Now before I finish let me add a small <b>warning</b> and <b>advice</b> to all of you who plan hacking khtml themselves:
0326 <p>
0327 khtml is by now a quite big library and it takes some time to understand how it works. Don't let yourself get frustrated
0328 if you don't immediately understand how it works. On the other hand, it is by now one of the libraries that
0329 get used a lot, that probably has the biggest number of remaining bugs (even though it's sometimes hard to
0330 know if some behavior is really a bug).
0331 <blockquote>
0332 Some parts of it's code are however <b>extremely touchy</b> (especially the layouting algorithms), 
0333 and making changes there (that might fix a bug on one web page) might introduce severe bugs.
0334 All the people developing khtml have already spend huge amounts of time searching for such bugs,
0335 that only showed up on some web pages, and thus were found only a week after the change that
0336 introduced the bug was made. This can be very frustrating for us, and we'd appreciate if people
0337 that are not completely familiar with khtml post changes touching these critical regions to kfm-devel
0338 for review before applying them.
0339 </blockquote>
0340 
0341 <div style="margin-top: 2em; font-size: large;">
0342 And now have fun hacking khtml.
0343 <div style="margin-left: 10em; margin-bottom: 1em;">Lars</div>
0344 </div>
0345 </body>
0346 </html>