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