From 5ae73ca7b1185c84d1e8f374d7525ad913b8ec25 Mon Sep 17 00:00:00 2001 From: "attinasi%netscape.com" Date: Wed, 16 Jan 2002 01:06:26 +0000 Subject: [PATCH] New layout documents: templates and space manager documentation. See bug 115310 and join in the fun git-svn-id: svn://10.0.0.236/trunk@112258 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/doc/DD-SpaceManager.html | 279 +++++++++++++++++++++ mozilla/layout/doc/ExampleClassDiagram.jpg | Bin 0 -> 5606 bytes mozilla/layout/doc/HLD-SpaceManager.html | 238 ++++++++++++++++++ mozilla/layout/doc/SpaceManagerClasses.gif | Bin 0 -> 61560 bytes mozilla/layout/doc/dd-template.html | 112 +++++++++ mozilla/layout/doc/hld-template.html | 105 ++++++++ mozilla/layout/doc/index.html | 35 +++ mozilla/layout/doc/overview.html | 176 +++++++++++++ 8 files changed, 945 insertions(+) create mode 100644 mozilla/layout/doc/DD-SpaceManager.html create mode 100644 mozilla/layout/doc/ExampleClassDiagram.jpg create mode 100644 mozilla/layout/doc/HLD-SpaceManager.html create mode 100644 mozilla/layout/doc/SpaceManagerClasses.gif create mode 100644 mozilla/layout/doc/dd-template.html create mode 100644 mozilla/layout/doc/hld-template.html create mode 100644 mozilla/layout/doc/index.html create mode 100644 mozilla/layout/doc/overview.html diff --git a/mozilla/layout/doc/DD-SpaceManager.html b/mozilla/layout/doc/DD-SpaceManager.html new file mode 100644 index 00000000000..32591c39b30 --- /dev/null +++ b/mozilla/layout/doc/DD-SpaceManager.html @@ -0,0 +1,279 @@ + + + + + + Detailed Design Template + + + +

Gecko Layout Detailed Design Document Template

+ +

Space Manger Detailed Design

+ +

Overview

+ The Space Manager and related classes and structures are an important of + the Gecko Layout system, specifically Block Layout.  See the High Level + Design document for an overview of the Space Manager, and as an introduction + to the classes, structures and algorithms container in this, the Detailed + Design Document.
+
+ +
+

nsSpaceManager

+ The Space Manger is the central class is a group of classes that manage + the occupied and available space that exists in horizontal bands across +a canvas.  The primary goal of the Space Manager is to provide information + about those bands of space to support the CSS notion of floated elements.
+
+ There are three important parts to the Space Manger API: the parts that +deal with the coordinate space of the Space Manager, the parts that deal with +the regions managed by the Space Manager, and the parts that manage floater +impact intervals.
+
+ The class nsSpaceManager is declared in the file + nsSpaceManger.h + .  The class is only used in the layout module and cannot be exported + outside of that module (nor does it need to be).  It is not a general + purpose class, and is not intended to be subclasses + .
+
+ Here is the class declaration, taken from the source file as of 01.08.02
+
+ +
/**
* Class for dealing with bands of available space. The space manager
* defines a coordinate space with an origin at (0, 0) that grows down
* and to the right.
*/
class nsSpaceManager {
public:
nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
~nsSpaceManager();

void* operator new(size_t aSize);
void operator delete(void* aPtr, size_t aSize);

static void Shutdown();

/*
* Get the frame that's associated with the space manager. This frame
* created the space manager, and the world coordinate space is
* relative to this frame.
*
* You can use QueryInterface() on this frame to get any additional
* interfaces.
*/
nsIFrame* GetFrame() const { return mFrame; }

/**
* Translate the current origin by the specified (dx, dy). This
* creates a new local coordinate space relative to the current
* coordinate space.
*/
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }

/**
* Returns the current translation from local coordinate space to
* world coordinate space. This represents the accumulated calls to
* Translate().
*/
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }

/**
* Returns the y-most of the bottommost band or 0 if there are no bands.
*
* @return PR_TRUE if there are bands and PR_FALSE if there are no bands
*/
PRBool YMost(nscoord& aYMost) const;

/**
* Returns a band starting at the specified y-offset. The band data
* indicates which parts of the band are available, and which parts
* are unavailable
*
* The band data that is returned is in the coordinate space of the
* local coordinate system.
*
* The local coordinate space origin, the y-offset, and the max size
* describe a rectangle that's used to clip the underlying band of
* available space, i.e.
* {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
* coordinate space
*
* @param aYOffset the y-offset of where the band begins. The coordinate is
* relative to the upper-left corner of the local coordinate space
* @param aMaxSize the size to use to constrain the band data
* @param aBandData [in,out] used to return the list of trapezoids that
* describe the available space and the unavailable space
* @return NS_OK if successful and NS_ERROR_FAILURE if the band data is not
* not large enough. The 'count' member of the band data struct
* indicates how large the array of trapezoids needs to be
*/
nsresult GetBandData(nscoord aYOffset,
const nsSize& aMaxSize,
nsBandData& aBandData) const;

/**
* Add a rectangular region of unavailable space. The space is
* relative to the local coordinate system.
*
* The region is tagged with a frame
*
* @param aFrame the frame used to identify the region. Must not be NULL
* @param aUnavailableSpace the bounding rect of the unavailable space
* @return NS_OK if successful
* NS_ERROR_FAILURE if there is already a region tagged with aFrame
*/
nsresult AddRectRegion(nsIFrame* aFrame,
const nsRect& aUnavailableSpace);

/**
* Resize the rectangular region associated with aFrame by the specified
* deltas. The height change always applies to the bottom edge or the existing
* rect. You specify whether the width change applies to the left or right edge
*
* Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
enum AffectedEdge {LeftEdge, RightEdge};
nsresult ResizeRectRegion(nsIFrame* aFrame,
nscoord aDeltaWidth,
nscoord aDeltaHeight,
AffectedEdge aEdge = RightEdge);

/**
* Offset the region associated with aFrame by the specified amount.
*
* Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);

/**
* Remove the region associated with aFrane.
*
* Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
nsresult RemoveRegion(nsIFrame* aFrame);

/**
* Clears the list of regions representing the unavailable space.
*/
void ClearRegions();

/**
* Methods for dealing with the propagation of float damage during
* reflow.
*/
PRBool HasFloatDamage()
{
return !mFloatDamage.IsEmpty();
}

void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
}

PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
}

#ifdef DEBUG
/**
* Dump the state of the spacemanager out to a file
*/
nsresult List(FILE* out);

void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif

private:
// Structure that maintains information about the region associated
// with a particular frame
struct FrameInfo {
nsIFrame* const mFrame;
nsRect mRect; // rectangular region
FrameInfo* mNext;

FrameInfo(nsIFrame* aFrame, const nsRect& aRect);
#ifdef NS_BUILD_REFCNT_LOGGING
~FrameInfo();
#endif
};

// Doubly linked list of band rects
struct BandRect : PRCListStr {
nscoord mLeft, mTop;
nscoord mRight, mBottom;
PRIntn mNumFrames; // number of frames occupying this rect
union {
nsIFrame* mFrame; // single frame occupying the space
nsVoidArray* mFrames; // list of frames occupying the space
};

BandRect(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom,
nsIFrame*);
BandRect(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom,
nsVoidArray*);
~BandRect();

// List operations
BandRect* Next() const {return (BandRect*)PR_NEXT_LINK(this);}
BandRect* Prev() const {return (BandRect*)PR_PREV_LINK(this);}
void InsertBefore(BandRect* aBandRect) {PR_INSERT_BEFORE(aBandRect, this);}
void InsertAfter(BandRect* aBandRect) {PR_INSERT_AFTER(aBandRect, this);}
void Remove() {PR_REMOVE_LINK(this);}

// Split the band rect into two vertically, with this band rect becoming
// the top part, and a new band rect being allocated and returned for the
// bottom part
//
// Does not insert the new band rect into the linked list
BandRect* SplitVertically(nscoord aBottom);

// Split the band rect into two horizontally, with this band rect becoming
// the left part, and a new band rect being allocated and returned for the
// right part
//
// Does not insert the new band rect into the linked list
BandRect* SplitHorizontally(nscoord aRight);

// Accessor functions
PRBool IsOccupiedBy(const nsIFrame*) const;
void AddFrame(const nsIFrame*);
void RemoveFrame(const nsIFrame*);
PRBool HasSameFrameList(const BandRect* aBandRect) const;
PRInt32 Length() const;
};

// Circular linked list of band rects
struct BandList : BandRect {
BandList();

// Accessors
PRBool IsEmpty() const {return PR_CLIST_IS_EMPTY((PRCListStr*)this);}
BandRect* Head() const {return (BandRect*)PR_LIST_HEAD(this);}
BandRect* Tail() const {return (BandRect*)PR_LIST_TAIL(this);}

// Operations
void Append(BandRect* aBandRect) {PR_APPEND_LINK(aBandRect, this);}

// Remove and delete all the band rects in the list
void Clear();
};


FrameInfo* GetFrameInfoFor(nsIFrame* aFrame);
FrameInfo* CreateFrameInfo(nsIFrame* aFrame, const nsRect& aRect);
void DestroyFrameInfo(FrameInfo*);

void ClearFrameInfo();
void ClearBandRects();

BandRect* GetNextBand(const BandRect* aBandRect) const;
void DivideBand(BandRect* aBand, nscoord aBottom);
PRBool CanJoinBands(BandRect* aBand, BandRect* aPrevBand);
PRBool JoinBands(BandRect* aBand, BandRect* aPrevBand);
void AddRectToBand(BandRect* aBand, BandRect* aBandRect);
void InsertBandRect(BandRect* aBandRect);

nsresult GetBandAvailableSpace(const BandRect* aBand,
nscoord aY,
const nsSize& aMaxSize,
nsBandData& aAvailableSpace) const;

nsIFrame* const mFrame; // frame associated with the space manager
nscoord mX, mY; // translation from local to global coordinate space
BandList mBandList; // header/sentinel for circular linked list of band rects
FrameInfo* mFrameInfoMap;
nsIntervalSet mFloatDamage;

static PRInt32 sCachedSpaceManagerCount;
static void* sCachedSpaceManagers[NS_SPACE_MANAGER_CACHE_SIZE];

nsSpaceManager(const nsSpaceManager&); // no implementation
void operator=(const nsSpaceManager&); // no implementation
};

+ +

Public API

+ +

Life Cycle:

+ The Constructor requires a Presentation Shell, used for arena allocations + mostly, and a frame that this Space Manager is rooted on.  The coordinate + space of this Space Manger is relative to the frame passed in to the constructor.
+ +
  nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
~nsSpaceManager();
+ Operators 'new' and 'delete' are overridden to support a recycler.  Space + Manager instances come and go pretty frequently, and this recycler prevents + excessive heap allocations and the performance penalties associated with +it. The #define NS_SPACE_MANAGER_CACHE_SIZE is used to control the number +of Space Manager instances that can be present in the recycler, currently +4.  If more than NS_SPACE_MANAGER_CACHE_SIZE are allocated at a time, +then standard allocation is used.
+ +

void* operator new(size_t aSize);
void operator delete(void* aPtr, size_t aSize);

+ A Static method is used to shutdown the Space Manager recycling.  This +method deletes all of the Space Mangers inthe recycler,and prevents further +recycling.  It is meant to be called only when the layout module is being +terminated.
+ +
  static void Shutdown();

+ +

Origin / Coordinate Space Translation

+ +
  /**
* Translate the current origin by the specified (dx, dy). This
* creates a new local coordinate space relative to the current
* coordinate space.
*/
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }

/**
* Returns the current translation from local coordinate space to
* world coordinate space. This represents the accumulated calls to
* Translate().
*/
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }

/**
* Returns the y-most of the bottommost band or 0 if there are no bands.
*
* @return PR_TRUE if there are bands and PR_FALSE if there are no bands
*/
PRBool YMost(nscoord& aYMost) const;
+ +

Region Management

+ +
  /**
* Returns a band starting at the specified y-offset. The band data
* indicates which parts of the band are available, and which parts
* are unavailable
*
* The band data that is returned is in the coordinate space of the
* local coordinate system.
*
* The local coordinate space origin, the y-offset, and the max size
* describe a rectangle that's used to clip the underlying band of
* available space, i.e.
* {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
* coordinate space
*
* @param aYOffset the y-offset of where the band begins. The coordinate is
* relative to the upper-left corner of the local coordinate space
* @param aMaxSize the size to use to constrain the band data
* @param aBandData [in,out] used to return the list of trapezoids that
* describe the available space and the unavailable space
* @return NS_OK if successful and NS_ERROR_FAILURE if the band data is not
* not large enough. The 'count' member of the band data struct
* indicates how large the array of trapezoids needs to be
*/
nsresult GetBandData(nscoord aYOffset,
const nsSize& aMaxSize,
nsBandData& aBandData) const;

/**
* Add a rectangular region of unavailable space. The space is
* relative to the local coordinate system.
*
* The region is tagged with a frame
*
* @param aFrame the frame used to identify the region. Must not be NULL
* @param aUnavailableSpace the bounding rect of the unavailable space
* @return NS_OK if successful
* NS_ERROR_FAILURE if there is already a region tagged with aFrame
*/
nsresult AddRectRegion(nsIFrame* aFrame,
const nsRect& aUnavailableSpace);

/**
* Resize the rectangular region associated with aFrame by the specified
* deltas. The height change always applies to the bottom edge or the existing
* rect. You specify whether the width change applies to the left or right edge
*
* Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
enum AffectedEdge {LeftEdge, RightEdge};
nsresult ResizeRectRegion(nsIFrame* aFrame,
nscoord aDeltaWidth,
nscoord aDeltaHeight,
AffectedEdge aEdge = RightEdge);

/**
* Offset the region associated with aFrame by the specified amount.
*
* Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);

/**
* Remove the region associated with aFrane.
*
* Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
* tagged with aFrame
*/
nsresult RemoveRegion(nsIFrame* aFrame);

/**
* Clears the list of regions representing the unavailable space.
*/
void ClearRegions();
+ +

Floater Impact

+ +
  /**
* Methods for dealing with the propagation of float damage during
* reflow.
*/
PRBool HasFloatDamage()
{
return !mFloatDamage.IsEmpty();
}

void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
}

PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
}
+ +

Debug Only Methods

+ +
  /**
* Dump the state of the spacemanager out to a file
*/
nsresult List(FILE* out);

void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;

+ +

Unused / Obsolete Methods

+ +
  /*
* Get the frame that's associated with the space manager. This frame
* created the space manager, and the world coordinate space is
* relative to this frame.
*
* You can use QueryInterface() on this frame to get any additional
* interfaces.
*/
nsIFrame* GetFrame() const { return mFrame; }

+ +

Implementation Notes

+ +

+ +

Algorithm 1: GetBandData

+GetBandData is used to provide information to clients about what space if +available and unavailable in a band of space.  The client provides a +vertical offset, the yOffset, that corresponds to the band that is of interest. + This will be the y offset of the frame that is being reflowed.  The +caller also provides a collection of BandData objects (an array) and the +number of items that the collection can handle.  If the collection is +too small, then an error is returned and the count is updated to indicate +the size required.
+
+The algorithm to provide the band data is as follows:
+ +
GetBandAvailableSpace:
+This method is called from GetBandData only. It walks all of the bands in +the space manager and determines which bands intersect with the band passed +in, and if within those bands there are regions that are available or occupied.
+ + +

Algorithm 2: AddRectRegion

+Clients call into this method to notify the Space Manger that a new frame +is occupying some space.
+ +
InsertBandRect:
+Internal method to insert a band rect into the BandList in the correct location. +There are several cases it has to handle, as specified in the source file +comments:
+
// When comparing a rect to a band there are seven cases to consider.
// 'R' is the rect and 'B' is the band.
//
// Case 1 Case 2 Case 3 Case 4
// ------ ------ ------ ------
// +-----+ +-----+ +-----+ +-----+
// | R | | R | +-----+ +-----+ | | | |
// +-----+ +-----+ | | | R | | B | | B |
// +-----+ | B | +-----+ | | +-----+ | |
// | | | | +-----+ | R | +-----+
// | B | +-----+ +-----+
// | |
// +-----+
//
//
//
// Case 5 Case 6 Case 7
// ------ ------ ------
// +-----+ +-----+ +-----+ +-----+
// | | | R | | B | | | +-----+
// | B | +-----+ +-----+ | R | | B |
// | | | | +-----+
// +-----+ +-----+
// +-----+
// | R |
// +-----+
//
+ +This algorithm is pretty confusing - basically what needs to happen is +that rects and bands need to be divided up so that complicated cases like +#2, #4, and #7, are reduced to simpler cases where the rects is totally above, +below, or between a band rect.  From the current implementation, it +might be worth verifying that the final result of the inserts is a correctly +ordered liest of bandRects (debug mode only).
+ +

Algorithm 3: RemoveRegion

+ When a floater is removed, the Space Manager is notified by a call to RemoveRegion, +passing in the frame that is being removed.
+ +
+ +
+

Cross-Component Algorithms

+
+
+ +
+

Tech Notes

+ +
+
+ + + diff --git a/mozilla/layout/doc/ExampleClassDiagram.jpg b/mozilla/layout/doc/ExampleClassDiagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c6accb2bb842d61a34a6c875ce2e6c33ee8fe19 GIT binary patch literal 5606 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 O6sBl^f~5(Ay#FUW0 + + + + + Space Manager High Level Design + + + + +

Gecko Layout High Level Design Document

+ +

Space Manager High Level Design

+
+ +

Overview

+ 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.
+
+ 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:
+ +
    +
  • nsSpaceManager
  • +
  • nsBandData
  • +
  • nsBlockBandData
  • +
  • BandRect / BandList (private structs)
  • +
  • FrameInfo (private struct)
  • +
  • nsBandtrapezoid
  • + +
+ 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:
+ +
    +
  • nsBlockReflowState
  • +
  • nsBlockFrame
  • +
  • nsBoxToBlockAdaptor
  • + +
+ 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).  
+
+ 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. +

Data Model

+ +

Class/Component Diagram

+ +
+
SpaceManager Class Diagram +
+
+
+ +
    +
  • nsSpaceManager: The central point of management of the space taken + up by floaters in a block
  • +
  • nsBandData: Provides information about the frames occupying a band + of occupied or available space
  • +
  • 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.
  • +
  • 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).
  • +
  • BandList: A subclass of BandRect that provides a list interface +- Head(), Tail(), IsEmpty(), etc.
  • +
  • FrameInfo: A structure that keeps information about the rectangle + associated with a specific frame, in a linked list.
  • +
  • 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.
    +
  • + +
+ +

Use Case

+ +

Use Case 1: Space Manger is Created / Destroyed

+ Space Manager instances are created in the nsBlockFrame's Reflow method. +  
+ +
    +
  • An instance is created 
  • +
  • The BlockReflowState's previous Space Manger is saved off.
  • +
  • The new Space Manger instance is associated with the BlockReflowState. + 
  • +
  • After the block frame's Reflow has completed, the old Space Manager +instance is re-associated with the BlockReflowState
  • +
  • The new Space Manager is destroyed.
  • + +
+ 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. +

Use Case 2: Floater is added to the Space Manager

+ 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:
+ +
    +
  • For each line in the block, see if it has floated blocks
  • +
  • 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.
  • +
  • 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. 
    +
  • + +
+ +

Use Case 3: Space Manager is used to find available space to reflow + into

+ 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).
+ +
    +
  • nsBlockFrame first frees all floater information for the line that + is being reflowed.
  • +
  • GetAvailableSpace is called on the BlockReflowState
  • +
  • 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).
  • +
  • BlockBandData then gets the band data from the space manager via +a call to the Space Manager associated with the BlockBandData instance.
  • +
  • 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.
  • +
  • The BlockReflowState then stores this available space rect for use + in the rest of the reflow chain.
    +
  • + +
+ +

Use Case 4: Propagation of Floater Damage: remembering floater damage

+ This process is driven by the Block Frame.
+ +
    +
  • A dirty line is reflowed
  • +
  • If the line's combined area has changed then the Space Manager is +told to include the combined area as a floater damage interval.
  • + +
+ +

Use Case 5: Propagation of Floater Damage: detecting and handling floater +damage

+ This process is driven by the Block Frame.
+ +
    +
  • A non-dirty line is encountered by the Block Frame in ReflowDirtyLines
  • +
  • Block Frame calls its PropagateFloaterDamage method
  • +
  • The Space Manger is checked to see if ther is any floater damage
  • +
  • If there is, then the block frame asks the Space Manager if the +line in question intersects the floater damage
  • +
  • If the line does intersect a damage interval, then the line is marked +dirty
  • +
  • If the line does not intersect a damage interval, it may still be +marked dirty if:
  • + +
      +
    • it was impacted by floaters before, but is not any longer
    • +
    • it was not impacted by floaters befre, but is now
    • +
    • + it is impacted by floaters and is a block
      +
    • + +
    + +
+
+ +

+ +

Problems / bugs found during documentation:

+ +
    +
  • BandRect and BandList are public in nsSpaceManager.h - should be +private (compiles fine)
  • +
  • nsSpaceManager data members are declared protected, but there are + no subclasses. Should be private (compiles fine)
  • +
  • nsBlockFrame::Paint is mucking with nsBlockBandData in and #if 0 +block - remove that and the include (compiles fine)
  • +
  • nsSpaceManger has no way of clearing the floater damage interval +set - this might be needed if the SpaceManager persists beyond a Reflow
  • +
  • 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 block-line impacted by a floater + .
  • + +
+
+
+ + + diff --git a/mozilla/layout/doc/SpaceManagerClasses.gif b/mozilla/layout/doc/SpaceManagerClasses.gif new file mode 100644 index 0000000000000000000000000000000000000000..71d89da74a7e1ec01cd04db2ad5b1a6115bd766c GIT binary patch literal 61560 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%0AKBfhIU29 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
    gL6hW; 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 literal 0 HcmV?d00001 diff --git a/mozilla/layout/doc/dd-template.html b/mozilla/layout/doc/dd-template.html new file mode 100644 index 00000000000..c95d56317bd --- /dev/null +++ b/mozilla/layout/doc/dd-template.html @@ -0,0 +1,112 @@ + + + + + + Layout Detailed Design Template + + + + +

    Gecko Layout Detailed Design Document Template

    + [Use this template to start your detailed design. Replace items in square + brackets with the appropriate text for your component, class or system.  Keep + in mind that this is just a general template intended for most designs. +Your specific design may require different organization or topics - the +goal is to provide detailed information about the software to the reader.]
    +
    + +

    [Component / Class Name] Detailed Design

    + +

    Overview

    + [Introduce the scope of this design document: what is being documented here. +Provide a reference back to the High Level design(s) that correspond.]
    + +
    +

    [Class / Component A]

    + [Briefly refresh the reader with the purpose of the class or component. +Provide enough information to make accessible the following sections on the +public API, private methods and members, and algorithms. Bring up and tricky +or otherwise interesting relationships that will be detailed.]
    +
    + +

    Public API

    + [Show the public API for the component, as IDL, C++ header file, or as a +pseudo-code description.  If using a source file, the comments in the +source file should cover most of the detail needed. If they do not, then add +that detail there.  See the Overview document for more details on the +scope of information that should be presented.]
    + +

    Protected API

    + [If there is a protected API, list the methods and members and indicate +the responsibilities of the callers with respect o calling the base class, +enforcing base class invariants, etc.]
    +
    + +

    Implementation Notes

    + [The nasty details of the implementation get exposed here. This section +can be broken down into subsections as necessary, and should include details +of particularly important algorithms, performance characteristics or constraints, +memory usage, tricky ownership issues, and anything else that would make understanding +the implementation easier for the reader.]
    + +

    Algorithms

    + +
    [Interesting Algorithm 1: The internally maintained sorted list]
    + [explain the nature of the algorithm, the reason it was chosen, the types +of input is is expected to operate on, etc. Annotated pseudo-code is a good +idea here, but actual code is often too detailed to b of much use by itself. +It the actual code is sufficient to understand it, then this subsection is +probably not needed.]
    + +
    [Interesting Algorithm 2: Handling overflow of the input buffer]
    + [your description here]
    + +

    + +
    +

    [Class / Component B]

    + [Repeat the structure for the next class or component.]
    +
    + +
    +

    Cross-Component Algorithms

    + [specify the details of algorithms that cross a single component. refer +to each component, describe the flow of control, the responsibilities of each +component along the way, the error handling, the state-management if any, +and the expected results for a given input. Generally each of these algorithms +gets its own subsection.]
    + +

    [Turning a byte-stream into a fully parsed token-tree]

    + [Detailed description, pesudo-code, state transitions, etc.]
    + +

    [Managing updates to the the document]

    + [Detailed description, pesudo-code, state transitions, etc.]
    +
    + +
    +

    Tech Notes

    + [This section contains links to tech notes related to the implementations +covered in this design.  Tech Notes tend to be extremely specific, often +recipes for how to do something or how to fix a class of defects.  If +the tech note is more general, it may be a good idea to move it into the Detailed +design itself.]
    + +
    +
    + + + diff --git a/mozilla/layout/doc/hld-template.html b/mozilla/layout/doc/hld-template.html new file mode 100644 index 00000000000..b1ea7ab531f --- /dev/null +++ b/mozilla/layout/doc/hld-template.html @@ -0,0 +1,105 @@ + + + + + + Layout High Level design Template + + + + + +

    Gecko Layout High Level Design Document Template

    + [Use this template to start your high level design. Replace items in square + brackets with the appropriate text for your component, class or system.  Keep + in mind that this is just a general template intended for most designs. +Your specific design may require different organization or topics - the +goal is to provide high-level information about the software to the reader.]
    +
    + +

    [Component/Class/System Name] High Level Design

    +
    + +

    Overview

    + [Provide a descriptive overview of the component, class, or system that + you are documenting. Describe what the system is supposed to do, where it + is in the overall system, who the clients are, how it is expected to perform, + and any other information that is important to convey to somebody interested + in understanding what the documented system is all about.]
    +
    + +

    Data Model

    + [This section describes the classes or components that make up the data + model for the system being documented. It can include a graphical representation + of the classes and their relationships to each other (derivation, aggregation, + ownership, usership, etc.). No implementation details are to be included +here, but general relationships and inter-relationships should be shown and +briefly described. The reader should be able to understand the players in +the system, and the extent to which those players interact with or are related +to the other players.]
    + +

    Class/Component Diagram

    + +
    +
    Example Class Diagram +
    +
    +
    + + +
    + +

    Use Case

    + [Use Cases describe interactions between specific instances of the objects + or components described in the Data Model.  There will generally be +use cases for each   interesting runtime interaction between the objects + in the system. An extremely simple system will have at least one use case + describing the behavior of the simple system in action, but most systems +have many use cases corresponding to the any things that the system does. + The reader should be able to find the use case (or cases) that correspond +to the situation they are interested in understanding, and they should be +able to learn how data flows through the system, what objects are involved, +how  object and data life-cycles are managed (e.g. where allocations +ad deallocations occur, and who maintains ownership). This section makes up +the bulk of the document. It touches on implementations and algorithms, but +rather than describing them in detail, it stays high-level and links to the +detailed designs that correspond.]
    + +

    [Use Case 1: Component is Created]

    + The component is created by a client with...
    +  [Image could go here if it were interesting enough...]
    +
    + +

    [Use Case 2: Component is Destroyed]

    + When the client is finished with the instance they created (or were given + ownership of) the destroy it by calling...
    +
    + +

    [Use Case 3: Component is used to find all invalid links on the page]

    + Descriptive text of how the component is invoked goes here. The other +components that it uses to carry out its task are shown, and the general +flow of data is documented.
    + [Picture of the component instance with annotations showing data flow, +ownership, etc. goes here]
    + +

    State Transitions

    + [Where appropriate, the discrete states of a system should be enumerated + and the transitions between the states defined.  Not all systems require + full state transition diagrams, but most systems have at least a handful +of interesting states, and at least a small number of interesting stimuli +that cause transitions from one state to another.   Of course, classes +or components that are not stateful have no need for this section.]
    +
    +
    + + + diff --git a/mozilla/layout/doc/index.html b/mozilla/layout/doc/index.html new file mode 100644 index 00000000000..a03d8721ed0 --- /dev/null +++ b/mozilla/layout/doc/index.html @@ -0,0 +1,35 @@ + + + + + Gecko Layout Documentation Index + + +

    Gecko Layout Documentation

    +
    +

    Meta Documents:

    + +

    Completed Documents:

    + +

    Works in Progress:

    +
      +
    • Debugging Facilities (Bernd):
      +
    • +
    +
    + + diff --git a/mozilla/layout/doc/overview.html b/mozilla/layout/doc/overview.html new file mode 100644 index 00000000000..f84fddf8431 --- /dev/null +++ b/mozilla/layout/doc/overview.html @@ -0,0 +1,176 @@ + + + + + + Layout Documentation Overview + + + +

    Layout Documentation Overview

    +
    Authors:
    +
      +
    • Marc Attinasi (attinasi@netscape.com)
    • +
    +History:
    +
      +
    • 12/17/2001 - created
      +
    • +
    +
    +

    Background

    + The Layout module of Gecko has not been documented very well. This has lead +to some predictable problems: difficult maintenance, hard to get new people +involved in the module, problems assessing the risk of changes, hard to know +where bugs are likely to be in the source.  One extreme result of the +lack of comprehensive has been an urge to rewrite some of the more impenetrable +parts of the layout component, the block and Line Layout areas.  Rather +than throwing it all away and rewriting it, we have decided to put significant +effort into thoroughly documenting what we already have. this effort will +help us to understand what parts of the system we want to keep as-is, incrementally +revise, or wholesale rewrite. Additionally, we will make the code base more +accessible to new (and not-so-new) engineers.
    +
    + +

    Strategy:

    + Documenting all of Block and Line layout is a large task, so it will be +divided up among knowledgeable and interested engineers. Progress will be +tracked in bugzilla + bug 115310 + .  This document lays out the basic documentation scope and formatting +so that all of the individual contributions can be combined into a relatively +cohesive unit of linked documents.
    +
    + +

    Scope:

    + The documentation will generally cover two levels of detail. There is room +for deviation from this as needed, but generally a High Level Design document +and a Detailed Design document will provide the necessary level of detail +for those trying to understand the system as a whole, and those trying to +get into the code.
    +
    + +

    High Level Designs

    + High level designs provided an overview of the system being documented. +The general concept of the component is described, and the classes involved +are described briefly (no details of the class implementations).  In +some cases the high level design vocabulary consists of other components +and not classes.  The important thing is to describe the interactions +between the classes and/or components such that the reader gets an understanding +of which pieces talk to which other pieces, what kinds of data are shared +by various components or classes, how the data is modified and by whom, beginning +states and end states of a process, and external constraints or inputs into +the system begin described.
    +
    + A fundamental piece of the high-level design is the data model. This +is generally a graphical representation of the classes or components involved +in the system, showing the relationships between them in terms of has-a, +is-a, uses, owns, etc. the specific representation is not as important as +the content of the representation. For example, using UML or Booch notation +is fine, as is an ad-hoc diagram that shows the same types of information.
    +
    + Another important piece of the high-level design is a set of use-cases + that describe specific interaction that result from specific events in +the system. For example, we might want to show specifically what happens +when an attribute is changed on an element via the DOM. Use cases differ +from data models in that they show specific instances of objects or components, +actual data values where interesting or important, and often give a glimpse +into the algorithms employed. All of the components or objects in the use +cases must be documented in the data model.
    +
    + State Transition Diagrams
    may be important to some systems, and they +should be documented in the high-level design as well. These should be described +in terms of the abstract states that the system may be in, not in terms of +how the state-machine is actually implemented.
    +
    + The high-level documents provide an overview of the components and classes +that make up a system. It can be used as a road map to the related detailed +design documents for the components and classes involved in the system. thus, +the classes, components, and algorithms referenced in the high-level design +document should be linked to the detailed design documents that correspond. +This link generally occurs at the first reference to the class or component, +but it can be provided in other contexts as well, for convenience to the reader. + Missing or invalid links are considered errors in the high-level design. +
    +   
    + +

    Detailed Designs

    + Detailed design documents provide specific information needed to implement +(or understand the implementation of) the components and classes described +in the high-level design. Users of the classes or components should also be +able to understand from the detailed design just how the classes, components +and API's are to be used. Special performance characteristics of methods or +interactions should be documented where pertinent.
    +
    + +

    Public API

    + The public API of the component or class being documented is essential to +the detailed design. Each publicly accessible interface, method and data member +must be documented. Ideally this information is contained in the implementation +files for a class, interface or component. If this is the case, the actual +IDL or class header file can be used as the documentation for the public API. +This should be done as a link or embedded document to avoid the perpetual +need to keep the document up to date with the source file.  Specific +items that are important to the description of the publicly available aspects +of the component, class, or interface include:
    + +
      +
    • entry-point semantics: what does the method do, or what does the data +member mean? Is the universe of expected clients limited or open (e.g.. who +can call it)?
      +
    • +
    • preconditions: what are the legal states for the instance to be in +before the entry point is called? what are the legal values for the arguments? +what are the required states for the objects or components used in the entry-point?
    • +
    • postconditions: what is guaranteed when the entry-point is returned +from? what return values are legal? what is the status of the output arguments +for various return states?
    • +
    • special performance characteristics: if there are special concerns +about performance of the method, explain them. for example, is the method +O(n^2)? Is there considerable memory required? Is the method recursive?
    • + +
    + Beyond the public interfaces, the private and protected methods need to +be documented as well. For protected methods and members, the expectations +of the subclasses must be made clear (e.g.. should the subclass call the +base class method? if so, when?)  As with the public methods, the semantics, +preconditions, postconditions, and special performance considerations should +be described. Again, this may be by direct inclusion of the source code files +where appropriate.
    +
    + +

    Algorithms

    + There is often a need to document specific algorithms used in methods and +functions.  Generally, it is not a good idea to include this sort of +information in the source files, so they must be described fully in the detailed +design document.  The extent of this information varies wildly from one +design to another.  Be sure to include an Algorithms section to the +document when there are interesting or critical algorithms that the classes +or components employ.  Spell out the algorithms in as much detail as +possible using pseudo-code or diagrams. Ideally, it should be possible to +implement the algorithm from the information in the design.
    +
    +
    + Algorithms that involve several different components or object instances +require special attention. These algorithms tend to be more complex and more +difficult to completely specify.  Start out by referring to the related +use cases in the high level design, and then drill down into the responsibilities +and requirements of the individual instances involved.  Here, diagrams +and pseudo-code are indispensable in communicating how the algorithm is carried +out across the system.
    + +

    +

    Tech Notes

    +The end of the detailed design document should contain a list of links to +Tech Notes. These will vary in depth and scope, but generally they provide +information geared toward helping developers work on the system.  Tech +Notes might contain information about  how code has been modified, how +a new feature was added, how to debug a certain class of problem, how to +use built-in debugging r logging facilities, or how to maintain or extend +unit tests.  The Tech Notes should be stored in a publibly accessable +location, as a comment or attachment in a bugzilla bug, for example.  The +text that holds the link should be descriptive of what the Tech Note addresses.
    +
    + + +