Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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.01 Transitional//EN"> |
michael@0 | 6 | <html> |
michael@0 | 7 | <head> |
michael@0 | 8 | |
michael@0 | 9 | <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> |
michael@0 | 10 | <title>Space Manager High Level Design</title> |
michael@0 | 11 | <meta name="author" content="Marc Attinasi (attinasi@netscape.com)"> |
michael@0 | 12 | </head> |
michael@0 | 13 | <body> |
michael@0 | 14 | |
michael@0 | 15 | <h1><font color="#cc0000">Gecko Layout High Level Design Document</font></h1> |
michael@0 | 16 | |
michael@0 | 17 | <h1>Space Manager High Level Design</h1> |
michael@0 | 18 | <br> |
michael@0 | 19 | |
michael@0 | 20 | <h2>Overview</h2> |
michael@0 | 21 | The Space Manager and associated classes and strructures are used by Block |
michael@0 | 22 | and Line layout to manage rectangular regions that are occupied and available, |
michael@0 | 23 | for correct handling of floated elements and the elements that flow around |
michael@0 | 24 | them. When elements are floated to the left or right in a layout, they |
michael@0 | 25 | take up space and influence where other elements can be placed. The |
michael@0 | 26 | Space Manager is responsible for keeping track of where space is taken up |
michael@0 | 27 | and where it is available. This information is used by block layout to correctly |
michael@0 | 28 | compute where other floated elements should be placed, and how much space |
michael@0 | 29 | is available to normal in-flow elements that flow around the floated bits.<br> |
michael@0 | 30 | <br> |
michael@0 | 31 | The Space Manager works in concert with several other classes to do its |
michael@0 | 32 | job. The classes that are considered part of the Space Manager are:<br> |
michael@0 | 33 | |
michael@0 | 34 | <ul> |
michael@0 | 35 | <li>nsSpaceManager</li> |
michael@0 | 36 | <li>nsBandData</li> |
michael@0 | 37 | <li>nsBlockBandData</li> |
michael@0 | 38 | <li>BandRect / BandList (private structs)</li> |
michael@0 | 39 | <li>FrameInfo (private struct)</li> |
michael@0 | 40 | <li>nsBandtrapezoid</li> |
michael@0 | 41 | |
michael@0 | 42 | </ul> |
michael@0 | 43 | Outside of the Space Manager itself, the clients of the Space Manager also |
michael@0 | 44 | play an inportant part in the management of he available and used space. |
michael@0 | 45 | The primary classes that interact with the Space Manager are:<br> |
michael@0 | 46 | |
michael@0 | 47 | <ul> |
michael@0 | 48 | <li>nsBlockReflowState</li> |
michael@0 | 49 | <li>nsBlockFrame</li> |
michael@0 | 50 | <li>nsBoxToBlockAdaptor</li> |
michael@0 | 51 | |
michael@0 | 52 | </ul> |
michael@0 | 53 | The general interaction model is to create a Space Manager for a block |
michael@0 | 54 | frame in the context of a Reflow, and to associate it with the BlockReflowState |
michael@0 | 55 | so it is passed down to child frames' reflow methods. After reflow, the |
michael@0 | 56 | Space Manager is destroyed. During reflow, the space manager stores |
michael@0 | 57 | the space taken up by floats (UpdateSpaceManager in nsBlockFrame) and |
michael@0 | 58 | provides information about the space available for other elements (GetAvailableSpace |
michael@0 | 59 | in nsBlockReflowState). <br> |
michael@0 | 60 | <br> |
michael@0 | 61 | Additionally, there is a need to manage impacts to lines caused by |
michael@0 | 62 | changes to floated elements. This is referred to as Propagation |
michael@0 | 63 | of Float Damage and is handled by the Block Frame, making use of the |
michael@0 | 64 | Space Manager. When a float is incrementally reflowed, the Space |
michael@0 | 65 | Manager is notified if the float's region has changed. If so, the |
michael@0 | 66 | vertical space that has been affected (including both the float's old |
michael@0 | 67 | region and the float's new region) is noted in the internal |
michael@0 | 68 | nsIntervalSet as potential float damage (the method is |
michael@0 | 69 | IncludeInDamage). During the incremental reflow of dirty lines the |
michael@0 | 70 | block frame may encounter lines that are NOT dirty. In this case the |
michael@0 | 71 | Space Manager is also asked if there is any float damage, and |
michael@0 | 72 | if there is then the block further checks to see if that damage |
michael@0 | 73 | intersects the area of the non-dirty line, marking it dirty if there |
michael@0 | 74 | is intersection. Thus, changes to floats on other lines may |
michael@0 | 75 | cause impact to otherwise clean lines, and the Space Manager |
michael@0 | 76 | facilitates the detection of this. <h2>Data Model</h2> |
michael@0 | 77 | |
michael@0 | 78 | <h4>Class/Component Diagram</h4> |
michael@0 | 79 | |
michael@0 | 80 | <blockquote> |
michael@0 | 81 | <div align="Left"><img src="SpaceManagerClasses.png" alt="SpaceManager Class Diagram" idth="500" eight="459" title="Example Class Diagram"> |
michael@0 | 82 | <br> |
michael@0 | 83 | </div> |
michael@0 | 84 | </blockquote> |
michael@0 | 85 | |
michael@0 | 86 | <ul> |
michael@0 | 87 | <li>nsSpaceManager: The central point of management of the space taken |
michael@0 | 88 | up by floats in a block</li> |
michael@0 | 89 | <li>nsBandData: Provides information about the frames occupying a band |
michael@0 | 90 | of occupied or available space</li> |
michael@0 | 91 | <li>nsBlockBandData: A specialization of nsBandData that is used by |
michael@0 | 92 | nsBlockReflowState to determine the available space, float impacts, and |
michael@0 | 93 | where floats are cleared. Essentially a CSS-specific wrapper for |
michael@0 | 94 | generic nsBandData.</li> |
michael@0 | 95 | <li>BandRect: Keeps the bounds of a band, along with the frames associated |
michael@0 | 96 | with the band. BandRects are a linked list (provided by PRCListStr |
michael@0 | 97 | super-class) and also provide some geometry-management methods (SplitVertically, |
michael@0 | 98 | SplitHorizontally) and some methods that query or manipulate the frames associated |
michael@0 | 99 | with the band (IsOccupiedBy, AddFrame, RemoveFrame).</li> |
michael@0 | 100 | <li>BandList: A subclass of BandRect that provides a list interface |
michael@0 | 101 | - Head(), Tail(), IsEmpty(), etc.</li> |
michael@0 | 102 | <li>FrameInfo: A structure that keeps information about the rectangle |
michael@0 | 103 | associated with a specific frame, in a linked list.</li> |
michael@0 | 104 | <li>nsBandTrapezoid: Represents the discrete regions within a band that |
michael@0 | 105 | are either Available, Occupied by a single frame, or Occupied by several |
michael@0 | 106 | frames. This is used to communicate information about the space in |
michael@0 | 107 | the band to the clients of the SpaceManager. There is no internal use |
michael@0 | 108 | of the nsBandTrapezoid by the Space Manager, rather it uses its internal |
michael@0 | 109 | BandList to create a BandData collection, which is largely made up of nsTrapezoid |
michael@0 | 110 | data.<br> |
michael@0 | 111 | </li> |
michael@0 | 112 | |
michael@0 | 113 | </ul> |
michael@0 | 114 | |
michael@0 | 115 | <h2>Use Case</h2> |
michael@0 | 116 | |
michael@0 | 117 | <h4>Use Case 1: Space Manager is Created / Destroyed</h4> |
michael@0 | 118 | Space Manager instances are created in the nsBlockFrame's Reflow method. |
michael@0 | 119 | <br> |
michael@0 | 120 | |
michael@0 | 121 | <ul> |
michael@0 | 122 | <li>An instance is created </li> |
michael@0 | 123 | <li>The BlockReflowState's previous Space Manager is saved off.</li> |
michael@0 | 124 | <li>The new Space Manager instance is associated with the BlockReflowState. |
michael@0 | 125 | </li> |
michael@0 | 126 | <li>After the block frame's Reflow has completed, the old Space Manager |
michael@0 | 127 | instance is re-associated with the BlockReflowState</li> |
michael@0 | 128 | <li>The new Space Manager is destroyed.</li> |
michael@0 | 129 | |
michael@0 | 130 | </ul> |
michael@0 | 131 | If the BlockReflowState already had a Space Manager instance associated |
michael@0 | 132 | with it, it is stored off before being replaced, and the returned to the |
michael@0 | 133 | BlockReflowState instance after the new one has been destroyed. Thus, |
michael@0 | 134 | Space Managers are effectively 'nested' during reflow, with each new block |
michael@0 | 135 | introducing its own Space Manager. |
michael@0 | 136 | |
michael@0 | 137 | <h4>Use Case 2: Float is added to the Space Manager</h4> After a Space Manager is created for a block context's reflow chain, a |
michael@0 | 138 | floated block may be added to it. This happens in the method <i>nsBlockReflowState::RecoverFloats</i> and |
michael@0 | 139 | <i>nsBlockReflowState::FlowAndPlaceFloat</i> (formerly this was done in nsBlockFrame::UpdateSpaceManager). <br> |
michael@0 | 140 | <br> |
michael@0 | 141 | The general algorightm in <i>nsBlockReflowState::RecoverFloats</i> is:<br> |
michael@0 | 142 | |
michael@0 | 143 | <ul> |
michael@0 | 144 | <li>For each line in the block, see if it has floated blocks</li> |
michael@0 | 145 | <li>If floats are in the line, iterate over the floats and add each |
michael@0 | 146 | one to the Space Manager via the AddRectRegion method. The actual rect |
michael@0 | 147 | for the frame is cached in an nsFloatCache so it does not have to be recomputed.</li> |
michael@0 | 148 | <li>If the block has any block children, then translate the Space Manager |
michael@0 | 149 | to the child block's origin and update the space manager in the context |
michael@0 | 150 | for the child block, recursively. When done with the child, restore the Space |
michael@0 | 151 | Managers coordinates by translating by the negative of the child block's |
michael@0 | 152 | origin. <br> |
michael@0 | 153 | </li> |
michael@0 | 154 | |
michael@0 | 155 | </ul><br> |
michael@0 | 156 | |
michael@0 | 157 | The general algorightm in <i>nsBlockReflowState::FlowAndPlaceFloat</i> is:<br> |
michael@0 | 158 | <ul> |
michael@0 | 159 | <li>The region that the float currently occupies is recorded.</li> |
michael@0 | 160 | <li>The band of available space is searched (with nsBlockReflowState::GetAvailableSpace);</li> |
michael@0 | 161 | <li>The float frame that is get from the passed nsFloatCache argument is reflowed |
michael@0 | 162 | and its rect is retrieved with GetRect;</li> |
michael@0 | 163 | <li>The floats margins are added;</li> |
michael@0 | 164 | <li>Check if the float can be placed in the acutal band: if not advance to the next band;</li> |
michael@0 | 165 | <li>Check the float type and if it can be added to the space manager;</li> |
michael@0 | 166 | <li>Align the float to its containing block top if rule |
michael@0 | 167 | <a href="http://www.w3.org/TR/REC-CSS2/visuren.html#float-position">CSS2/9.5.1/4</a> |
michael@0 | 168 | is not respected;</li> |
michael@0 | 169 | <li>Add the float using <i>nsSpaceManager::AddRectRegion</i> </li> |
michael@0 | 170 | <li>Compare the area that the float used to occupy with the area that it now occupies: if different, |
michael@0 | 171 | record the vertically affected interval using <i>nsSpaceManager::IncludeInDamage</i></li> |
michael@0 | 172 | </ul> |
michael@0 | 173 | <h4>Use Case 3: Space Manager is used to find available space to reflow |
michael@0 | 174 | into</h4> |
michael@0 | 175 | The nsBlockFrame makes use of the Space Manager indirectly to get the available |
michael@0 | 176 | space to reflow a child block or inline frame into. The block frame uses |
michael@0 | 177 | a helper method on the nsBlockReflowState class to do the actual computation |
michael@0 | 178 | of available space based on the data in the Space Manager. Here is how it |
michael@0 | 179 | works for reflowing an inline frame within a block (this also occurs for |
michael@0 | 180 | reflowing a block frame and, partially, for preparing for a resize reflow).<br> |
michael@0 | 181 | |
michael@0 | 182 | <ul> |
michael@0 | 183 | <li>nsBlockFrame first frees all float information for the line that |
michael@0 | 184 | is being reflowed.</li> |
michael@0 | 185 | <li>GetAvailableSpace is called on the BlockReflowState</li> |
michael@0 | 186 | <li>the BlockReflowState calls GetAvailableSpace on its BlockBandData |
michael@0 | 187 | instance (which was setup in the BlockReflowState's constructor based on |
michael@0 | 188 | the SpaceManager passed in and computed content area).</li> |
michael@0 | 189 | <li>BlockBandData then gets the band data from the space manager via |
michael@0 | 190 | a call to the Space Manager associated with the BlockBandData instance.</li> |
michael@0 | 191 | <li>The BlockBandData then walks the collection of trapezoids that were |
michael@0 | 192 | returned by the SpaceManager method GetBandData (as nsBandData wrappers) |
michael@0 | 193 | and determines the right-most edge of the available space.</li> |
michael@0 | 194 | <li>The BlockReflowState then stores this available space rect for use |
michael@0 | 195 | in the rest of the reflow chain.<br> |
michael@0 | 196 | </li> |
michael@0 | 197 | |
michael@0 | 198 | </ul> |
michael@0 | 199 | |
michael@0 | 200 | <h4>Use Case 4: Propagation of Float Damage: detecting and handling float |
michael@0 | 201 | damage</h4> |
michael@0 | 202 | This process is driven by the Block Frame.<br> |
michael@0 | 203 | |
michael@0 | 204 | <ul> |
michael@0 | 205 | <li>A non-dirty line is encountered by the Block Frame in ReflowDirtyLines</li> |
michael@0 | 206 | <li>Block Frame calls its PropagateFloatDamage method</li> |
michael@0 | 207 | <li>The Space Manager is checked to see if there is any float damage</li> |
michael@0 | 208 | <li>If there is, then the block frame asks the Space Manager if the |
michael@0 | 209 | line in question intersects the float damage</li> |
michael@0 | 210 | <li>If the line does intersect a damage interval, then the line is marked |
michael@0 | 211 | dirty</li> |
michael@0 | 212 | <li>If the line does not intersect a damage interval, it may still be |
michael@0 | 213 | marked dirty if:</li> |
michael@0 | 214 | |
michael@0 | 215 | <ul> |
michael@0 | 216 | <li>it was impacted by floats before, but is not any longer</li> |
michael@0 | 217 | <li>it was not impacted by floats befre, but is now</li> |
michael@0 | 218 | <li><a name="block-line-impact"></a> |
michael@0 | 219 | it is impacted by floats and is a block<br> |
michael@0 | 220 | </li> |
michael@0 | 221 | |
michael@0 | 222 | </ul> |
michael@0 | 223 | |
michael@0 | 224 | </ul> |
michael@0 | 225 | <br> |
michael@0 | 226 | |
michael@0 | 227 | <hr width="100%" size="2"><br> |
michael@0 | 228 | |
michael@0 | 229 | <h1><font color="#ff0000">Problems / bugs found during documentation:</font></h1> |
michael@0 | 230 | |
michael@0 | 231 | <ul> |
michael@0 | 232 | <li>BandRect and BandList are public in nsSpaceManager.h - should be |
michael@0 | 233 | private (compiles fine)</li> |
michael@0 | 234 | <li>nsSpaceManager data members are declared protected, but there are |
michael@0 | 235 | no subclasses. Should be private (compiles fine)</li> |
michael@0 | 236 | <li>nsBlockFrame::Paint is mucking with nsBlockBandData in and #if 0 |
michael@0 | 237 | block - remove that and the include (compiles fine)</li> |
michael@0 | 238 | <li>nsSpaceManger has no way of clearing the float damage interval |
michael@0 | 239 | set - this might be needed if the SpaceManager persists beyond a Reflow</li> |
michael@0 | 240 | </ul> |
michael@0 | 241 | <br> |
michael@0 | 242 | <br> |
michael@0 | 243 | |
michael@0 | 244 | </body> |
michael@0 | 245 | </html> |