layout/doc/HLD-SpaceManager.html

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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. &nbsp;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. &nbsp;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 &nbsp;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. &nbsp;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). &nbsp;<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. &nbsp;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 &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;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. &nbsp;This is used to communicate information about the space in
michael@0 107 the band to the clients of the SpaceManager. &nbsp;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 &nbsp;<br>
michael@0 120
michael@0 121 <ul>
michael@0 122 <li>An instance is created&nbsp;</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 &nbsp;</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. &nbsp;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. &nbsp;This happens in the method <i>nsBlockReflowState::RecoverFloats</i> and
michael@0 139 <i>nsBlockReflowState::FlowAndPlaceFloat</i> (formerly this was done in nsBlockFrame::UpdateSpaceManager). &nbsp;<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. &nbsp;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.&nbsp; <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>

mercurial