nsBlockFrame implements layout behavior that conforms to the CSS "display:block" and "display: list-item" layout. It has several responsibilities:
"inline" lines which contain only inline elementsEach line has a "dirty" bit which indicates that it needs reflow. Reflow consists of identifying which lines need to be marked dirty and then reflowing all lines. For lines which are "clean" the reflow logic will endeavor to recover the state of reflow as if the line had been reflowed. This saves time and allows for a faster incremental reflow. For lines which are dirty, the line is reflowed appropriately.
"block" lines which contain exactly one block element
The only special thing about incremental reflow command handling is that it marks lines dirty before proceeding, and keeps track of the child frame that is the next frame on the reflow command path.
Here is a list of the various classes involved in block layout:
nsBlockFrame
The primary culprit.nsBlockReflowState
This helper class is used to augment the nsHTMLReflowState with other information needed by the block reflow logic during reflow. It is a temporary object that is designed to live on the processor stack and contains "running" state used by the blocks reflow logic.nsBlockBandData
Another helper class that wraps up management of a space manager (nsISpaceManager, nsSpaceManager) and nsBandData. It also assists in management of floating elements. While nsSpaceManager is policy free, nsBlockBandData provides specific HTML and CSS policy.nsBlockReflowContext
A helper class that encapsulates the logic needed to reflow a child block frame. This is used by the block code reflow a child block and to reflow floating elements (which are to be treated as blocks according to the CSS2 spec).nsLineBox
A data class used to store line information for the block frame code. Each line has a list of children (though the frames are linked together across lines to maintain the sibling list for nsIFrame::FirstChild) and some other state used to assist in incremental reflow.nsLineLayout
This class is the line layout engine. Its a passive entity in the sense that its the responsibility of the block/inline code to use the class (this is done so that the line layout engine doesn't have to manage child frame lists so that both nsBlockFrame and nsInlineFrame can use the class).nsTextRun
This is a data class used to store text run information. Text runs are logically contiguous runs of text (they may or may not be structurally contiguous). The block frame stores a pointer to a list of nsTextRun's and during line layout provides the list to the nsLineLayout engine so that when text is reflowed the text layout code (nsTextFrame) can find related text to properly handle word breaking.
When structural changes are made to the blocks children (append/insert/remove) the block code updates the line's and then marks the affected lines "dirty" (each nsLineBox has a dirty bit). After the structural changes are finished then the block will generate an incremental reflow command of type "ReflowDirty".
The helper class nsLineLayout provides the majority of the line layout behavior needed by the block.
The block does keep "text-run" information around for the nsLineLayout logic to use during reflow. Text runs keep track of logically adjacent pieces of text within a block. This information is essential for properly computing line and word breaking. Why? Well, because in html you can write something like this:
<p>I <b>W</b>as thinking one day</p>
Notice that the word "Was" is composed of two pieces of text, and that they do not have the same parent (content or frame). To properly reflow this and not break the word prematurely after the "W", the text-run information is used by the text frame code to "look ahead" and prevent premature breaking.
Lines also keep track of the type of "break" that occurred on the line. This is used, for example, to support html's "<br clear=left>" behavior.
The nsLineLayout class and the block frame cooperate in the management of floaters. Since the frame construction code leaves a "placeholder" frame in-flow where the floater was found, when nsLineLayout reflows a placeholder frame it knows to inform the block about it. That triggers the blocks "AddFloater" logic which then determines where the floater should be placed (on the current line or below the current line).
The block frame uses the space manager to manage the effects of floaters, namely the consumption of available space. For example, for a left aligned floating element, the inline elements must be placed to the right of the floater. To simplify this process, the spacemanager is used to keep track of available and busy space. Floaters when placed mark space as busy and the spacemanager will them compute the available space. Most of this logic is handled by the nsBlockReflowState which uses a helper class, nsBlockBandData, in concert with the space manager, to do the available space computations.
<div>
<p>abc</p>
<p>def</p>
</div>
In the content model for the above html, there is white space between the various block elements (some after the <div>, some after the first </p>, again after the second </p>).
For css margin collapsing to work properly, each of those instances of white space has to behave as if they didn't exist. Consequently, there is special logic in the inline line reflow code, and in the nsBlockReflowContext code and in the GetTopBlockChild method, to basically ignore such lines.
There are two things different that the block does:
It is responsible for calling nsLineLayout::SetFirstLetterStyleOK
It is responsible for continuing to place frames on a line, even after
a frame has said "it can't fit". Normally during inline reflow, if a frame
comes back and says it can't fit, the block will end the line, push all
remaining frames to the next line and pick up the reflow from there after
making sure the frame that didn't fit is continued. For letter-frames,
this would result in the first-letter being on one line with the remaining
text on subsequent lines. Hence, the block code handles this special case.