зеркало из https://github.com/mozilla/pjs.git
239 строки
11 KiB
HTML
239 строки
11 KiB
HTML
<!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 witht eh 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 floaters (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 Floater Damage
|
|
and is handled by the Block Frame, making use of teh Space Manager. When
|
|
dirty lines are incrementally reflowed, the Space Manger is told about the
|
|
larger of the new or old line combined width, which it records in an internal
|
|
nsIntervalSet as potential floater 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 floater 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 floaters 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.gif" alt="SpaceManager Class Diagram" width="500" height="459" title="Example Class Diagram">
|
|
<br>
|
|
</div>
|
|
</blockquote>
|
|
|
|
<ul>
|
|
<li>nsSpaceManager: The central point of management of the space taken
|
|
up by floaters 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, floater impacts, and
|
|
where floaters 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 Manger 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 Manger is saved off.</li>
|
|
<li>The new Space Manger 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: Floater 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 via the nsBlockFrame
|
|
method UpdateSpaceManager. The general algorightm is:<br>
|
|
|
|
<ul>
|
|
<li>For each line in the block, see if it has floated blocks</li>
|
|
<li>If floaters are in the line, iterate over the floaters and add each
|
|
one to the Space Manger via the AddRectRegion method. The actual rect
|
|
for the frame is cached in an nsFloaterCache so it does nto 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
|
|
fo 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>
|
|
|
|
<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 Manger. 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 floater 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 Floater Damage: remembering floater damage</h4>
|
|
This process is driven by the Block Frame.<br>
|
|
|
|
<ul>
|
|
<li>A dirty line is reflowed</li>
|
|
<li>If the line's combined area has changed then the Space Manager is
|
|
told to include the combined area as a floater damage interval.</li>
|
|
|
|
</ul>
|
|
|
|
<h4>Use Case 5: Propagation of Floater Damage: detecting and handling floater
|
|
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 PropagateFloaterDamage method</li>
|
|
<li>The Space Manger is checked to see if ther is any floater damage</li>
|
|
<li>If there is, then the block frame asks the Space Manager if the
|
|
line in question intersects the floater 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 floaters before, but is not any longer</li>
|
|
<li>it was not impacted by floaters befre, but is now</li>
|
|
<li><a name="block-line-impact"></a>
|
|
it is impacted by floaters 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 floater damage interval
|
|
set - this might be needed if the SpaceManager persists beyond a Reflow</li>
|
|
<li>As dbaron has documetned inteh code, the floater damage logic is
|
|
flawed: it only handles vertical changes to a line's combined area. The
|
|
Floater Damage API on the Space Manger does not support horizontal changes,
|
|
and the block frame does not attempt to handle them either except for the
|
|
case of a <a href="#block-line-impact">block-line impacted by a floater</a>
|
|
.</li>
|
|
|
|
</ul>
|
|
<br>
|
|
<br>
|
|
|
|
</body>
|
|
</html>
|