123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <!-- 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.01 Transitional//EN">
- <html>
- <head>
-
- <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
- <title>Space Manager High Level Design</title>
- <meta name="author" content="Marc Attinasi (attinasi@netscape.com)">
- </head>
- <body>
-
- <h1><font color="#cc0000">Gecko Layout High Level Design Document</font></h1>
-
- <h1>Space Manager High Level Design</h1>
- <br>
-
- <h2>Overview</h2>
- The Space Manager and associated classes and strructures are used by Block
- and Line layout to manage rectangular regions that are occupied and available,
- for correct handling of floated elements and the elements that flow around
- them. When elements are floated to the left or right in a layout, they
- take up space and influence where other elements can be placed. The
- Space Manager is responsible for keeping track of where space is taken up
- and where it is available. This information is used by block layout to correctly
- compute where other floated elements should be placed, and how much space
- is available to normal in-flow elements that flow around the floated bits.<br>
- <br>
- The Space Manager works in concert with several other classes to do its
- job. The classes that are considered part of the Space Manager are:<br>
-
- <ul>
- <li>nsSpaceManager</li>
- <li>nsBandData</li>
- <li>nsBlockBandData</li>
- <li>BandRect / BandList (private structs)</li>
- <li>FrameInfo (private struct)</li>
- <li>nsBandtrapezoid</li>
-
- </ul>
- Outside of the Space Manager itself, the clients of the Space Manager also
- play an inportant part in the management of he available and used space.
- The primary classes that interact with the Space Manager are:<br>
-
- <ul>
- <li>nsBlockReflowState</li>
- <li>nsBlockFrame</li>
- <li>nsBoxToBlockAdaptor</li>
-
- </ul>
- The general interaction model is to create a Space Manager for a block
- frame in the context of a Reflow, and to associate it with the BlockReflowState
- so it is passed down to child frames' reflow methods. After reflow, the
- Space Manager is destroyed. During reflow, the space manager stores
- the space taken up by floats (UpdateSpaceManager in nsBlockFrame) and
- provides information about the space available for other elements (GetAvailableSpace
- in nsBlockReflowState). <br>
- <br>
- Additionally, there is a need to manage impacts to lines caused by
- changes to floated elements. This is referred to as Propagation
- of Float Damage and is handled by the Block Frame, making use of the
- Space Manager. When a float is incrementally reflowed, the Space
- Manager is notified if the float's region has changed. If so, the
- vertical space that has been affected (including both the float's old
- region and the float's new region) is noted in the internal
- nsIntervalSet as potential float damage (the method is
- IncludeInDamage). During the incremental reflow of dirty lines the
- block frame may encounter lines that are NOT dirty. In this case the
- Space Manager is also asked if there is any float damage, and
- if there is then the block further checks to see if that damage
- intersects the area of the non-dirty line, marking it dirty if there
- is intersection. Thus, changes to floats on other lines may
- cause impact to otherwise clean lines, and the Space Manager
- facilitates the detection of this. <h2>Data Model</h2>
-
- <h4>Class/Component Diagram</h4>
-
- <blockquote>
- <div align="Left"><img src="SpaceManagerClasses.png" alt="SpaceManager Class Diagram" idth="500" eight="459" title="Example Class Diagram">
- <br>
- </div>
- </blockquote>
-
- <ul>
- <li>nsSpaceManager: The central point of management of the space taken
- up by floats in a block</li>
- <li>nsBandData: Provides information about the frames occupying a band
- of occupied or available space</li>
- <li>nsBlockBandData: A specialization of nsBandData that is used by
- nsBlockReflowState to determine the available space, float impacts, and
- where floats are cleared. Essentially a CSS-specific wrapper for
- generic nsBandData.</li>
- <li>BandRect: Keeps the bounds of a band, along with the frames associated
- with the band. BandRects are a linked list (provided by PRCListStr
- super-class) and also provide some geometry-management methods (SplitVertically,
- SplitHorizontally) and some methods that query or manipulate the frames associated
- with the band (IsOccupiedBy, AddFrame, RemoveFrame).</li>
- <li>BandList: A subclass of BandRect that provides a list interface
- - Head(), Tail(), IsEmpty(), etc.</li>
- <li>FrameInfo: A structure that keeps information about the rectangle
- associated with a specific frame, in a linked list.</li>
- <li>nsBandTrapezoid: Represents the discrete regions within a band that
- are either Available, Occupied by a single frame, or Occupied by several
- frames. This is used to communicate information about the space in
- the band to the clients of the SpaceManager. There is no internal use
- of the nsBandTrapezoid by the Space Manager, rather it uses its internal
- BandList to create a BandData collection, which is largely made up of nsTrapezoid
- data.<br>
- </li>
-
- </ul>
-
- <h2>Use Case</h2>
-
- <h4>Use Case 1: Space Manager is Created / Destroyed</h4>
- Space Manager instances are created in the nsBlockFrame's Reflow method.
- <br>
-
- <ul>
- <li>An instance is created </li>
- <li>The BlockReflowState's previous Space Manager is saved off.</li>
- <li>The new Space Manager instance is associated with the BlockReflowState.
- </li>
- <li>After the block frame's Reflow has completed, the old Space Manager
- instance is re-associated with the BlockReflowState</li>
- <li>The new Space Manager is destroyed.</li>
-
- </ul>
- If the BlockReflowState already had a Space Manager instance associated
- with it, it is stored off before being replaced, and the returned to the
- BlockReflowState instance after the new one has been destroyed. Thus,
- Space Managers are effectively 'nested' during reflow, with each new block
- introducing its own Space Manager.
- <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
- floated block may be added to it. This happens in the method <i>nsBlockReflowState::RecoverFloats</i> and
- <i>nsBlockReflowState::FlowAndPlaceFloat</i> (formerly this was done in nsBlockFrame::UpdateSpaceManager). <br>
- <br>
- The general algorightm in <i>nsBlockReflowState::RecoverFloats</i> is:<br>
-
- <ul>
- <li>For each line in the block, see if it has floated blocks</li>
- <li>If floats are in the line, iterate over the floats and add each
- one to the Space Manager via the AddRectRegion method. The actual rect
- for the frame is cached in an nsFloatCache so it does not have to be recomputed.</li>
- <li>If the block has any block children, then translate the Space Manager
- to the child block's origin and update the space manager in the context
- for the child block, recursively. When done with the child, restore the Space
- Managers coordinates by translating by the negative of the child block's
- origin. <br>
- </li>
-
- </ul><br>
- The general algorightm in <i>nsBlockReflowState::FlowAndPlaceFloat</i> is:<br>
- <ul>
- <li>The region that the float currently occupies is recorded.</li>
- <li>The band of available space is searched (with nsBlockReflowState::GetAvailableSpace);</li>
- <li>The float frame that is get from the passed nsFloatCache argument is reflowed
- and its rect is retrieved with GetRect;</li>
- <li>The floats margins are added;</li>
- <li>Check if the float can be placed in the acutal band: if not advance to the next band;</li>
- <li>Check the float type and if it can be added to the space manager;</li>
- <li>Align the float to its containing block top if rule
- <a href="http://www.w3.org/TR/REC-CSS2/visuren.html#float-position">CSS2/9.5.1/4</a>
- is not respected;</li>
- <li>Add the float using <i>nsSpaceManager::AddRectRegion</i> </li>
- <li>Compare the area that the float used to occupy with the area that it now occupies: if different,
- record the vertically affected interval using <i>nsSpaceManager::IncludeInDamage</i></li>
- </ul>
- <h4>Use Case 3: Space Manager is used to find available space to reflow
- into</h4>
- The nsBlockFrame makes use of the Space Manager indirectly to get the available
- space to reflow a child block or inline frame into. The block frame uses
- a helper method on the nsBlockReflowState class to do the actual computation
- of available space based on the data in the Space Manager. Here is how it
- works for reflowing an inline frame within a block (this also occurs for
- reflowing a block frame and, partially, for preparing for a resize reflow).<br>
-
- <ul>
- <li>nsBlockFrame first frees all float information for the line that
- is being reflowed.</li>
- <li>GetAvailableSpace is called on the BlockReflowState</li>
- <li>the BlockReflowState calls GetAvailableSpace on its BlockBandData
- instance (which was setup in the BlockReflowState's constructor based on
- the SpaceManager passed in and computed content area).</li>
- <li>BlockBandData then gets the band data from the space manager via
- a call to the Space Manager associated with the BlockBandData instance.</li>
- <li>The BlockBandData then walks the collection of trapezoids that were
- returned by the SpaceManager method GetBandData (as nsBandData wrappers)
- and determines the right-most edge of the available space.</li>
- <li>The BlockReflowState then stores this available space rect for use
- in the rest of the reflow chain.<br>
- </li>
-
- </ul>
-
- <h4>Use Case 4: Propagation of Float Damage: detecting and handling float
- damage</h4>
- This process is driven by the Block Frame.<br>
-
- <ul>
- <li>A non-dirty line is encountered by the Block Frame in ReflowDirtyLines</li>
- <li>Block Frame calls its PropagateFloatDamage method</li>
- <li>The Space Manager is checked to see if there is any float damage</li>
- <li>If there is, then the block frame asks the Space Manager if the
- line in question intersects the float damage</li>
- <li>If the line does intersect a damage interval, then the line is marked
- dirty</li>
- <li>If the line does not intersect a damage interval, it may still be
- marked dirty if:</li>
-
- <ul>
- <li>it was impacted by floats before, but is not any longer</li>
- <li>it was not impacted by floats befre, but is now</li>
- <li><a name="block-line-impact"></a>
- it is impacted by floats and is a block<br>
- </li>
-
- </ul>
-
- </ul>
- <br>
-
- <hr width="100%" size="2"><br>
-
- <h1><font color="#ff0000">Problems / bugs found during documentation:</font></h1>
-
- <ul>
- <li>BandRect and BandList are public in nsSpaceManager.h - should be
- private (compiles fine)</li>
- <li>nsSpaceManager data members are declared protected, but there are
- no subclasses. Should be private (compiles fine)</li>
- <li>nsBlockFrame::Paint is mucking with nsBlockBandData in and #if 0
- block - remove that and the include (compiles fine)</li>
- <li>nsSpaceManger has no way of clearing the float damage interval
- set - this might be needed if the SpaceManager persists beyond a Reflow</li>
- </ul>
- <br>
- <br>
-
- </body>
- </html>
|