Blame layout/doc/HLD-SpaceManager.html

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
        
      SpaceManager Class Diagram
      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>