Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | <!-- This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | - License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
michael@0 | 4 | |
michael@0 | 5 | <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
michael@0 | 6 | <html> |
michael@0 | 7 | <head> |
michael@0 | 8 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
michael@0 | 9 | <meta name="GENERATOR" content="Mozilla/4.61 [en] (X11; I; Linux 2.2.5-22 i686) [Netscape]"> |
michael@0 | 10 | </head> |
michael@0 | 11 | <body> |
michael@0 | 12 | |
michael@0 | 13 | <h1> |
michael@0 | 14 | <u>Block Layout</u></h1> |
michael@0 | 15 | This document attempts to describe how "block" layout works in the mozilla |
michael@0 | 16 | layout engine. |
michael@0 | 17 | <p><tt>nsBlockFrame</tt> implements layout behavior that conforms to the |
michael@0 | 18 | CSS "display:block" and "display: list-item" layout. It has several responsibilities: |
michael@0 | 19 | <ol> |
michael@0 | 20 | <li> |
michael@0 | 21 | Line layout. The block is responsible for flowing inline elements |
michael@0 | 22 | into "lines" and applying all of the css behavior as one might expect, |
michael@0 | 23 | including line-height, vertical-align, relative positioning, etc.</li> |
michael@0 | 24 | |
michael@0 | 25 | <li> |
michael@0 | 26 | Float management. The block is responsible for the reflow and placement |
michael@0 | 27 | of floating elements.</li> |
michael@0 | 28 | |
michael@0 | 29 | <li> |
michael@0 | 30 | Child block management. Blocks can contain inline elements and block elements. |
michael@0 | 31 | Hence, blocks are responsible for reflowing child blocks. The majority |
michael@0 | 32 | of that logic has been split out into nsBlockReflowContext, but a fair |
michael@0 | 33 | amount remains here.</li> |
michael@0 | 34 | |
michael@0 | 35 | <li> |
michael@0 | 36 | Supporting table reflow. The block has to carefully compute the "max-element-size" |
michael@0 | 37 | information needed by tables. Hence, any time changes are made here one |
michael@0 | 38 | should always run the table regression tests because the odds are you broke |
michael@0 | 39 | one of them!</li> |
michael@0 | 40 | </ol> |
michael@0 | 41 | |
michael@0 | 42 | <h3> |
michael@0 | 43 | <u>The Big Picture for Block Reflow</u></h3> |
michael@0 | 44 | The block frame uses a list of nsLineBox's to keep track of each "line" |
michael@0 | 45 | of frames it manages. There are two types of lines: |
michael@0 | 46 | <blockquote>"inline" lines which contain only inline elements |
michael@0 | 47 | <br>"block" lines which contain exactly one block element</blockquote> |
michael@0 | 48 | Each line has a "dirty" bit which indicates that it needs reflow. Reflow |
michael@0 | 49 | consists of identifying which lines need to be marked dirty and then reflowing |
michael@0 | 50 | all lines. For lines which are "clean" the reflow logic will endeavor to |
michael@0 | 51 | recover the state of reflow <i>as if the line had been reflowed</i>. This |
michael@0 | 52 | saves time and allows for a faster incremental reflow. For lines which |
michael@0 | 53 | are dirty, the line is reflowed appropriately. |
michael@0 | 54 | <p>The only special thing about incremental reflow command handling is |
michael@0 | 55 | that it marks lines dirty before proceeding, and keeps track of the child |
michael@0 | 56 | frame that is the next frame on the reflow command path. |
michael@0 | 57 | <p>Here is a list of the various classes involved in block layout: |
michael@0 | 58 | <p><b>nsBlockFrame</b> |
michael@0 | 59 | <blockquote>The primary culprit.</blockquote> |
michael@0 | 60 | <b>nsBlockReflowState</b> |
michael@0 | 61 | <blockquote>This helper class is used to augment the nsHTMLReflowState |
michael@0 | 62 | with other information needed by the block reflow logic during reflow. |
michael@0 | 63 | It is a temporary object that is designed to live on the processor stack |
michael@0 | 64 | and contains "running" state used by the blocks reflow logic.</blockquote> |
michael@0 | 65 | <b>nsBlockBandData</b> |
michael@0 | 66 | <blockquote>Another helper class that wraps up management of a space manager |
michael@0 | 67 | (nsISpaceManager, nsSpaceManager) and nsBandData. It also assists in management |
michael@0 | 68 | of floating elements. While nsSpaceManager is policy free, nsBlockBandData |
michael@0 | 69 | provides specific HTML and CSS policy.</blockquote> |
michael@0 | 70 | <b>nsBlockReflowContext</b> |
michael@0 | 71 | <blockquote>A helper class that encapsulates the logic needed to reflow |
michael@0 | 72 | a child block frame. This is used by the block code reflow a child block |
michael@0 | 73 | and to reflow floating elements (which are to be treated as blocks according |
michael@0 | 74 | to the CSS2 spec).</blockquote> |
michael@0 | 75 | <b>nsLineBox</b> |
michael@0 | 76 | <blockquote>A data class used to store line information for the block frame |
michael@0 | 77 | code. Each line has a list of children (though the frames are linked together |
michael@0 | 78 | across lines to maintain the sibling list for nsIFrame::FirstChild) and |
michael@0 | 79 | some other state used to assist in incremental reflow.</blockquote> |
michael@0 | 80 | <b>nsLineLayout</b> |
michael@0 | 81 | <blockquote>This class is the line layout engine. Its a passive entity |
michael@0 | 82 | in the sense that its the responsibility of the block/inline code to use |
michael@0 | 83 | the class (this is done so that the line layout engine doesn't have to |
michael@0 | 84 | manage child frame lists so that both nsBlockFrame and nsInlineFrame can |
michael@0 | 85 | use the class).</blockquote> |
michael@0 | 86 | <b>nsTextRun</b> |
michael@0 | 87 | <blockquote>This is a data class used to store text run information. Text |
michael@0 | 88 | runs are <i>logically</i> contiguous runs of text (they may or may not |
michael@0 | 89 | be structurally contiguous). The block frame stores a pointer to a list |
michael@0 | 90 | of nsTextRun's and during line layout provides the list to the nsLineLayout |
michael@0 | 91 | engine so that when text is reflowed the text layout code (nsTextFrame) |
michael@0 | 92 | can find related text to properly handle word breaking.</blockquote> |
michael@0 | 93 | |
michael@0 | 94 | <h3> |
michael@0 | 95 | <u>Frame construction methods</u></h3> |
michael@0 | 96 | When the blocks child list is modified (AppendFrames, InsertFrames, RemoveFrame) |
michael@0 | 97 | the block code updates its nsLineBox list. Since each nsLineBox is typed |
michael@0 | 98 | (some are marked "inline" and some are marked "block"), the update logic |
michael@0 | 99 | maintains the invariant of "one block frame per block line". |
michael@0 | 100 | <p>When structural changes are made to the blocks children (append/insert/remove) |
michael@0 | 101 | the block code updates the line's and then marks the affected lines "dirty" |
michael@0 | 102 | (each nsLineBox has a dirty bit). After the structural changes are finished |
michael@0 | 103 | then the block will generate an incremental reflow command of type "ReflowDirty". |
michael@0 | 104 | <h3> |
michael@0 | 105 | <u>Line Layout</u></h3> |
michael@0 | 106 | Line layout consists of the placement of inline elements on a line until |
michael@0 | 107 | there is no more room on the line. At that point the line is "broken" and |
michael@0 | 108 | continued on the next line. This process continues until all inline elements |
michael@0 | 109 | have been exhausted. The block code maintains a list of "nsLineBox"'s to |
michael@0 | 110 | facilitate this. These are used instead of frames because they use less |
michael@0 | 111 | memory and because it allows the block to directly control their behavior. |
michael@0 | 112 | <p>The helper class nsLineLayout provides the majority of the line layout |
michael@0 | 113 | behavior needed by the block. |
michael@0 | 114 | <p>The block does keep "text-run" information around for the nsLineLayout |
michael@0 | 115 | logic to use during reflow. Text runs keep track of logically adjacent |
michael@0 | 116 | pieces of text within a block. This information is essential for properly |
michael@0 | 117 | computing line and word breaking. Why? Well, because in html you can write |
michael@0 | 118 | something like this: |
michael@0 | 119 | <p> <p>I <b>W</b>as thinking one day</p> |
michael@0 | 120 | <p>Notice that the word "Was" is composed of two pieces of text, and that |
michael@0 | 121 | they do <i>not</i> have the same parent (content or frame). To properly |
michael@0 | 122 | reflow this and not break the word prematurely after the "W", the text-run |
michael@0 | 123 | information is used by the text frame code to "look ahead" and prevent |
michael@0 | 124 | premature breaking. |
michael@0 | 125 | <p>Lines also keep track of the type of "break" that occurred on the line. |
michael@0 | 126 | This is used, for example, to support html's "<br clear=left>" behavior. |
michael@0 | 127 | <h3> |
michael@0 | 128 | <u>Float Management</u></h3> |
michael@0 | 129 | Since child block elements are containing blocks for floats, the only |
michael@0 | 130 | place where a block frame will see a float is as part of an inline line. |
michael@0 | 131 | Consequently, the nsLineBox will only keep track of floats on inline |
michael@0 | 132 | lines (saving storage for block lines). |
michael@0 | 133 | <p>The nsLineLayout class and the block frame cooperate in the management |
michael@0 | 134 | of floats. Since the frame construction code leaves a "placeholder" frame |
michael@0 | 135 | in-flow where the float was found, when nsLineLayout reflows a placeholder |
michael@0 | 136 | frame it knows to inform the block about it. That triggers the blocks "AddFloat" |
michael@0 | 137 | logic which then determines where the float should be placed (on the |
michael@0 | 138 | current line or below the current line). |
michael@0 | 139 | <p>The block frame uses the space manager to manage the effects of floats, |
michael@0 | 140 | namely the consumption of available space. For example, for a left aligned |
michael@0 | 141 | floating element, the inline elements must be placed to the right of the |
michael@0 | 142 | float. To simplify this process, the spacemanager is used to keep track |
michael@0 | 143 | of available and busy space. Floats when placed mark space as busy and |
michael@0 | 144 | the spacemanager will them compute the available space. Most of this logic |
michael@0 | 145 | is handled by the nsBlockReflowState which uses a helper class, nsBlockBandData, |
michael@0 | 146 | in concert with the space manager, to do the available space computations. |
michael@0 | 147 | <h3> |
michael@0 | 148 | <u>Child Block Placement</u></h3> |
michael@0 | 149 | Child block reflow is done primarily by using the nsBlockReflowContext |
michael@0 | 150 | code. However, a key detail worth mentioning here is how margins are handled. |
michael@0 | 151 | When the nsHTMLReflowState was created, we placed into it the logic for |
michael@0 | 152 | computing margins, border and padding (among other things). Unfortunately, |
michael@0 | 153 | given the css rules for sibling and generational margin collapsing, the |
michael@0 | 154 | nsHTMLReflowState is unable to properly compute top and bottom margins. |
michael@0 | 155 | Hence, the block frame and the nsBlockReflowContext code perform that function. |
michael@0 | 156 | At the time that the nsBlockReflowContext was designed and implemented |
michael@0 | 157 | we thought that it could compute the top-margin itself and then proceed |
michael@0 | 158 | to place the child block element. However, that turned out to be wrong |
michael@0 | 159 | (oh well) because the correct available space isn't known until <i>after</i> |
michael@0 | 160 | the top margin is computed. Hence, there is some unfortunate duplication |
michael@0 | 161 | of reflow state calculations present in the block frame code. |
michael@0 | 162 | <h3> |
michael@0 | 163 | <u>Bullets</u></h3> |
michael@0 | 164 | Another type of block frame is the "display: list-item". List-items use |
michael@0 | 165 | nsBulletFrame's to manage bullet reflow. However, the block is responsible |
michael@0 | 166 | for bullet placement. In most situations, the nsLineLayout class is used |
michael@0 | 167 | to do the placement. However, if the first effective child of the block |
michael@0 | 168 | is another block, then the block has to do the placement itself. |
michael@0 | 169 | <h3> |
michael@0 | 170 | <u>Blank lines</u></h3> |
michael@0 | 171 | Because our content model contains as much of the original source documents |
michael@0 | 172 | content as possible, we end up with a lot of white space that ends up being |
michael@0 | 173 | compressed into nothingness. This white space ends up impacting this logic |
michael@0 | 174 | in several ways. For example: |
michael@0 | 175 | <p> <div> |
michael@0 | 176 | <br> <p>abc</p> |
michael@0 | 177 | <br> <p>def</p> |
michael@0 | 178 | <br> </div> |
michael@0 | 179 | <p>In the content model for the above html, there is white space between |
michael@0 | 180 | the various block elements (some after the <div>, some after the first |
michael@0 | 181 | </p>, again after the second </p>). |
michael@0 | 182 | <p>For css margin collapsing to work properly, each of those instances |
michael@0 | 183 | of white space has to behave as if they didn't exist. Consequently, there |
michael@0 | 184 | is special logic in the inline line reflow code, and in the nsBlockReflowContext |
michael@0 | 185 | code and in the GetTopBlockChild method, to basically ignore such lines. |
michael@0 | 186 | <h3> |
michael@0 | 187 | <u>First-letter style</u></h3> |
michael@0 | 188 | The block contributes, in a small way, to first-letter style reflow. The |
michael@0 | 189 | frame construction code is responsible for creating the list of child frames |
michael@0 | 190 | for all frames, including the block. It manages the creation of letter-frames, |
michael@0 | 191 | where appropriate, so that all the block has to do is reflow them almost |
michael@0 | 192 | normally like other inline frames. |
michael@0 | 193 | <p>There are two things different that the block does: |
michael@0 | 194 | <p>It is responsible for calling nsLineLayout::SetFirstLetterStyleOK |
michael@0 | 195 | <br>It is responsible for continuing to place frames on a line, even after |
michael@0 | 196 | a frame has said "it can't fit". Normally during inline reflow, if a frame |
michael@0 | 197 | comes back and says it can't fit, the block will end the line, push all |
michael@0 | 198 | remaining frames to the next line and pick up the reflow from there after |
michael@0 | 199 | making sure the frame that didn't fit is continued. For letter-frames, |
michael@0 | 200 | this would result in the first-letter being on one line with the remaining |
michael@0 | 201 | text on subsequent lines. Hence, the block code handles this special case. |
michael@0 | 202 | <br> |
michael@0 | 203 | <h3> |
michael@0 | 204 | <u>First-line style</u></h3> |
michael@0 | 205 | First-line is handled entirely by the frame construction code. |
michael@0 | 206 | <br> |
michael@0 | 207 | <br> |
michael@0 | 208 | </body> |
michael@0 | 209 | </html> |