Overview
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 italics. 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 inDidReflow(). 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 inital 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
mOverflowAreawill 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_ISTOPMARGINROOTandBRS_ISBOTTOMMARGINROOTflags.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
nsLineBoxfor each line, and onensLineBoxfor each block child. These are stored as a doubly-linked list in themLinesmember ofnsBlockFrame. - 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
nsBlockReflowStateflagBRS_COMPUTEMAXWIDTHis 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
nsSizeobject. When null, the frame need not compute it.
- nsBlockReflowState
-
Additional reflow state information that the block frame uses along with
nsHTMLReflowState. LikensHTMLReflowState, 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
nsBlockReflowStateconstructor when:-
There is no computed width for the frame in the
nsHTMLReflowState, and -
the frame being reflowed has been given
NS_UNCONSTRAINEDSIZEas its available width in thensHTMLReflowState.
-
There is no computed width for the frame in the
- BRS_UNCONSTRAINEDHEIGHT
-
This flag is set in the
nsBlockReflowStateconstructor when the frame being reflowed has been givenNS_UNCONSTRAINEDSIZEas its available height in thensHTMLReflowState.If set,
NS_UNCONSTRAINEDSIZEis passed tonsLineLayoutas 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
nsBlockReflowStateconstructor when the ``white-space'' style of the block frame ispreornowrap. It is cleared, otherwise. - BRS_ISTOPMARGINROOT
-
This flag is set in the
nsBlockReflowStateconstructor when reflowing a ``block margin root'' frame (i.e., a frame with theNS_BLOCK_MARGIN_ROOTflag 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
nsBlockReflowStateconstructor when reflowing a ``block margin root'' frame (i.e., a frame with theNS_BLOCK_MARGIN_ROOTflag 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 innsBlockReflowContext::ComputeCollapsedTopMargin(). In this case, the flag won't be set, so subsequent calls toShouldApplyTopMargin()will continue crawl the line list.)This flag is also set in the
nsBlockReflowStateconstructor ifBRS_ISTOPMARGINROOTis 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
nsBlockReflowStateconstructor if the ``maxElementSize'' member of thensHTMLReflowMetricsobject 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::ReflowLinewill flow the first line and each unwrapped line in the block twice.
- nsBlockReflowContext
-
Encapsulates the transient reflow state for a
nsLineBoxthat 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
nsLineBoxthat contains inline frames. A newnsLineLayoutobject is created for each inline linebox that is flowed.- mFlags
-
- LL_ENDSINWHITESPACE
-
Set to
trueby 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. PerhapsPerParentDataandPerChildDatawould be better names?nsLineLayout::BeginLineReflowcreates the initialPerSpanDatawhich is called the ``root span''.nsInlineFrame::ReflowFramescreates a newPerSpanDatawhen it callsnsLineLayout::BeginSpan: at this time, thensLineLayoutobject'smCurrentSpanis switched to the new span. The new span records the oldmCurrentSpanas its parent. After reflowing the child inline frames,nsInlineFrame::ReflowFramescallsnsLineLayout::EndSpan, which pops thePerSpanDataand re-setsmCurrentSpan.- mFirstFrame
-
The first
PerFrameDatastructure in the span. - mLastFrame
-
The last
PerFrameDatastructure frame in the span.PerFrameDatastructures are added to the span as they are reflowed.mLastFramemay also be directly manipulated if a line is split, or if frames are pushed from one line to the next. - mFrame
-
The
PerFrameDataof the inline frame that ``owns'' the span, ornullif this is the root span.mFrameis initialized to the containing inline frame'sPerFrameDatawhen a newPerSpanDatais pushed innsLineLayout::BeginSpan.