You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.
Reflow is the process by which the geometry of the layout engine's formatting objects are computed. The HTML formatting objects are called frames: a frame corresponds to the geometric information for (roughly) a single element in the content model; the frames are arranged into a hierarchy that parallels the containment hierarchy in the content model. A frame is rectangular, with width, height, and an offset from the parent frame that contains it.
More than one frame may be needed to represent a single element from the content model; for example, text that wraps is broken into several frames, one per wrapped line. In this case, the primary frame is the frame containing the first line of text, with continuing frames (or continuations) created for subsequent lines.
HTML uses a flow based layout model, meaning that most of the time it is possible to compute the geometry in a single pass. Elements later ``in the flow'' typically do not affect the geometry of elements that are earlier ``in the flow'', so layout can proceed left-to-right, top-to-bottom through the document. There are exceptions to this rule: most notably, HTML tables may require more than one pass.
The XUL box layout model, on the other hand, is constraint based, meaning that geometric preferences and constraints of neighboring elements are taken into consideration before the elements' final geometry can be computed. The box is the geometric primitive for the XUL layout model.
   All HTML reflow, including the intial reflow, begins at
   the root frame, which corresponds to the
   <html> element of the HTML document. Reflow
   proceeds recursively through some or all of the frame hierarchy,
   computing geometric information for each frame object that requires
   it. Reflow may have the side-effect of creating new continuation
   frames, for example, for a text frame when the text must be
   wrapped.
  
   Some reflows are immediate in response to user or script
   actions; for example, resizing the window or changing the
   document's default font. These are dispatched directly from the
   presentation shell (e.g.,
   nsIPresShell::StyleChangeReflow), and affect the
   entire frame tree. Other reflows are incremental and are
   dealt with asynchronously; for example, when content streams in
   from the network. Incremental reflows are queued by the
   presentation shell for batched dispatch.
  
   The reflow state object,
   nsHTMLReflowState, is used to pass constraining
   information ``down'' from parent frames to child frames. For
   example, a <div> with a constrained width (e.g.,
   set via the CSS width property) would note this in the
   reflow state object before flowing its children.
  
   When reflow begins, the root reflow state is initialized
   with information about the top-level container for the document's
   presentation; e.g., the width and height of the application
   window. This is passed as an argument to the Reflow
   method of the root frame in the frame hierarchy.
  
Each container frame constructs a new reflow state object (based on its container's reflow state object) in which the container will reflow its children. Most of the constraints in the new reflow state are computed when the state is created; for example, the available space in the new reflow state is computed by subtracting the container frame's border and padding from the parent reflow state's available space.
All reflows have a reason, which is maintained in the reflow state object (and may mutate, as described below). The reflow reason controls how a frame reacts during a reflow, and is one of the following:
Initial, for the very first time that the
    frame hierarchy is flowed. In this case, a frame knows that there
    is no residual state that can be used to simplify geometry
    computation.
   Incremental, when something in the frame
    tree changes; for example, when more content is read from the
    network, or some script manipulates the DOM. An incremental reflow
    is targeted at a single frame in the frame
    hierarchy. During an incremental reflow, a frame can assume that
    none of the constraints computed ``from above'' (for example,
    available width) have changed; instead, something ``within'' the
    frame has changed, which may have bottom-up impact to the frame
    hierarchy.
   Resize, when the containing boundary for
    the frame hierarchy changes. During a resize reflow, the frame can
    assume that none of the frame's internal state (e.g., a text
    frame's text) has changed; instead, a top-down change in the
    layout constraints has occured.
   StyleChange, when the entire frame
    hierarchy must be traversed to recover from stylistic change; for
    example, a change in the default font size.
   Dirty, when a container frame has
    consolidated several individual Incremental reflows
    that have been targeted at its child frames.
   Initial, incremental, resize, and style change reflows may each be performed as an immediate ``global'' reflow from the presentation shell:
A dirty reflow is never performed directly from the presentation shell. Instead, a dirty reflow is detected when an incremental reflow reaches its target frame, described below.
   The reflow metrics object,
   nsHTMLReflowMetrics, is used to propagate information
   from child frames back to the parent. For example, the dimensions
   of each child frame of an unconstrained <div>
   would be passed back to the <div>'s frame via
   the nsHTMLReflowMetrics object.
  
   Although all of the reflow in Gecko attempts to re-use as much
   existing state as possible (and is in therefore some sense
   ``incremental'') an Incremental reflow corresponds to
   a reflow that is specifically targeted at an individual frame in
   the frame hierarchy. A frame requests a Incremental
   reflow (or one is requested on a frame's behalf) when something
   about the frame itself has changed.
  
   Scheduling. To request (or schedule) an
   incremental reflow (e.g., in response to a change in the content
   model), a reflow command object is created and passed to
   the presentation shell via the
   nsIPresShell::AppendReflowCommand method. The
   presentation shell does not process the command
   immediately. Instead, it queues the command, and processes it
   asynchronously along with other queued reflow commands en
   masse.
  
Coalescing. As described below, the reflow command has a type and a target frame. Multiple reflow commands with the same type and target frame are coalesced: the presentation shell simply refuses to add subsequent commands of the same type for the same frame to the queue. A caller may also cancel a reflow command that is in the queue; e.g., if the target frame is destroyed.
   Dispatch. The presentation shell processes the
   reflow queue by removing a single reflow command from the queue and
   dispatching it to its target frame.
   (But cf. the
   reflow tree
   work, which will remove several commands from the queue at
   once.)
   A path is built from the target frame to the root
   frame and stored in the reflow command. A reflow
   state object is created with a reflow reason of
   Incremental, the reflow command is stored in the
   state, and the Reflow method of the root frame is
   invoked.
  
   Processing. The root frame notes the
   Incremental reflow reason specified in the reflow
   state, and inspects the path contained within the reflow command
   object. Specifically, it extracts the next frame along
   the path from the reflow command object, creates its own reflow
   state, also with an Incremental reason, and invokes
   the Reflow method of the next frame.
  
The incremental reflow proceeds recursively through the frame hierarchy. Each frame along the incremental reflow path (as specified in the reflow command object) extracts the next frame and dispatches the reflow downward. In order to correctly dispatch the reflow to the child frame, the frame may need to perform some state recovery; for example, a block frame will traverse its line list to recover the space occupied by floated frames.
At some point, the incremental reflow reaches the target frame, at which point the reflow command's type becomes significant.
ContentChanged indicates that the content
    corresponding to the target frame has changed somehow; for
    example, the text associated with a text frame has been modified.
    In reality, the only frame that responds to
    this sort of reflow is the block frame. The block frame treats
    this sort of change as a `full reflow' (i.e., as a resize). This
    makes me believe that we could probably eliminate this class
    altogether.
   StyleChanged indicates that the stylistic
    information corresponding to the target frame has changed; for
    example, the font size has increased. This causes the frame to
    mutate the reflow state's reason to
    StyleChange, which is propagated recursively to the
    entire subtree beneath the target frame.
   ReflowDirty indicates that container frame
    has decided to coalesce several incremental reflows targeted at
    its children into a single reflow. The container frame maintains
    the necessary state to determine which children must be reflowed.
   UserDefined, for ``special
    situations''.
    Currently, this is only used by the
    viewport frame to schedule a reflow to reflow all of
    the viewport's fixed-position frames. We should probably try to
    eliminate it.
   An incremental reflow may damage other parts of the frame hierarchy; for example, changing the size of the font used in a specific paragraph may cause the paragraph to grow or shrink. A container must therefore propagate any damage that the incremental reflow of the child frame caused, possibly reflowing other children as well.
   If several incremental changes occur in the same part of the frame
   hierarchy, it is possible to have several Incremental
   reflows targeted at nearby frames. In this case, it is likely that
   the individual Incremental reflows will end up doing
   redundant work. For example, each keystroke typed into a text
   widget could generate a separate Incremental reflow
   targeted at the text frame. Were we to process each individually,
   the text widget would be flowed once for each keystroke, which
   would be wasteful if the latency of an individual reflow exceeds
   the speed at which text is being typed. The purpose of the
   Dirty reflow is to allow these individual reflows to
   be coalesced intelligently.
  
   A frame that decides it needs a dirty reflow sets the
   NS_FRAME_IS_DIRTY state bit on itself, and then calls
   the ReflowDirtyChild method on its parent frame. In
   ReflowDirtyChild, the parent frame sets the
   NS_FRAME_HAS_DIRTY_CHILD state bit on itself, and does
   any bookkeeping necessary to remember which child is dirty (for
   example, the block frame marks the linebox dirty that contains the
   child frame). The parent frame can then either decide to schedule a
   ReflowDirty Incremental reflow targeted
   at itself, or to delegate that responsibility to its
   parent. If it decides to delegate, then it sets the
   NS_FRAME_IS_DIRTY state bit on itself and recursively
   calls ReflowDirtyChild.
  
   Eventually, the ReflowDirty Incremental
   reflow is dispatched, and arrives at the container frame that
   scheduled it. The target frame recovers its bookkeeping information
   (e.g., the block frame iterates through the dirty lineboxes), and
   reflows the dirty child frames.
  
   Isn't information lost if a
   ReflowDirty Incremental reflow coalesces
   different kinds of incremental reflows (e.g., a
   ContentChanged with a
   StyleChanged)? No, because these kinds of
   reflows aren't coalesced; instead, they're directly
   enqueued to the presentation shell's reflow queue.
  
   As mentioned above, HTML and XUL have fundamentally different
   layout models, the former being a flow-based model, and the latter
   being a constraint based model. These differences are mediated by
   two adapter classes: nsBoxFrame and
   nsBoxToBlockAdaptor.
  
   nsBoxFrame is an HTML frame that ``wraps'' a XUL
   box. Its purpose is to convert HTML reflows their box analog.
  
   nsBoxToBlockAdaptor is a XUL box that wraps an HTML
   block frame, used to convert changes in the box layout into HTML
   reflows.