Introduction to Layout in Mozilla

Overview

  • Basic data flow
  • Key data structures
  • Detailed walk-through
  • Incrementalism
  • Future tech-talks
  • Wrap-up, Q&A

Basic Data Flow

  • Source document arrives via network APIs
  • Incrementally “pumped” through the single-threaded layout engine
    • Parse, compute style, render; repeat
    • CSS used for rendering all content
  • Content theoretically separate from “presentation”

Key Data Structures

  • Content node
    • Elements, attributes, leaves
    • DOM
  • Frame
    • Rectangular formatting primitive
    • Geometric information
    • [0..n] per content node
    • 2nd thru nth are “continuations”
  • Style context
    • Non-geometric information
    • May be shared by adjacent frames
    • Reference counted, owned by frame
  • View
    • Clipping, z-order, transparency
    • [0..1] per frame, owned by frame
  • Widget
    • Native window
    • [0..1] per view, owned by view

Key Data Structures

  • The document owns the content model, and one or more presentations
    • Exposed programmatically via DOM APIs
  • The presentation owns the frame hierarchy
    • Frames own the style contexts, views, widgets
    • Presentation has media type, dimensions, etc.
    • May not be directly manipulated

Detailed Walk-Through

  • Setting up
  • Content model construction
  • Frame construction
  • Style resolution
  • Reflow
  • Painting

Setting Up

  • Assume basic knowledge of embedding and network APIs (doc shell, streams)
  • Content DLL auto-registers a Document Loader Factory (DLF)
    • @mozilla.org/content-viewer-factory/view;1?type=text/html
    • All MIME types mapped to the same class, nsContentDLF
  • nsDocShell
    • Receives inbound content via nsDSURIContentListener
    • Invokes nsIDLF::CreateInstance, passes MIME type to DLF
  • nsContentDLF
    • Creates a nsHTMLDocument object, invokes StartDocumentLoad.
      • Creates a parser, returned as nsIStreamListener back to the docshell
      • Creates a content sink, which is linked to the parser and the document
    • Creates a DocumentViewerImpl object, which is returned as nsIContentViewer back to the docshell
  • DocumentViewerImpl creates pres context and pres shell

Content Model Construction

  • Content arrives from network via nsIStreamListener::OnDataAvailable
  • Parser tokenizes & processes content; invokes methods on nsIContentSink with parser node objects
    • Some buffering and fixup occurs here
    • OpenContainer, CloseContainer, AddLeaf
  • Content sink creates and attaches content nodes using nsIContent interface
    • Content sink maintains stack of “live” elements
    • More buffering and fixup occurs here
    • InsertChildAt, AppendChildTo, RemoveChildAt

Frame Construction

  • Content sink uses nsIDocument interface to notify of Δs in content model
    • ContentAppended, ContentInserted, ContentRemoved
  • PresShell is registered as document observer
    • Receives ContentAppended, etc. notifications
    • Passes these to the style set object, who in turn passes to the frame constructor
  • Frame constructor creates frames
    • ConstructFrameInternal recursively walks content tree, resolves style and creates frames
    • Either created by tag (<select>) or by display type (<p>)
  • Frame manager maintains mapping from content to frame

Style Resolution

  • Compute stylistic information based on the style rules that apply for the frame’s content node
  • Style data broken into different structures
    • Display, visibility, font, color, background, …
    • Inherit vs. reset
  • Style context object is a placeholder for partially computed stylistic data
    • Style data is computed lazily, as it is asked for

Reflow

  • Recursively compute geometry (x, y, w, h) for frames, views, and widgets
    • Given w & h constraints of “root frame” compute (x, y, w, h) for all children
    • Constraints propagated “down” via nsHTMLReflowState
    • Desired size returned “up” via nsHTMLReflowMetrics
  • Basic pattern
    • Parent frame initializes child reflow state (available w, h); places child frame (x, y); invokes child’s Reflow method
    • Child frame computes desired (w, h), returns via reflow metrics
    • Parent frame sizes child frame and view based on child’s metrics
  • N.B. many don’t work like this! (Tables, blocks, XUL boxes)

Reflow

  • “Global” reflows
    • Initial, resize, style-change
    • Processed immediately via PresShell method
  • Incremental reflows
    • Targeted at a specific frame
    • Dirty, content-changed, style-changed, user-defined
    • nsHTMLReflowCommand object encapsulates info
    • Queued and processed asynchronously, nsIPressShell::AppendReflowCommand, ProcessReflowCommands

Incremental Reflow

  • Recursively descend to target recovering reflow state
    • Child rs.reason set to incremental

Incremental Reflow

  • Process reflow “normally” at target frame
    • Child rs.reason set based on rc’s type

Incremental Reflow

  • Propagate damage to frames later “in the flow”

Incremental Reflow

  • Multiple reflow commands are batched
    • nsReflowPath maintains a tree of target frames
    • Amortize state recovery and damage propagation cost

Painting

  • As reflow proceeds through the frame hierarchy, areas are invalidated via nsIViewManager::UpdateView
  • Unless immediate, invalid areas are coalesced and processed asynchronously via OS expose event
  • Native expose event dispatched to widget; widget delegates to the view manager
  • View manager paints views back-to-front, invoking PresShell’s Paint method
  • PresShell::Paint walks from the view to the frame; invokes nsIFrame::Paint for each layer

Incrementalism

  • Single-threaded
    • Simple (no locking)
    • Can’t leave event queue unattended
  • Content construction unwinds “at will”
    • Parser and content sink do some buffering
    • Content sink has “notification limits”
    • Efficiency vs. responsiveness trade-off
  • Frame construction runs to completion
  • CSS parsing runs to completion
  • Reflow runs to completion (mostly)
  • Painting runs to completion

Future (?) Tech Talks

  • Content model and DOM - jst, jkeiser
  • Parser and content sink (esp. invalid content) - harishd
  • Events - saari, joki
  • Block-and-line reflow - waterson, dbaron
  • Table reflow - karnaze
  • Form controls - rods, bryner
  • Style resolution and rule tree - dbaron
  • Views, widgets, and painting - roc, kmcclusk
  • Editor - kin, jfrancis
  • XUL and box layout - hewitt, ben
  • XBL - hewitt, ben

Conclusion

  • Data flow
  • Key data structures
  • Detailed walk-through
  • Incrementalism
  • Q & A?

Original Document Information

  • Author(s): Chris Waterson
  • Last Updated Date: June 10, 2002
  • Copyright Information: Portions of this content are © 1998–2007 by individual mozilla.org contributors; content available under a Creative Commons license | Details.

Document Tags and Contributors

Tags: 
Contributors to this page: ethertank, DBaron, Kohei, Kennykaiyinyu
Last updated by: ethertank,