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 <html> 0066 <head> 0067 <style> 0068 h1: { color: red; } 0069 </style> 0070 </head> 0071 <body> 0072 <H1> 0073 some red text 0074 </h1> 0075 more text 0076 <p> 0077 a paragraph with an 0078 <img src="foo.png"> 0079 embedded image. 0080 </p> 0081 </body> 0082 </html> 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><style></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><style></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><img>, <link>, <object>, 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* (<H1>) 0251 | \--> RenderText* ("some red text") 0252 |--> RenderFlow* (anonymous box) 0253 | \--> RenderText* ("more text") 0254 \--> RenderFlow* (<P>) 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>