mozilla
Your Search Results

    Block and Line Layout Cheat Sheet

    The details of block and line layout are tricky; this document serves as a "cheat sheet" that describes how the vagary of different state flags control what's going on. It's a work-in-progress, with questions in red highlight. If you know the answer, please pass it along to me so I can update the document.

    Objects

    This section presents some of the classes involved in block and line reflow, along with important members of each object that control reflow processing.

    nsFrame

    The base class for all frames.

    mFlags

    Flags set on the frame to indicate its state. These flags can be grouped into two categories: flags which affect all frames ("public" flags), and flags that are reserved for an individual frame's private use ("private" flags).

    NS_FRAME_IN_REFLOW
    This bit is set when the frame is being actively being reflowed. By default it is set in WillReflow(), and unset in DidReflow(). Many frames' Reflow() method verifies that the bit is set with an assertion.
    NS_FRAME_FIRST_REFLOW
    This flag is set on a newly created frame, and later cleared by the frame's Reflow() method when the frame has had its initial reflow.
    NS_FRAME_SYNC_FRAME_AND_VIEW
    NS_FRAME_OUTSIDE_CHILDREN
    This flag is set if the combined area of a frame's children extend past the frame's bounding box. (What is a frame's "bounding box"?) If this flag is set, then <code>mOverflowArea</code> will contain the total area of the frame, including the overflow.
    NS_FRAME_EXTERNAL_REFERENCE
    NS_FRAME_REPLACED_ELEMENT
    NS_FRAME_GENERATED_CONTENT
    NS_FRAME_HAS_LOADED_IMAGES
    NS_FRAME_OUT_OF_FLOW
    NS_FRAME_SELECTED_CONTENT
    NS_FRAME_IS_DIRTY
    NS_FRAME_IS_UNFLOWABLE
    An unflowable frame is an error condition; for example, due to system limitations. Currently, the only way to get an unflowable frame is to have a frame tree that is "too deep". (See nsFrame::IsFrameTreeTooDeep().)
    NS_FRAME_HAS_DIRTY_CHILDREN
    NS_FRAME_HAS_VIEW
    NS_FRAME_INDEPENDENT_SELECTION
    NS_FRAME_IS_SPECIAL

    nsBlockFrame

    mFlags

    These flags are the private flags that are meaningful to block frames.

    NS_BLOCK_SHRINK_WRAP
    Causes the block to "shrink-wrap" around its content. This means the block will determine its children's width and make its content area that wide. Finally, it will add padding and border to determine the final width. Is this where the "tending towards zero width" stuff comes in?
    NS_BLOCK_NO_AUTO_MARGINS
    NS_BLOCK_MARGIN_ROOT
    Indicates that this is a frame from which child margins can be calculated. The absence of this flag implies that child margin calculations should ignore the frame and look further up the parent chain. Used in nsBlockReflowContext::ComputeCollapsedTopMargin(). This flag causes the nsBlockReflowState's constructor to set the BRS_ISTOPMARGINROOT and BRS_ISBOTTOMMARGINROOT flags. This is set by default for document, table cell inner, and absolutely positioned wrapper frames.
    NS_BLOCK_SPACE_MGR
    This indicates that a block frame should create its own space manager. This is required by each block frame that can contain floaters: the space manager is used to reserve space for the floated frames. This is set by default for document frames, area frames, table cell inner frames, absolutely positioned wrapper frames, and floated frames when the frame is created.

    nsLineBox

    A block consists of lines and other blocks, stacked vertically. A block frame has one nsLineBox for each line, and one nsLineBox for each block child. These are stored as a doubly-linked list in the mLines member of nsBlockFrame.

    nsInlineFrame

    mFlags
    NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD
    This flag is set if the inline frame has any children that have a percentage value set (via the style context) for the width or height of the content area, padding, border, or margin.

    nsHTMLReflowState

    The current state of reflow, built up as reflow recursively descends the frame tree. This is "passed in" to a child frame from its parent, and provides the constraints in which the child frame must size itself; e.g. the width and height available to the child frame.

    mComputedWidth
    mComputedHeight
    mComputedMargin
    mComputedBorderPadding
    mComputedPadding
    mComputedOffsets
    mComputedMinWidth
    mComputedMaxWidth
    mComputedMinHeight
    mComputedMaxHeight

    Given the current container frame and the style applied to the child, these values are the resolved values for the child frame's box.

    nsHTMLReflowMetrics

    The structure that is "filled in" by a frame during reflow, and is used to communicate the frame's desired size information back to its container.

    mMaximumWidth

    The maximum width that the frame would consume if it were reflowed with an unconstrained available width. It might be better named "preferred width". This is computed when the nsBlockReflowState flag BRS_COMPUTEMAXWIDTH is set.

    maxElementWidth

    The maximum width for elements within the frame that cannot be broken down further; e.g., the longest word in a paragraph. Note that an out-of-flow frame (e.g., a floater) may affect this value. This field is a pointer to an nsSize object. When null, the frame need not compute it.

    nsBlockReflowState

    Additional reflow state information that the block frame uses along with nsHTMLReflowState. Like nsHTMLReflowState, this is read-only data that is passed down from a parent frame to its children.

    mFlags
    BRS_UNCONSTRAINEDWIDTH
    This flag is set in the nsBlockReflowState constructor when:
    1. There is no computed width for the frame in the nsHTMLReflowState, and
    2. the frame being reflowed has been given NS_UNCONSTRAINEDSIZE as its available width in the nsHTMLReflowState.
    BRS_UNCONSTRAINEDHEIGHT
    This flag is set in the nsBlockReflowState constructor when the frame being reflowed has been given NS_UNCONSTRAINEDSIZE as its available height in the nsHTMLReflowState. If set, NS_UNCONSTRAINEDSIZE is passed to nsLineLayout as the available height.
    BRS_SHRINKWRAPWIDTH
    BRS_NEEDRESIZEREFLOW
    Related to BRS_SHRINKWRAPWIDTH. Set if we need to force a resize reflow when computing the final size. e.g., because...why?
    BRS_ISINLINEINCRREFLOW
    This flag is set in nsBlockFrame::Reflow() if we detect that we're incrementally reflowing a linebox that contains inline frames. In this case, we can avoid some of the work that occurs during reflow.
    BRS_NOWRAP
    This flag is set in the nsBlockReflowState constructor when the "white-space" style of the block frame is pre or nowrap. It is cleared, otherwise.
    BRS_ISTOPMARGINROOT
    This flag is set in the nsBlockReflowState constructor when reflowing a "block margin root" frame (i.e., a frame with the NS_BLOCK_MARGIN_ROOT flag set, for which margins apply by default). The flag is also set when reflowing a frame whose computed top border padding is zero. (why?)
    BRS_ISBOTTOMMARGINROOT
    This flag is set in the nsBlockReflowState constructor when reflowing a "block margin root" frame (i.e., a frame with the NS_BLOCK_MARGIN_ROOT flag set, for which margins apply by default). The flag is also set when reflowing a frame whose computed bottom border padding is zero. (why?)
    BRS_APPLYTOPMARGIN
    This flag is set if the top margin should be considered when placing a linebox that contains a block frame. It may be set as a side-effect of calling nsBlockFrame::ShouldApplyTopMargin(); once set, ShouldApplyTopMargin() uses it as a fast-path way to return whether the top margin should apply. If the flag hasn't been set in the block reflow state, then ShouldApplyTopMargin() will crawl the line list to see if a block frame precedes the specified frame. If so, the top margin should be applied, and the flag set to cache the result. (If not, the top margin will be applied as a result of the generational margin collapsing logic in nsBlockReflowContext::ComputeCollapsedTopMargin(). In this case, the flag won't be set, so subsequent calls to ShouldApplyTopMargin() will continue crawl the line list.) This flag is also set in the nsBlockReflowState constructor if BRS_ISTOPMARGINROOT is set; that is, if the frame being reflowed is a margin root by default.
    BRS_COMPUTEMAXELEMENTSIZE
    This flag is set if reflow should recompute an element's maximum size. It is set in the nsBlockReflowState constructor if the "maxElementSize" member of the nsHTMLReflowMetrics object has been provided by (the parent frame?).
    BRS_COMPUTEMAXWIDTH
    This flag is set if reflow should recompute a frame's maximum width; for example, during first-pass table reflow. When this is set, nsBlockFrame::ReflowLine will flow the first line and each unwrapped line in the block twice.

    nsBlockReflowContext

    Encapsulates the transient reflow state for a nsLineBox that contains a block frame.

    mNextRCFrame

    During an incremental reflow, this member holds current frame in the reflow chain.

    nsLineLayout

    Encapsulates the transient reflow state for a nsLineBox that contains inline frames. A new nsLineLayout object is created for each inline linebox that is flowed.

    mFlags
    LL_ENDSINWHITESPACE
    Set to true by default when starting line layout.
    LL_UNDERSTANDSNWHITESPACE
    LL_TEXTSTARTSWITHNBSP
    LL_FIRSTLETTERSTYLEOK
    LL_ISTOPOFPAGE
    LL_UPDATEDBAND
    LL_IMPACTEDBYFLOATERS
    LL_LASTFLOATERWASLETTERFRAME
    LL_CANPLACEFLOATER
    LL_KNOWSTRICTMODE
    LL_INSTRICTMODE
    LL_LINEENDSINBR

    PerFrameData

    (Why isn't this just stored in the frame?)

    mFlags
    PFD_RELATIVEPOS
    PFD_ISTEXTFRAME
    PFD_ISNONEMPTYTEXTFRAME
    PFD_ISNONWHITESPACETEXTFRAME
    PFD_ISLETTERFRAME
    PFD_ISSTICKY
    PFD_ISBULLET

    PerSpanData

    In nsLineLayout, a "span" is a container inline frame, and a "frame" is one of its children. Perhaps PerParentData and PerChildData would be better names? nsLineLayout::BeginLineReflow creates the initial PerSpanData which is called the "root span". nsInlineFrame::ReflowFrames creates a new PerSpanData when it calls nsLineLayout::BeginSpan: at this time, the nsLineLayout object's mCurrentSpan is switched to the new span. The new span records the old mCurrentSpan as its parent. After reflowing the child inline frames, nsInlineFrame::ReflowFrames calls nsLineLayout::EndSpan, which pops the PerSpanData and re-sets mCurrentSpan.

    mFirstFrame

    The first PerFrameData structure in the span.

    mLastFrame

    The last PerFrameData structure frame in the span. PerFrameData structures are added to the span as they are reflowed. mLastFrame may also be directly manipulated if a line is split, or if frames are pushed from one line to the next.

    mFrame

    The PerFrameData of the inline frame that "owns" the span, or null if this is the root span. mFrame is initialized to the containing inline frame's PerFrameData when a new PerSpanData is pushed in nsLineLayout::BeginSpan.

    Original Document Information

    • Author(s): Chris Waterson
    • Last Updated Date: December 4, 2004
    • 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: Sheppy, Kohei, DBaron
    Last updated by: DBaron,