Gecko Layout Engine Troy Chevalier 8 August 1999 Overview Gecko is Mozilla's new layout engine. It is based on the HTML4, CSS1, XML 1.0, and DOM Internet standards, and it is built using a modular XPCOM-based architecture. When we talk about layout, we're referring to the formatting process that applies presentation styles to a source document. The formatting process is controlled by the style specification. Components Here are a list of components and terms that will be referenced by this document. Parser Either the HTML or XML parser. Processes the document and makes calls to the content sink. Content sink Called by the parser. Responsible for building the content model. Content model Consists of document object and a tree of content objects. Changes to the content model result in modifications of the frame model. Frame model Frames are formatting objects. Each frame defines a particular set of formatting characteristics. Reflow The formatting process. Reflow of the frame model defines the visual appearance of the formatted document. Frame construction Initial creation and updating of the frame model in response to changes to the content model and changes to the style data. Style system Provide the mapping and management of style data onto document content in a given presentation. Major components are style set, style sheets, style sheet and rules, style context, and style sheet loader. Presentation shell Controlling point for managing the presentation of a document. View system Consists of a view manager and view objects arranged in a tree hierarchy. Views support overlapped positioning, z-order sorting, and opacity levels. Document Loading The basic flow of control is as follows: as the parser encounters tokens it notifies the content sink that a new node (or child node) is encountered. The content sink creates the appropriate type content object and inserts it into the content model. Whenever the content model changes the document's observers are notified. The presentation shell is one of the document observers. The presentation shell forwards the document change notification to the style set object The style set passes the notification to the frame construction code, the frame construction code creates new frames and inserts them into the frame model. The document is reflowed, and the formatted changes are displayed. The actual interfaces involved are: nsIDocument nsIDocumentObserver nsIPresShell nsIStyleSet nsIStyleFrameConstruction nsIFrame All of the interface files are located in the mozilla/layout/base/public directory. Object Lifetimes Gecko supports multiple views of the same document. This means you can print the same document that you're viewing on the screen, and there's only one content model. Because there's just a single content model, each of the content objects is referenced counted. The document holds a reference to the root content object, and each content node holds a reference to its child content nodes. Each view of the document has a separate presentation shell, style manager, style set, and frame hierarchy. The presentation shell is the controlling point for the presentation of a document, and it holds a reference to the document object. Frames and views are not referenced counted. The lifetime of the frame hierarchy is bounded by the lifetime of the presentation shell which owns the frames. The lifetime of the view hierarchy is bounded by the lifetime of the view manager that owns the views. Frames Each frame defines a particular set of formatting characteristics. Frames have the opportunity to: reflow (format) their child frames render their appearance handle mouse and keyboard events display a cursor have an associated view object Frames can have multiple child lists, the default unnamed child list (referred to as the principal child list) and additional named child lists. There is an ordering of frames within a child list, but no ordering between frames in different child lists of the same parent frame. The principal child list contains the flowed children, and the additional child lists are for out-of-flow frames like floated elements and absolutely positioned elements. Child frames are linked together in a singly linked list. Each frame defines its own local coordinate space. Frame bounding rects are in twips, and the origin is relative to the upper-left corner of its parent frame. The bounding rect includes the content area, borders, and padding. Frame Construction The frame construction process begins with a notification that content has been added or removed or that style has changed. The first step is to resolve style information for the content element. This process creates a style context that is stored in the frame (see nsIStyleContext). Once style is resolved construction rules are used to decide the type of frame to create. First we look at the element's tag and special case some things like IMG elements. If we don't create a frame that way, then we use the 'display' property to dictate what type of frame to create. Typically it's a block or inline frame. For a 'display' value of 'none' no frame is created. For elements that are out of the flow (for example, a floated element or an absolutely positioned element), a placeholder frame is also created. The placeholder frame is inserted into the flow exactly where the out-of-flow frame would have been inserted. The out-of-flow frame is then inserted as a child of its containing block in one of the additional child lists. Floated frames are inserted into the "Float-list" and absolutely positioned frames are inserted into the "Absolute-list". Frame Manager The frame manager is owned by the presentation shell and used by both the presentation shell and the frame construction code. It serves two main purposes: provides a service for mapping from content object to frame and from out-of-flow frame to placeholder frame coordinates structural modifications to the frame model In many places in the frame code we need to find the frame associated with a particular content object. In order to quickly implement this operation we maintain a mapping from content objects to frames. The frame construction adds and removes entries from the map as frames are created and destroyed. When creating new frames and removing existing frames, the frame construction code doesn't directly modify the frame hierarchy. Instead if informs the frame manager and has it coordinate the request. If the frame model lock is available, the change is processed immediately; otherwise, the request is queued and processed later. The frame manager also coordinates processing of replaced elements that can't be rendered (for example, an IMG or OBJECT element), and it allows client to register to be notified when a particular frame is being destroyed. This is needed because frames are not reference counted. It's used by the event manager and other clients to ensure that any outstanding references to the frame are cleaned up. Reflow Process The fact that are two reflow interfaces reflects an early goal of having core layout and HTML specific layout. The core reflow process would be the same for all frames, and each class of formatting objects (for example, CSS and DSSSL) would have their own reflow additions. The reflow process is a top-down protocol where a frame is given some available space and asked to reflow its child frames and return a desired size. The reflow process is not part of the nsIFrame interface. The generic reflow interface is defined in the nsIFrameReflow interface, and the HTML/CSS specific reflow interface is defined in the nsIHTMLReflow interface. An important part of the reflow process is the calculation of the computed values for the CSS properties. This includes things like 'width', 'height', and 'margin', and involves calculation of the containing block width and height and percentage based values and properties whose value is inherited. This process is encapsulated in the HTML specific reflow state struct (struct nsHTMLReflowState) that is passed in as part of reflow. The reflow states are linked together with the reflow state for a child frame pointing to its parent frame's reflow state. This allows us to walk up the reflow state structures and calculate containing block width and height and percentage based values. In addition to the computed values for the CSS box model properties, the following items are also included: reflow reason that indicates why the frame is being reflowed a rendering context that can be used to measure text reflow command (only used for incremental reflow) space manager The most common reflow reasons are 'eReflowReason_Resize' (the viewport has changed size) and 'eReflowReason_Incremental' (processing of an incremental reflow command). Reflow commands (see nsHTMLReflowCommand in mozilla/layout/html/base/src) are used to kick off an incremental reflow. They're generated either by the style system (in response to a style change) or by a frame itself (for example, if a frame has dirty child frames that need to be reflowed it will generate a reflow command). Reflow commands are queued by the presentation shell and then dispatched. Reflow commands have a target frame, which is the frame for which the reflow command is destined. In the example above the target frame is the frame with dirty child frames that need to be reflowed. Reflow command processing follows a path from the root frame down to the target frame. The space manager (see nsISpaceManager in mozilla/layout/base/public) is used when flowing text around floated elements. It has an API for managing bands of unavailable space (space that is reserved for a floated element). Internally it organizes the band data similar to how a region data structure works. Frame Classes There are four main categories of frame classes, all of which are located in mozilla/layout/html/src: core frame classes table frame classes form frame classes frameset frame classes The core frame classes implement the CSS viewport abstraction, scrolling, block and inline display of flowed elements, floats, and absolute positioning. For more information on block layout, click here. For more information about line layout, click here. The table frame classes correspond to the HTML4 table spec, and in addition to the table frame there are row group frames, row frames, column group frames, column frames, and cell frames. There is an "outer" table frame as well that's really an anonymous frame that contains the caption frame and the table frame itself. Table layout is determined in a 3-step process. In the first step, the table is flowed into an infinitely wide and tall space. This gives us the minimum and desired sizes for every cell in the table. In the second step, the table constraints are factored in and widths are assigned to every cell. In the third step, heights are assigned to every cell based on the computed width constraint. The results of the first step are cached and only need to be recomputed when content or constraints are changed. Event Manager To be written