diff options
Diffstat (limited to 'layout/doc/obsolete/block.html')
-rw-r--r-- | layout/doc/obsolete/block.html | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/layout/doc/obsolete/block.html b/layout/doc/obsolete/block.html new file mode 100644 index 000000000..255b84cd6 --- /dev/null +++ b/layout/doc/obsolete/block.html @@ -0,0 +1,209 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.61 [en] (X11; I; Linux 2.2.5-22 i686) [Netscape]"> +</head> +<body> + +<h1> +<u>Block Layout</u></h1> +This document attempts to describe how "block" layout works in the mozilla +layout engine. +<p><tt>nsBlockFrame</tt> implements layout behavior that conforms to the +CSS "display:block" and "display: list-item" layout. It has several responsibilities: +<ol> +<li> + Line layout. The block is responsible for flowing inline elements +into "lines" and applying all of the css behavior as one might expect, +including line-height, vertical-align, relative positioning, etc.</li> + +<li> +Float management. The block is responsible for the reflow and placement +of floating elements.</li> + +<li> +Child block management. Blocks can contain inline elements and block elements. +Hence, blocks are responsible for reflowing child blocks. The majority +of that logic has been split out into nsBlockReflowContext, but a fair +amount remains here.</li> + +<li> +Supporting table reflow. The block has to carefully compute the "max-element-size" +information needed by tables. Hence, any time changes are made here one +should always run the table regression tests because the odds are you broke +one of them!</li> +</ol> + +<h3> +<u>The Big Picture for Block Reflow</u></h3> +The block frame uses a list of nsLineBox's to keep track of each "line" +of frames it manages. There are two types of lines: +<blockquote>"inline" lines which contain only inline elements +<br>"block" lines which contain exactly one block element</blockquote> +Each 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 <i>as if the line had been reflowed</i>. This +saves time and allows for a faster incremental reflow. For lines which +are dirty, the line is reflowed appropriately. +<p>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. +<p>Here is a list of the various classes involved in block layout: +<p><b>nsBlockFrame</b> +<blockquote>The primary culprit.</blockquote> +<b>nsBlockReflowState</b> +<blockquote>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.</blockquote> +<b>nsBlockBandData</b> +<blockquote>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.</blockquote> +<b>nsBlockReflowContext</b> +<blockquote>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).</blockquote> +<b>nsLineBox</b> +<blockquote>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.</blockquote> +<b>nsLineLayout</b> +<blockquote>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).</blockquote> +<b>nsTextRun</b> +<blockquote>This is a data class used to store text run information. Text +runs are <i>logically</i> 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.</blockquote> + +<h3> +<u>Frame construction methods</u></h3> +When the blocks child list is modified (AppendFrames, InsertFrames, RemoveFrame) +the block code updates its nsLineBox list. Since each nsLineBox is typed +(some are marked "inline" and some are marked "block"), the update logic +maintains the invariant of "one block frame per block line". +<p>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". +<h3> +<u>Line Layout</u></h3> +Line layout consists of the placement of inline elements on a line until +there is no more room on the line. At that point the line is "broken" and +continued on the next line. This process continues until all inline elements +have been exhausted. The block code maintains a list of "nsLineBox"'s to +facilitate this. These are used instead of frames because they use less +memory and because it allows the block to directly control their behavior. +<p>The helper class nsLineLayout provides the majority of the line layout +behavior needed by the block. +<p>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> <p>I <b>W</b>as thinking one day</p> +<p>Notice that the word "Was" is composed of two pieces of text, and that +they do <i>not</i> 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. +<p>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. +<h3> +<u>Float Management</u></h3> +Since child block elements are containing blocks for floats, the only +place where a block frame will see a float is as part of an inline line. +Consequently, the nsLineBox will only keep track of floats on inline +lines (saving storage for block lines). +<p>The nsLineLayout class and the block frame cooperate in the management +of floats. Since the frame construction code leaves a "placeholder" frame +in-flow where the float was found, when nsLineLayout reflows a placeholder +frame it knows to inform the block about it. That triggers the blocks "AddFloat" +logic which then determines where the float should be placed (on the +current line or below the current line). +<p>The block frame uses the space manager to manage the effects of floats, +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 +float. To simplify this process, the spacemanager is used to keep track +of available and busy space. Floats 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. +<h3> +<u>Child Block Placement</u></h3> +Child block reflow is done primarily by using the nsBlockReflowContext +code. However, a key detail worth mentioning here is how margins are handled. +When the nsHTMLReflowState was created, we placed into it the logic for +computing margins, border and padding (among other things). Unfortunately, +given the css rules for sibling and generational margin collapsing, the +nsHTMLReflowState is unable to properly compute top and bottom margins. +Hence, the block frame and the nsBlockReflowContext code perform that function. +At the time that the nsBlockReflowContext was designed and implemented +we thought that it could compute the top-margin itself and then proceed +to place the child block element. However, that turned out to be wrong +(oh well) because the correct available space isn't known until <i>after</i> +the top margin is computed. Hence, there is some unfortunate duplication +of reflow state calculations present in the block frame code. +<h3> +<u>Bullets</u></h3> +Another type of block frame is the "display: list-item". List-items use +nsBulletFrame's to manage bullet reflow. However, the block is responsible +for bullet placement. In most situations, the nsLineLayout class is used +to do the placement. However, if the first effective child of the block +is another block, then the block has to do the placement itself. +<h3> +<u>Blank lines</u></h3> +Because our content model contains as much of the original source documents +content as possible, we end up with a lot of white space that ends up being +compressed into nothingness. This white space ends up impacting this logic +in several ways. For example: +<p> <div> +<br> <p>abc</p> +<br> <p>def</p> +<br> </div> +<p>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>). +<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. +<h3> +<u>First-letter style</u></h3> +The block contributes, in a small way, to first-letter style reflow. The +frame construction code is responsible for creating the list of child frames +for all frames, including the block. It manages the creation of letter-frames, +where appropriate, so that all the block has to do is reflow them almost +normally like other inline frames. +<p>There are two things different that the block does: +<p>It is responsible for calling nsLineLayout::SetFirstLetterStyleOK +<br>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. +<br> +<h3> +<u>First-line style</u></h3> +First-line is handled entirely by the frame construction code. +<br> +<br> +</body> +</html> |