diff options
Diffstat (limited to 'layout/doc')
24 files changed, 5654 insertions, 0 deletions
diff --git a/layout/doc/DD-SpaceManager.html b/layout/doc/DD-SpaceManager.html new file mode 100644 index 000000000..39cd16597 --- /dev/null +++ b/layout/doc/DD-SpaceManager.html @@ -0,0 +1,743 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <title>Detailed Design Template</title> +</head> + <body> + +<h1><font color="#cc0000">Gecko Layout Detailed Design Document</font></h1> + +<h1>Space Manager Detailed Design</h1> + +<h2>Overview</h2> +<p> + 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. +</p> + + + +<hr width="100%" size="2"> +<h2>nsSpaceManager</h2> +<p> + The Space Manager 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. +</p> + +<p> + There are three important parts to the Space Manager 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 float +impact intervals. +</p> + +<p> + The class nsSpaceManager is declared in the file <a href="http://lxr.mozilla.org/seamonkey/source/layout/base/src/nsSpaceManager.h"> + nsSpaceManger.h</a> + . 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<font color="#cc0000"> + .</font> +</p> + +<p> + Here is the class declaration, taken from the source file as of 01.08.02 +</p> + + + +<pre>/** + * 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, uint32_t* 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; + int32_t 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; + int32_t 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 int32_t sCachedSpaceManagerCount; + static void* sCachedSpaceManagers[NS_SPACE_MANAGER_CACHE_SIZE]; + + nsSpaceManager(const nsSpaceManager&); // no implementation + void operator=(const nsSpaceManager&); // no implementation +}; + +</pre> + +<h3>Public API</h3> + +<h4>Life Cycle:</h4> +<p> + 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 Manager is relative to the frame passed in to the constructor. +</p> + +<pre> nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame); + ~nsSpaceManager(); +</pre> +<p> + 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. +</p> + +<pre> + void* operator new(size_t aSize); + void operator delete(void* aPtr, size_t aSize); + +</pre> +<p> + 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. +</p> + +<pre> static void Shutdown(); + +</pre> + +<h4>Origin / Coordinate Space Translation</h4> + +<pre> /** + * 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; +</pre> + +<h4>Region Management</h4> + +<pre> /** + * 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(); +</pre> + +<h4>Float Impact</h4> + +<pre> /** + * 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); + } +</pre> + +<h4>Debug Only Methods</h4> + +<pre> /** + * Dump the state of the spacemanager out to a file + */ + nsresult List(FILE* out); + + void SizeOf(nsISizeOfHandler* aHandler, uint32_t* aResult) const; + +</pre> + +<h4>Unused / Obsolete Methods</h4> + +<pre> /* + * 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; } + +</pre> + +<h3>Implementation Notes</h3> + +<h4></h4> + +<h4>Algorithm 1: GetBandData</h4> +<p> +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. +</p> + +<p> +The algorithm to provide the band data is as follows: +</p> +<ul> + <li>Get a vertical offset in world coordinates (instead of frame-relative +coordinates) by adding the y-origin of the SpaceManager to the y offset passed +in</li> + <li>If the (adjusted) y value passed in is greater than the greatest band +being managed, then all space is available so a single trapezoid is returned, +marked as available and sized to the maximum size value (passed in).</li> + <li>If the (adjusted) y offset intersects a band, then gather the band +data:</li> + <ul> + <li>walk the internal bandData list from head to tail</li> + <li>for each band data entry, see if the top of the band is greater than +the (adjusted) y offset requested</li> + <li>if it is, then band is below the offset requested, so the area between +the band and the y offset is available - create a trapezoid with that region +and return it.</li> + <li>if the (adjusted) y offset is between the band top and bottom, then +get the available space for the band by calling GetBandAvailableSpace</li> + <li>otherwise, move to the next band</li> + </ul> +</ul> +<h5>GetBandAvailableSpace:</h5> +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. + +<ul> + <li>First, walk all of the bands until a band that is to the right of the +desired offset is located</li> + <li>Starting at that band, walk the remaining bands:</li> + <ul> + <li>if the current band is to the right of the requested band, then there +is available space. </li> + <ul> + <li>if there is more room in the bandData collection, then add a trapezoid +to the bandData collection such that it is marked as available and has a +rect that represents the space between the reference band tna dht band being +examined</li> + <li>if there is no more room in the BandData collection, estimate the +number of entries requires as the current count + twice the number of bands +below the reference band, plus two. Return an error code so the caller +can reallocate the collection and try again.</li> + </ul> + <li>check the size of the collection again, if there is no room left +then estimate the number of items requires as the current count + twice the +number of bands below the band in question plus one. </li> + <li>create a new trapezoid in the band collection that has a region corresponding +to the reference band rect, marked as occupied by either a single or multiple +frames.</li> + <li>move to the next band</li> + </ul> + <li>after walking all of the band data, se if we have reached the right +edge of the band. </li> + <ul> + <li>If not, then check for space in the band collection</li> + <ul> + <li>if there is no room left, then set the count to the current count +plus 1 and return an error.</li> + <li>otherwise, create another entry in the band collection, marked +as available, and with a rect corresponding to the area remainin in the band +(eg. from the right edge of the last band rect to the right edge of the band).</li> + </ul> + </ul> +</ul> + +<h4>Algorithm 2: AddRectRegion</h4> +Clients call into this method to notify the Space Manager that a new frame +is occupying some space. + +<ul> + <li>First, try to get frame info for the frame. If it is found, return +an error since the frame is already associated with a region in the Space +Manager.</li> + <li>Next, create a rect from the occupied space passed in by the caller, +transforming it first to world-coordinates by adding the Space Manager's +offset to the occupied space rect passed in.</li> + <li>Create a new Frame Info instance for the frame and rect, returning +an error if allocation fails.</li> + <li>Check if the occupied space rect (adjusted) is empty, if so, return +an error (<font color="#cc0000">NOTE: this could be done earlier, or +prevented by the caller</font>)</li> + <li>Allocate a new BandRect instance with the rect and frame as constructor +arguments, and insert it into the collection via InsertBandRect</li> +</ul> +<h5>InsertBandRect:</h5> +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: + +<pre>// 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 | +// +-----+ +// +</pre> +<ul> + <li>First, check for the easiest case, where there are no existing band +rects, or the band rect passed in is below the bottommost rect. In this case, +just append the band rect and return.</li> + <li>Starting at the head of the list of bandRects, check for intersection +with the rect passed in:</li> + <ul> + <li>case #1: the rect is totally above the current band rect, so insert +a new band rect before the current bandRect</li> + <li>cases #2 and #7: the rect is partially above the band rect, so it +is divided into two bandRects, one entirely above the band, and one containing +the remainder of the rect. Insert the part that is totally above the +bandRect before the current bandRect, as in case #1 above, and adjust the +other band rect to exclude the part already added.</li> + <li>case #5: the rect is totally below the current bandRect, so just +skip to the next band</li> + <li>case #3 and #4: rect is at least partially intersection with the +bandRect, so divide the current band into two parts, where the top part is +above the current rect. Move to the new band just created, which is +the next band.</li> + <li>case #6: the rect shares the bottom and height with the bandRect, +so just add the rect to the band.</li> + <li>case #4 and #7: create a new rect for the part that overlaps the +bandRect, and add it to the current bandRect (similar to case #6) and then +move on to the next band, removing that part from the rect passed in. If +no more bands, append the rect passed in to the end of the bandRect list.</li> + </ul> +</ul> +<i>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).</i> + + +<h4>Algorithm 3: RemoveRegion</h4> + When a float is removed, the Space Manager is notified by a call to RemoveRegion, +passing in the frame that is being removed. + +<ul> + <li>Get the FrameInfo for the frame passed in. If not found, an error is +returned.</li> + <li>If the rect for the frame is not empty, then visit each band in the +bandList:</li> + <ul> + <li>for each rect in the band: + + </li> + </ul> + <ul> + <ul> + <li>if the bandRect is occupied by the frame, either remove the frame +from the bandRect (if there are other frames sharing it) and remember that +it was shared</li> + <li>otherwise simply remove the bandRect (no other frames share it).</li> + <li>if the bandRect was shared, then try to coalesce adjacent bandRects</li> + <ul> + <li>if the previous bandRect is directly next to the current bandRect, +and they have the same frame list, then make the current bandRect cover the +previous bandRect's full region (adjust the left edge to be that of the previous +bandRect) and remove the previous bandRect.</li> + </ul> + </ul> + </ul> + <ul> + <li>if the current band or prior band had a rect occupied byu the frame, +then try to join the two bands via JoinBands</li> + </ul> + <li>Finally, destroy the frameInfo for the frame. + + </li> +</ul> + +<br> + +<hr width="100%" size="2"> +<h2>Cross-Component Algorithms</h2> + +<br> + + + +<hr width="100%" size="2"> +<h2>Tech Notes</h2> +<ul> + <li> + + </li> + +</ul> + + + + + +</body> +</html> diff --git a/layout/doc/ExampleClassDiagram.jpg b/layout/doc/ExampleClassDiagram.jpg Binary files differnew file mode 100644 index 000000000..0c6accb2b --- /dev/null +++ b/layout/doc/ExampleClassDiagram.jpg diff --git a/layout/doc/HLD-SpaceManager.html b/layout/doc/HLD-SpaceManager.html new file mode 100644 index 000000000..b67d8d5ef --- /dev/null +++ b/layout/doc/HLD-SpaceManager.html @@ -0,0 +1,245 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <title>Space Manager High Level Design</title> + <meta name="author" content="Marc Attinasi (attinasi@netscape.com)"> +</head> + <body> + +<h1><font color="#cc0000">Gecko Layout High Level Design Document</font></h1> + +<h1>Space Manager High Level Design</h1> + <br> + +<h2>Overview</h2> + The Space Manager and associated classes and strructures are used by Block +and Line layout to manage rectangular regions that are occupied and available, +for correct handling of floated elements and the elements that flow around +them. When elements are floated to the left or right in a layout, they +take up space and influence where other elements can be placed. The +Space Manager is responsible for keeping track of where space is taken up +and where it is available. This information is used by block layout to correctly +compute where other floated elements should be placed, and how much space +is available to normal in-flow elements that flow around the floated bits.<br> + <br> + The Space Manager works in concert with several other classes to do its +job. The classes that are considered part of the Space Manager are:<br> + +<ul> + <li>nsSpaceManager</li> + <li>nsBandData</li> + <li>nsBlockBandData</li> + <li>BandRect / BandList (private structs)</li> + <li>FrameInfo (private struct)</li> + <li>nsBandtrapezoid</li> + +</ul> + Outside of the Space Manager itself, the clients of the Space Manager also + play an inportant part in the management of he available and used space. + The primary classes that interact with the Space Manager are:<br> + +<ul> + <li>nsBlockReflowState</li> + <li>nsBlockFrame</li> + <li>nsBoxToBlockAdaptor</li> + +</ul> + The general interaction model is to create a Space Manager for a block +frame in the context of a Reflow, and to associate it with the BlockReflowState + so it is passed down to child frames' reflow methods. After reflow, the +Space Manager is destroyed. During reflow, the space manager stores +the space taken up by floats (UpdateSpaceManager in nsBlockFrame) and +provides information about the space available for other elements (GetAvailableSpace +in nsBlockReflowState). <br> + <br> + Additionally, there is a need to manage impacts to lines caused by +changes to floated elements. This is referred to as Propagation +of Float Damage and is handled by the Block Frame, making use of the +Space Manager. When a float is incrementally reflowed, the Space +Manager is notified if the float's region has changed. If so, the +vertical space that has been affected (including both the float's old +region and the float's new region) is noted in the internal +nsIntervalSet as potential float damage (the method is +IncludeInDamage). During the incremental reflow of dirty lines the +block frame may encounter lines that are NOT dirty. In this case the +Space Manager is also asked if there is any float damage, and +if there is then the block further checks to see if that damage +intersects the area of the non-dirty line, marking it dirty if there +is intersection. Thus, changes to floats on other lines may +cause impact to otherwise clean lines, and the Space Manager +facilitates the detection of this. <h2>Data Model</h2> + +<h4>Class/Component Diagram</h4> + +<blockquote> + <div align="Left"><img src="SpaceManagerClasses.png" alt="SpaceManager Class Diagram" idth="500" eight="459" title="Example Class Diagram"> + <br> + </div> + </blockquote> + + <ul> + <li>nsSpaceManager: The central point of management of the space taken + up by floats in a block</li> + <li>nsBandData: Provides information about the frames occupying a band + of occupied or available space</li> + <li>nsBlockBandData: A specialization of nsBandData that is used by +nsBlockReflowState to determine the available space, float impacts, and +where floats are cleared. Essentially a CSS-specific wrapper for +generic nsBandData.</li> + <li>BandRect: Keeps the bounds of a band, along with the frames associated + with the band. BandRects are a linked list (provided by PRCListStr +super-class) and also provide some geometry-management methods (SplitVertically, +SplitHorizontally) and some methods that query or manipulate the frames associated +with the band (IsOccupiedBy, AddFrame, RemoveFrame).</li> + <li>BandList: A subclass of BandRect that provides a list interface +- Head(), Tail(), IsEmpty(), etc.</li> + <li>FrameInfo: A structure that keeps information about the rectangle + associated with a specific frame, in a linked list.</li> + <li>nsBandTrapezoid: Represents the discrete regions within a band that + are either Available, Occupied by a single frame, or Occupied by several +frames. This is used to communicate information about the space in +the band to the clients of the SpaceManager. There is no internal use +of the nsBandTrapezoid by the Space Manager, rather it uses its internal +BandList to create a BandData collection, which is largely made up of nsTrapezoid +data.<br> + </li> + + </ul> + + <h2>Use Case</h2> + + <h4>Use Case 1: Space Manager is Created / Destroyed</h4> + Space Manager instances are created in the nsBlockFrame's Reflow method. + <br> + + <ul> + <li>An instance is created </li> + <li>The BlockReflowState's previous Space Manager is saved off.</li> + <li>The new Space Manager instance is associated with the BlockReflowState. + </li> + <li>After the block frame's Reflow has completed, the old Space Manager +instance is re-associated with the BlockReflowState</li> + <li>The new Space Manager is destroyed.</li> + + </ul> + If the BlockReflowState already had a Space Manager instance associated +with it, it is stored off before being replaced, and the returned to the +BlockReflowState instance after the new one has been destroyed. Thus, +Space Managers are effectively 'nested' during reflow, with each new block +introducing its own Space Manager. + + <h4>Use Case 2: Float is added to the Space Manager</h4> After a Space Manager is created for a block context's reflow chain, a +floated block may be added to it. This happens in the method <i>nsBlockReflowState::RecoverFloats</i> and +<i>nsBlockReflowState::FlowAndPlaceFloat</i> (formerly this was done in nsBlockFrame::UpdateSpaceManager). <br> +<br> +The general algorightm in <i>nsBlockReflowState::RecoverFloats</i> is:<br> + + <ul> + <li>For each line in the block, see if it has floated blocks</li> + <li>If floats are in the line, iterate over the floats and add each + one to the Space Manager via the AddRectRegion method. The actual rect + for the frame is cached in an nsFloatCache so it does not have to be recomputed.</li> + <li>If the block has any block children, then translate the Space Manager + to the child block's origin and update the space manager in the context +for the child block, recursively. When done with the child, restore the Space + Managers coordinates by translating by the negative of the child block's +origin. <br> + </li> + + </ul><br> + +The general algorightm in <i>nsBlockReflowState::FlowAndPlaceFloat</i> is:<br> +<ul> + <li>The region that the float currently occupies is recorded.</li> + <li>The band of available space is searched (with nsBlockReflowState::GetAvailableSpace);</li> + <li>The float frame that is get from the passed nsFloatCache argument is reflowed + and its rect is retrieved with GetRect;</li> + <li>The floats margins are added;</li> + <li>Check if the float can be placed in the acutal band: if not advance to the next band;</li> + <li>Check the float type and if it can be added to the space manager;</li> + <li>Align the float to its containing block top if rule + <a href="http://www.w3.org/TR/REC-CSS2/visuren.html#float-position">CSS2/9.5.1/4</a> + is not respected;</li> + <li>Add the float using <i>nsSpaceManager::AddRectRegion</i> </li> + <li>Compare the area that the float used to occupy with the area that it now occupies: if different, + record the vertically affected interval using <i>nsSpaceManager::IncludeInDamage</i></li> +</ul> + <h4>Use Case 3: Space Manager is used to find available space to reflow + into</h4> + The nsBlockFrame makes use of the Space Manager indirectly to get the available + space to reflow a child block or inline frame into. The block frame uses +a helper method on the nsBlockReflowState class to do the actual computation + of available space based on the data in the Space Manager. Here is how it +works for reflowing an inline frame within a block (this also occurs for +reflowing a block frame and, partially, for preparing for a resize reflow).<br> + + <ul> + <li>nsBlockFrame first frees all float information for the line that + is being reflowed.</li> + <li>GetAvailableSpace is called on the BlockReflowState</li> + <li>the BlockReflowState calls GetAvailableSpace on its BlockBandData + instance (which was setup in the BlockReflowState's constructor based on +the SpaceManager passed in and computed content area).</li> + <li>BlockBandData then gets the band data from the space manager via +a call to the Space Manager associated with the BlockBandData instance.</li> + <li>The BlockBandData then walks the collection of trapezoids that were + returned by the SpaceManager method GetBandData (as nsBandData wrappers) +and determines the right-most edge of the available space.</li> + <li>The BlockReflowState then stores this available space rect for use + in the rest of the reflow chain.<br> + </li> + + </ul> + + <h4>Use Case 4: Propagation of Float Damage: detecting and handling float +damage</h4> + This process is driven by the Block Frame.<br> + + <ul> + <li>A non-dirty line is encountered by the Block Frame in ReflowDirtyLines</li> + <li>Block Frame calls its PropagateFloatDamage method</li> + <li>The Space Manager is checked to see if there is any float damage</li> + <li>If there is, then the block frame asks the Space Manager if the +line in question intersects the float damage</li> + <li>If the line does intersect a damage interval, then the line is marked +dirty</li> + <li>If the line does not intersect a damage interval, it may still be +marked dirty if:</li> + + <ul> + <li>it was impacted by floats before, but is not any longer</li> + <li>it was not impacted by floats befre, but is now</li> + <li><a name="block-line-impact"></a> + it is impacted by floats and is a block<br> + </li> + + </ul> + + </ul> + <br> + + <hr width="100%" size="2"><br> + + <h1><font color="#ff0000">Problems / bugs found during documentation:</font></h1> + + <ul> + <li>BandRect and BandList are public in nsSpaceManager.h - should be +private (compiles fine)</li> + <li>nsSpaceManager data members are declared protected, but there are + no subclasses. Should be private (compiles fine)</li> + <li>nsBlockFrame::Paint is mucking with nsBlockBandData in and #if 0 +block - remove that and the include (compiles fine)</li> + <li>nsSpaceManger has no way of clearing the float damage interval +set - this might be needed if the SpaceManager persists beyond a Reflow</li> + </ul> + <br> + <br> + + </body> + </html> diff --git a/layout/doc/Layout_Overview.html b/layout/doc/Layout_Overview.html new file mode 100644 index 000000000..40c85265c --- /dev/null +++ b/layout/doc/Layout_Overview.html @@ -0,0 +1,354 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <title>Layout Overview</title> + <meta http-equiv="content-type" + content="text/html; charset=ISO-8859-1"> +</head> +<body> +<h1>Layout System Overview</h1> +<br> +<h3>Layout's Job: Provide the Presentation</h3> +Layout is primarily concerned with providing a presentation to an HTML or +XML document. This presentation is typically formatted in accordance with +the requirements of the <a href="http://www.w3.org/TR/REC-CSS1">CSS1</a> +and <a href="http://www.w3.org/TR/REC-CSS2/">CSS2</a> specifications from +the W3C. Presentation formatting is also required to provide compatibility +with legacy browsers (Microsoft Internet Explorer and Netscape Navigator +4.x). The decision about when to apply CSS-specified formatting and when +to apply legacy formatting is controlled by the document's DOCTYPE specification. +These layout modes are referred to as 'Standards' and 'NavQuirks' modes. (DOCTYPE +and modes are explained in more detail <a + href="http://www.mozilla.org/quality/help/bugzilla-helper.html">here</a>).<br> +<br> +The presentation generally is constrained by the width of the window in which +the presentation is to be displayed, and a height that extends as far as +necessary. This is referred to as the Galley Mode presentation, and is what +one expects from a typical browser. Additionally, layout must support a paginated +presentation, where the width of the presentation is constrained by the dimensions +of the printed output (paper) and the height of each page is fixed. This +paged presentation presents several challenges not present in the galley +presentation, namely how to break up elements that are larger than a single +page, and how to handle changes to page dimensions.<br> +<br> +The original design of the Layout system allowed for multiple, possibly different, +presentations to be supported simultaneously from the same content model. +In other words, the same HTML or XML document could be viewed as a normal +galley presentation in a browser window, while simultaneously being presented +in a paged presentation to a printer, or even an aural presentation to a +speech-synthesizer. To date the only real use of this multiple presentation +ability is seen in printing, where multiple presentations are managed, all +connected to the same content model. (note: it is unclear if this is really +a benefit - it may have been better to use a copy of the content model for +each presentation, and to remove the complexity of managing separate presentations +- analysis is needed here). The idea of supporting a non-visual presentation +is interesting. Layout's support for aural presentations is undeveloped, +though conceptually, it is possible and supported by the architecture.<br> +<br> +<h3>How Layout Does its Job: Frames and Reflow</h3> +So, layout is concerned with providing a presentation, in galley or paged +mode. Given a content model, how does the layout system actually create the +presentation? Through the creation and management of frames. Frames are an +encapsulation of a region on the screen, a region that contains geometry +(size and location, stacking order). Generally frames correspond to the content +elements, though there is often a one-to-many correspondence between content +elements and frames. Layout creates frames for content based on either the +specific HTML rules for an element or based on the CSS display type of the +element. In the case of the HTML-specific elements, the frame types that +correspond to the element are hard-coded, but in the more general case where +the display type is needes, the layout system must determine that display +type by using the Style System. A content element is passed to the Style +System and a request is made to resolve the style for that element. This +causes the Style System to apply all style rules that correspond to the element +and results in a resolved Style Context - the style data specific to that +element. The Layout module looks at the 'display' field of the style context +to determine what kind of frame to create (block, inline, table, etc.). The +style context is associated with the frame via a reference because it is +needed for many other computations during the formatting of the frames.<br> +<br> +Once a frame is created for a content element, it must be formatted. We refer +to this as 'laying out' the frame, or as 'reflowing' the frame. Each frame +implements a Reflow method to compute its position and size, among other +things. For more details on the Reflow mechanism, see the Reflow Overview +document... The CSS formatting requirements present two distinct layout +models: 1) the in-flow model, where the geometry of an element is influenced +by the geometry of the elements that precede it, and 2) the positioned model, +where the geometry of an element is not influenced by the geometry of the +elements that precede it, or in any case, is influenced more locally. The +in-flow cased is considered the 'normal' case, and corresponds to normal +HTML formatting. The later case, called 'out of flow' puts the document author +in control of the layout, and the author must specify the locations and sizes +of all of the elements that are positioned. There is, of course, some complexity +involved with managing these two models simultanelusly...<br> +<br> +So far the general flow of layout looks like this:<br> +<br> +1) Obtain a document's content model<br> +2) Utilize the Style System to resolve the style of each element in the content +model<br> +3) Construct the frames that correspond to the content model, according to +the resolved style data.<br> +4) Perform the initial layout, or initial reflow, on the newly constructed +frame.<br> +<br> +This is pretty straight-forward, but is complicated somewhat by the notion +of <i>incrementalism</i>. One of the goals of the Layout system's design +is to create parts of the presentation as they become available, rather than +waiting for the entire document to be read, parsed, and then presented. This +is a major benefit for large documents because the user does not have to wait +for the 200th page of text to be read in before the first page can be displayed +- they can start reading something right away. So really, this sequence of +operations Resolve Style, Create Frame, Layout Frame, gets repeated many +times as the content becomes available. In the normal in-flow case this is +quite natural because the sequential addition of new content results in sequential +addition of new frames, and because everything is in-flow, the new frames +do not influence the geometry of the frames that have already been formatted. +When out-of-flow frames are present this is a more difficult problem, however. +Sometimes a content element comes in incrementally, and invalidates the formatting +of some of the frames that precede it, frame that have already been formatted. +In this case the Layout System has to detect that impact and reflow again +the impacted frames. This is referred to as an <i>incremental reflow</i>.<br> +<br> +<a name="DHTML_interaction"></a>Another responsibility of layout is to manage +dynamic changes to the content model, changes that occur after the document +has been loaded and (possibly) presented. These dynamic changes are caused +by manipulations of the content model via the <acronym + title="Document Object Model">DOM<acronym></acronym></acronym> (generally +through java script). When a content element is modified, added or removed, +Layout is notified. If content elements have been inserted, new frames are +created and formatted (and impacts to other frames are managed by performing +further incremental reflows). If content is removed, the corresponding frames +are destroyed (again, impacts to other elements are managed). If a content +element is modified, layout must determine if the chage influences the formatting +of that or other elements' presentations, and must then reformat, or re-reflow, +the impacted elements. In all cases, the determination of the impact is critical +to avoid either the problem of not updating impacted elements, thus presenting +an invalid presentation, or updating too much of the presentation and thus +doing too much work, potentially causing performance problems.<br> +<br> +One very special case of dynamic content manipulation is the HTML Editor. +Layout is used to implement both a full-blown WYSIWYG HTML editor, and a single +and multi-line text entry control. In both cases, the content is manipulated +by the user (via the DOM) and the resulting visual impacts must be shown as +quickly as possible, without disconcerting flicker or other artifacts that +might bother the user. Consider a text entry field: the user types text into +a form on the web. As the user types a new character it is inserted into +the content model. This causes layout to be notified that a new piece of +content has been entered, which causes Layout to create a new frame and format +it. This must happen very fast, so the user's typing is not delayed. In the +case of the WYSIWYG HTML editor, the user expects that the modifications +they make to the document will apear immediately, not seconds later. This +is especially critical when the user is typing into the document: it would +be quite unusable if typing a character at the end of a document in the HTML +editor caused the entire document to be reformated - it would be too slow, +at least on low-end machines. Thus the HTML editor and text controls put +considerable performance requirements on the layout system's handling of dynamic +content manipulation.<br> +<h3>The Fundamentals of Frames: Block and Line</h3> +There are many types of frames that are designed to model various formatting +requirements of different HTML and XML elements. CSS2 defines several (block, +inline, list-item, marker, run-in, compact, and various table types) and +the standard HTML form controls require their own special frame types to +be formatted as expected. The most essential frame types are Block and Inline, +and these correspond to the most important Layout concepts, the Block and +Line.<br> +<br> +A block is a rectangular region that is composed of one or more lines. A +line is a single row of text or other presentational elements. All layout +happens in the context of a block, and all of the contents of a block are +formatted into lines within that block. As the width of a block is changed, +the contents of the lines must be reformatted. consider for example a large +paragraph of text sitting in paragraph:<br> +<br> +<pre><p><br> We need documentation for users, web developers, and developers working + on Mozilla. If you write your own code, document it. Much of the + existing code <b>isn’t very well documented</b>. In the process of figuring + things out, try and document your discoveries. + If you’d like to contribute, let us know.<br></p></pre> +There is one block that corresponds to the <p> element, and then a number +of lines of text that correspond to the text. As the width of the block changes +(due to the window being resized, for example) the length of the lines within +it changes, and thus more or less text appears on each line. The block is +responsible for managing the lines. Note that lines may contain only inline +elements, whereas block may contain both inline elements and other blocks.<br> +<h3>Other Layout Models: XUL</h3> +In addition to managing CSS-defined formatting, the layout system provides +a way to integrate other layout schemes into the presentation. Currently +layout supports the formatting of XUL elements, which utilize a constraint-based +layout language. The Box is introduced into the layout system's frame model +via an adapter (BoxToBlockAdapter) that translates the normal layout model +into the box formatting model. Conceptually, this could be used to introduce +other layout systems, but it might be worth noting that there was no specific +facility designed into the layout system to accommodate this. Layout deals +with frames, but as long as the layout system being considered has no need +to influence presentational elements from other layout systems, it can be +adapted using a frame-based adapter, ala XUL.<br> +<br> +<h2>Core Classes</h2> +At the highest level, the layout system is a group of classes that manages +the presentation within a fixed width and either unlimited height (galley +presentation) or discrete page heights (paged presentation). Digging just +a tiny bit deeper into the system we find that the complexity (and interest) +mushrooms very rapidly. The idea of formatting text and graphics to fit within +a given screen area sounds simple, but the interaction of in-flow and out-of-flow +elements, the considerations of incremental page rendering, and the performance +concerns of dynamic content changes makes for a system that has a lot of +work to do, and a lot of data to manage. Here are the high-level classes +that make up the layout system. Of course this is a small percentage of the +total clases in layout (see the detailed design documents for the details +on all of the classes, in the context of their actual role).<br> +<h3>Presentation Shell / Presentation Context</h3> +Together the presentation shell and the presentation context provide the +root of the current presentation. The original design provided for a single +Presentation Shell to manage multiple Presentation Contexts, to allow a single +shell to handle multiple presentations. It is unclear if this is really possible, +however, and in general it is assumed that there is a one-to-one correspondence +between a presentation shell and a presentation context. The two classes +should probably be folded into one, or the distinction between them formalized +and utilized in the code. The Presentation Shell currently owns a controlling +reference to the Presentation Context. Further references to the Presentation +Shell and Presentation Context will be made by using the term Presentation +Shell.<br> +<br> +The Presentation Shell is the root of the presentation, and as such it owns +and manges a lot of layout objects that are used to create and maintain a +presentation (<font color="#990000">note that the DocumentViewer is the owner +of the Presentation Shell, and in some cases the creator of the objects +used by the Presentation Shell to manage the presentation. More details +of the Document Viewer are needed here...</font>). The Presentation Shell, +or PresShell, is first and foremost the owner of the formatting objects, +the frames. Management of the frames is facilitated by the Frame Manager, +an instance of which the PresShell owns. Additionally, the PresShell provides +a specialized storage heap for frames, called an Arena, that is used to make +allocation and deallocation of frames faster and less likely to fragment +the global heap. <br> +<br> +The Presentation Shell also owns the root of the Style System, the Style +Set. In many cases the Presentation Shell provides pass-through methods to +the Style Set, and generally uses the Style Set to do style resolution and +Style Sheet management.<br> +<br> +One of the critical aspects of the Presentation Shell is the handling of +frame formatting, or reflow. The Presentation Shell owns and maintains a +Reflow Queue where requests for reflow are held until it is time to perform +a reflow, and then pulled out and executed.<br> +<br> +It is also important to see the Presentation Shell as an observer of many +kinds of events in the system. For example, the Presentation Shell receives +notifications of document load events, which are used to trigger updates +to the formatting of the frames in some cases. The Presentation Shell also +receives notifications about changes in cursor and focus states, whereby +the selection and caret updates can be made visible.<br> +<br> +There are dozens of other data objects managed by the Presentation Shell +and Presentation Context, all necessary for the internal implementation. +These data members and their roles will be discussed in the Presentation +Shell design documents. For this overview, the Frames, Style Set, and Reflow +Queue are the most important high-level parts of the Presentation Shell.<br> +<h3>Frame Manager</h3> +The Frame Manager is used to, well, manage frames. Frames are basic formatting +objects used in layout, and the Frame Manager is responsible for making frames +available to clients. There are several collections of frames maintained +by the Frame Manager. The most basic is a list of all of the frames starting +at the root frame. Clients generally do not want to incur the expense of +traversing all of the frames from the root to find the frame they are interested +in, so the Frame Manager provides some other mappings based on the needs of +the clients.<br> +<br> +The most crucial mapping is the Primary Frame Map. This collection provides +access to a frame that is designated as the primary frame for a piece of +content. When a frame is created for a piece of content, it may be the 'primary +frame' for that content element (content elements that require multiple +frames have primary and secondary frames; only the primary frame is mapped). +The Frame Manager is then instructed to store the mapping from a content +element to the primary frame. This mapping facilitates updates to frames +that result in changes to content (see <a href="#DHTML_interaction">discussion +above</a>).<br> +<br> +Another important mapping maintained by the Frame Manager is that of the +undisplayed content. When a content element is defined as having no display +(via the CSS property 'display:none') it is noted by a special entry in the +undisplayed map. This is important because no frame is generated for these +elements yet changes to their style values and to the content elements still +need to be handled by layout, in case their display state changes from 'none' +to something else. The Undisplayed Map keeps track of all content and style +data for elements that currently have no frames. (<font color="#990000">note: +the original architecture of the layout system included the creation of frames +for elements with no display. This changed somewhere along the line, but +there is no indication of why the change was made. Presumably it is more +time and space-efficient to prevent frame creation for elements with no display.)</font><br> +<br> +The Frame Manager also maintains a list of Forms and Form Controls, as <i>content +nodes</i>. This is presumably related to the fact that layout is responsible +for form submission, but this is a design flaw that is being corrected by +moving form submission into the content world. These collections of Forms +and Form Controls should be removed eventually.<br> +<br> +<h3>CSS Frame Constructor</h3> +The Frame Constructor is responsible for resolving style values for content +elements and creating the appropriate frames corresponding to that element. +In addition to managing the creation of frames, the Frame Constructor is +responsible for managing changes to the frames. Frame Construction is generally +achieved by the use of stateless methods, but in some cases there is the +need to provide context to frames created as children of a container. The +Frame Manager uses the Frame Constructor State class to manage the important +information about the container of a frame being created (<font + color="#990000">and lots of other state-stuff too - need to describe more +fully</font>).<br> +<h3>Frame</h3> +The Frame is the most fundamental layout object. The class nsFrame is the +base class for all frames, and it inherits from the base class nsIFrame (note: +nsIFrame is NOT an interface, it is an abstract base class. It was once an +interface but was changed to be a base class when the Style System was modified +- the name was not changed to reflect that it is not an interface). The Frame +provides generic functionality that can be used by subclasses but cannot +itself be instantiated.<br> +<br> +nsFrame:<br> +The Frame provides a mechanism to navigate to a parent frame as well as child +frames. All frames have a parent except for the root frame. The Frame is +able to provide a reference to its parent and to its children upon request. +The basic data that all frames maintain include: a rectangle describing the +dimensions of the frame, a pointer to the content that the frame is representing, +the style context representing all of the stylistic data corresponding to +the frame, a parent frame pointer, a sibling frame pointer, and a series +of state bits.<br> +<br> +Frames are chained primarily by the sibling links. Given a frame, one can +walk the sibling of that frame, and can also navigate back up to the parent +frame. Specializations of the frame also allow for the management of child +frames; this functionality is provided by the Container Frame.<br> +<br> +Container Frames:<br> +The Container Frame is a specialization of the base frame class that introduces +the ability to manage a list of child frames. All frames that need to manage +child frames (e.g. frames that are not themselves leaf frames) derive from +Container Frame.<br> +<br> +<br> +<br> +<h3>Block Frame<br> +</h3> +<h3>Reflow State</h3> +<h3>Reflow Metrics<br> +</h3> +<h3>Space Manager<br> +</h3> +<h3>StyleSet</h3> +<h3>StyleContext</h3> +<br> +<br> +<hr width="100%" size="2"><br> +<b>Document History:<br> +</b> +<ul> + <li>05/20/2002 - Marc Attinasi: created, wrote highest level introduction +to general layout concepts, links to relevant specs and existing documents.<br> + </li> +</ul> +</body> +</html> diff --git a/layout/doc/SpaceManagerClasses.gif b/layout/doc/SpaceManagerClasses.gif Binary files differnew file mode 100644 index 000000000..71d89da74 --- /dev/null +++ b/layout/doc/SpaceManagerClasses.gif diff --git a/layout/doc/SpaceManagerClasses.png b/layout/doc/SpaceManagerClasses.png Binary files differnew file mode 100644 index 000000000..a51c839be --- /dev/null +++ b/layout/doc/SpaceManagerClasses.png diff --git a/layout/doc/SpaceMgr_BlockReflSt_OD.sda b/layout/doc/SpaceMgr_BlockReflSt_OD.sda Binary files differnew file mode 100644 index 000000000..145f8d282 --- /dev/null +++ b/layout/doc/SpaceMgr_BlockReflSt_OD.sda diff --git a/layout/doc/adding-style-props.html b/layout/doc/adding-style-props.html new file mode 100644 index 000000000..c654a55d5 --- /dev/null +++ b/layout/doc/adding-style-props.html @@ -0,0 +1,479 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <meta name="author" content="Marc Attinasi"><title>Adding a new style property - layout cookbook</title></head> + +<body> +<h1>Adding a new style property</h1> +<blockquote> + <h4>Document history:</h4> + <ul> + <li>03/21/2002: Marc Attinasi (attinasi@netscape.com) created document +/ implementing -moz-force-broken-image-icon for bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646"> +58646</a></li> + <li> + 6/18/2002: David Baron (dbaron@dbaron.org): corrected support + for 'inherit' and 'initial' (didn't test with code, though), + and explained what the final boolean in CheckPropertyData is for. + </li> + <li> + 11/09/2002: Christopher Aillon (caillon@returnzero.com): updated + nsCSSPropList.h macro description and added information about + nsIDOMCSS2Properties.idl. + </li> + </ul> + <p> + <b>NOTE</b>: This document is still missing a few pieces. I need to + add information on adding to <code>nsComputedDOMStyle</code>. + </p> + </blockquote> + <h2>Overview</h2> +When a new style property is needed there are many places in the code that +need to be updated. This document outlines the procedure used to add a new +property, in this case the property is a proprietary one called '-moz-force-broken-image-icons' +and is used as a way for a stylesheet to force broken image icons to be displayed. +This is all being done in the context of <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646"> +bug 58646</a>. + + <h2>Analysis</h2> +<p>Up front you have to decide some things about the new property:</p> + +<p><b>Questions:</b></p> + <ol> + <li>Is the property proprietary or specified by the CSS standard?</li> + <li>Is the property inherited?</li> + <li>What types of values can the property have?</li> + <li>Does it logically fit with other existing properties?</li> + <li>What is the impact to the layout of a page if that property changes?</li> + <li>What do you want to name it?</li> + </ol> +<p><b>Answers:</b></p> + <ol> + <li>In our specific case, we want a property that is used internally, +so it is a proprietary property.</li> + <li>The property is to be used for images, which are leaf elements, so +there is no need to inherit it.</li> + <li>The property is used simply to force a broken image to be represented +by an icon, so it only supports the values '0' and '1' as numerics. </li> + <li>It is hard to see how this property fits logically in with other +properties, but if we stretch our imaginations we could say that it is a +sort of UI property.</li> + <li>If this property changes, the image frame has to be recreated. This +is because the decision about whether to display the icon or not will impact +the decision to replace the image frame with an inline text frame for the +ALT text, so if the ALT text inline is already made, there is no image frame +left around to reflow or otherwise modify.</li> + <li>Finally, the name will be '-moz-force-broken-image-icons' - that +should be pretty self-describing (by convention we start proprietary property +names with '-moz-').</li> + </ol> + <h2>Implementation</h2> + +<p>There are several places that need to be educated about a new style property. +They are: +</p> + <ul> + <li><a href="#CSSPropList">CSS Property Names and Hint Tables</a>: the new +property name must be made formally know to the system</li> + <li><a href="#CSSDeclaration">CSS Declaration</a>: the declaration must be +able to hold the property and its value(s)</li> + <li><a href="#Parser">CSS Parser</a>: the parser must be able to parse the +property name, validate the values, and provide a declaration for the property +and value</li> + <li><a href="#StyleContext">Style Context</a>: the StyleContext must be able +to hold the resolved value of the property, and provide a means to retrieve the +property value. Additionally, the StyleContext has to know what kind of impact a +change to this property causes.</li> + <li><a href="#RuleNode">Rule Nodes</a>: the RuleNodes need to know how the +property is inherited and how it is shared by other elements.</li> + <li><a href="#DOM">DOM</a>: Your style should be accessible from the DOM so +users may dynamically set/get its property value.</li> + <li><a href="#Layout">Layout</a>: layout has to know what to do with the +property, in other words, the meaning of the property.</li> + </ul> + <h3><a name="CSSPropList">CSS Property Name / Constants / Hints</a></h3> + +<p> +First, add the new name to the property list in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h"> +nsCSSPropList.h</a> + Insert the property in the list alphabetically, using the existing +property names as a template. The format of the entry you will create is: +</p> + <pre>CSS_PROP(-moz-force-broken-image-icons, force_broken_image_icons, MozForceBrokenImageIcons, nsChangeHint_ReconstructFrame) // bug 58646</pre> + +<p>The first value is the formal property name, in other words the property +name as it is seen by the CSS parser.<br> +The second value is the name of the property as it will appear internally.<br> +The third value is the name of the DOM property used to access your style.<br> +The last value indicates what must change when the value of the property +changes. It should be an +<a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsChangeHint.h">nsChangeHint</a>.</p> + +<p>If you need to introduce new constants for the values of the property, they +must be added to <a href="http://lxr.mozilla.org/seamonkey/source/layout/base/public/nsStyleConsts.h"> +nsStyleConsts.h</a> + and to the appropriate keyword tables in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsCSSProps.cpp"> +nsCSSProps.cpp</a> + (note: this cookbook does not do this since the new property does not require +any new keywords for the property values). + <h3><a name="CSSDeclaration">CSS Declaration</a></h3> +Changes will need to be made to the structs and classes defined in <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.h"> +nsCSSDeclaration.h </a> +and <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.cpp"> +nsCSSDeclaration.cpp</a> + <br> + <br> +First, find the declaration of the struct that will hold the new property +value (in the header file). For this example it is the struct <b>nsCSSUserInterface</b> +. Modify the struct declaration to include a new data member for the new +property, of the type CSSValue. Next, open the implementation file (the cpp) +and modify the struct's constructors. <br> + <br> +Next, the <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.cpp#1410"> +AppendValue</a> + method must be updated to support your new property. The CSSParser will +call this to build up a declaration. Find the portion of that method that +deals with the other properties in the struct that you are adding your property +to (or create a new section if you are creating a new style struct). For +this example we will find the 'UserInterface' section and add our new property + <a href="#AppendValueCase">there</a> +.<br> + <pre> // nsCSSUserInterface + case eCSSProperty_user_input: + case eCSSProperty_user_modify: + case eCSSProperty_user_select: + case eCSSProperty_key_equivalent: + case eCSSProperty_user_focus: + case eCSSProperty_resizer: + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icons: { + CSS_ENSURE(UserInterface) { + switch (aProperty) { + case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; + case eCSSProperty_user_modify: theUserInterface->mUserModify = aValue; break; + case eCSSProperty_user_select: theUserInterface->mUserSelect = aValue; break; + case eCSSProperty_key_equivalent: + CSS_ENSURE_DATA(theUserInterface->mKeyEquivalent, nsCSSValueList) { + theUserInterface->mKeyEquivalent->mValue = aValue; + CSS_IF_DELETE(theUserInterface->mKeyEquivalent->mNext); + } + break; + case eCSSProperty_user_focus: theUserInterface->mUserFocus = aValue; break; + case eCSSProperty_resizer: theUserInterface->mResizer = aValue; break; + case eCSSProperty_cursor: + CSS_ENSURE_DATA(theUserInterface->mCursor, nsCSSValueList) { + theUserInterface->mCursor->mValue = aValue; + CSS_IF_DELETE(theUserInterface->mCursor->mNext); + } + break; +<b> <a name="AppendValueCase"></a>case eCSSProperty_force_broken_image_icons: theUserInterface->mForceBrokenImageIcon = aValue; break; +</b> + CSS_BOGUS_DEFAULT; // make compiler happy + } + } + break; + } + +</pre> +The GetValue method must be similarly <a href="#GetValueCase">modified</a> +:<br> + <pre> // nsCSSUserInterface + case eCSSProperty_user_input: + case eCSSProperty_user_modify: + case eCSSProperty_user_select: + case eCSSProperty_key_equivalent: + case eCSSProperty_user_focus: + case eCSSProperty_resizer: + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icons: { + CSS_VARONSTACK_GET(UserInterface); + if (nullptr != theUserInterface) { + switch (aProperty) { + case eCSSProperty_user_input: aValue = theUserInterface->mUserInput; break; + case eCSSProperty_user_modify: aValue = theUserInterface->mUserModify; break; + case eCSSProperty_user_select: aValue = theUserInterface->mUserSelect; break; + case eCSSProperty_key_equivalent: + if (nullptr != theUserInterface->mKeyEquivalent) { + aValue = theUserInterface->mKeyEquivalent->mValue; + } + break; + case eCSSProperty_user_focus: aValue = theUserInterface->mUserFocus; break; + case eCSSProperty_resizer: aValue = theUserInterface->mResizer; break; + case eCSSProperty_cursor: + if (nullptr != theUserInterface->mCursor) { + aValue = theUserInterface->mCursor->mValue; + } + break; +<b> <a name="GetValueCase"></a>case eCSSProperty_force_broken_image_icons: aValue = theUserInterface->mForceBrokenImageIcons; break; +</b> + CSS_BOGUS_DEFAULT; // make compiler happy + } + } + else { + aValue.Reset(); + } + break; + } + +</pre> +Finally <a href="#ListCase">modify </a> +the 'List' method to output the property value.<br> + <pre>void nsCSSUserInterface::List(FILE* out, int32_t aIndent) const +{ + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); + + nsAutoString buffer; + + mUserInput.AppendToString(buffer, eCSSProperty_user_input); + mUserModify.AppendToString(buffer, eCSSProperty_user_modify); + mUserSelect.AppendToString(buffer, eCSSProperty_user_select); + nsCSSValueList* keyEquiv = mKeyEquivalent; + while (nullptr != keyEquiv) { + keyEquiv->mValue.AppendToString(buffer, eCSSProperty_key_equivalent); + keyEquiv= keyEquiv->mNext; + } + mUserFocus.AppendToString(buffer, eCSSProperty_user_focus); + mResizer.AppendToString(buffer, eCSSProperty_resizer); + + nsCSSValueList* cursor = mCursor; + while (nullptr != cursor) { + cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); + cursor = cursor->mNext; + } + + <b> <a name="ListCase"></a>mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icons);</b> + + fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); +} + +</pre> + + <h3><a name="Parser">CSS Parser</a></h3> +Next, the CSSParser must be educated about this new property so that it can +read in the formal declarations and build up the internal declarations that +will be used to build the rules. If you are adding a simple property that +takes a single value, you simply add your new property to the ParseSingleProperty +method. If a more complex parsing is required you will have to write a new +method to handle it, modeling it off of one of the existing parsing helper +methods (see <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#4151"> +ParseBackground</a> +, for and example). We are just adding a simple single-value property here.<br> + <br> +Open nsCSSParser.cpp and look for the method <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#3580"> +ParseSingleProperty</a> +. This method is responsible for calling the relevant helper routine to parse +the value(s). Find an existing property that is similar to the property you +are adding. For our example we are adding a property that takes a numeric +value so we will model it after the 'height' property and call ParsePositiveVariant. +Add a new case for the new property and call the appropriate parser-helper +and make a call to ParseVariant passing the <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#2754"> +variant flag</a> + that makes sense for your property. In our case<br> + <br> + <pre> case eCSSProperty_force_broken_image_icons:</pre> + <pre> return ParsePositiveVariant(aErrorCode, aValue, VARIANT_INTEGER, nullptr);</pre> +This will parse the value as a positive integer value, which is what we want.<br> + <br> + <h3><a name="StyleContext">Style Context</a></h3> +Having implemented support for the new property in the CSS Parser and CSS +Declaration classes in the content module, it is now time to provide support +for the new property in layout. The Style Context must be given a new data +member corresponding to the declaration's new data member, so the computed +value can be held for the layout objects to use.<br> + <br> +First look into <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsStyleStruct.h"> +nsStyleStruct.h</a> + to see the existing style strucs. Find the one that you want to store the +data on. In this example, we want to put it on the nsStyleUserInterface struct, +however there is also a class nsStyleUIReset that holds the non-inherited +values, so we will use that one (remember, our property is not inherited). +Add a <a href="#StyleContextMember">data member</a> + to hold the value: + <pre>struct nsStyleUIReset { + nsStyleUIReset(void); + nsStyleUIReset(const nsStyleUIReset& aOther); + ~nsStyleUIReset(void); + + NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_UIReset) + + void* operator new(size_t sz, nsPresContext* aContext) { + return aContext->AllocateFromShell(sz); + } + void Destroy(nsPresContext* aContext) { + this->~nsStyleUIReset(); + aContext->FreeToShell(sizeof(nsStyleUIReset), this); + }; + + int32_t CalcDifference(const nsStyleUIReset& aOther) const; + + uint8_t mUserSelect; // [reset] (selection-style) + PRUnichar mKeyEquivalent; // [reset] XXX what type should this be? + uint8_t mResizer; // [reset] + <b><a name="StyleContextMember"></a>uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)</b> +}; +</pre> +In the implementation file <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsStyleStruct.cpp"> +nsStyleContext.cpp </a> +add the new data member to the constructors of the style struct and the CalcDifference +method, which must return the correct style-change hint when a change to +your new property is detected. The constructor changes are obvious, but here +is the CalcDifference change for our example:<br> + <pre>int32_t nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const +{ + <b> if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {</b> + if (mResizer == aOther.mResizer) { + if (mUserSelect == aOther.mUserSelect) { + if (mKeyEquivalent == aOther.mKeyEquivalent) { + return NS_STYLE_HINT_NONE; + } + return NS_STYLE_HINT_CONTENT; + } + return NS_STYLE_HINT_VISUAL; + } + return NS_STYLE_HINT_VISUAL; + } + <b>return nsChangeHint_ReconstructFrame; +</b>} +</pre> + <h3>CSSStyleRule</h3> +The nsCSSStyleRule must be updated to manage mapping the declaration to the +style struct. In the file <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSStyleRule.cpp"> +nsCSSStyleRule.cpp</a> +, locate the Declaration mapping function corresponding to the style struct +you have added your property to. For example, we <a href="http://bugzilla.mozilla.org/MapUIForDeclChange"> +update </a> +MapUIForDeclaration:<br> + <pre>static nsresult +MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUserInterface& aUI) +{ + if (!aDecl) + return NS_OK; // The rule must have a declaration. + + nsCSSUserInterface* ourUI = (nsCSSUserInterface*)aDecl->GetData(kCSSUserInterfaceSID); + if (!ourUI) + return NS_OK; // We don't have any rules for UI. + + if (aID == eStyleStruct_UserInterface) { + if (aUI.mUserFocus.GetUnit() == eCSSUnit_Null && ourUI->mUserFocus.GetUnit() != eCSSUnit_Null) + aUI.mUserFocus = ourUI->mUserFocus; + + if (aUI.mUserInput.GetUnit() == eCSSUnit_Null && ourUI->mUserInput.GetUnit() != eCSSUnit_Null) + aUI.mUserInput = ourUI->mUserInput; + + if (aUI.mUserModify.GetUnit() == eCSSUnit_Null && ourUI->mUserModify.GetUnit() != eCSSUnit_Null) + aUI.mUserModify = ourUI->mUserModify; + + if (!aUI.mCursor && ourUI->mCursor) + aUI.mCursor = ourUI->mCursor; + + + } + else if (aID == eStyleStruct_UIReset) { + if (aUI.mUserSelect.GetUnit() == eCSSUnit_Null && ourUI->mUserSelect.GetUnit() != eCSSUnit_Null) + aUI.mUserSelect = ourUI->mUserSelect; + + if (!aUI.mKeyEquivalent && ourUI->mKeyEquivalent) + aUI.mKeyEquivalent = ourUI->mKeyEquivalent; + + if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null) + aUI.mResizer = ourUI->mResizer; + <b> + <a name="MapUIForDeclChange"></a>if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer) + aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon;</b> + } + + return NS_OK; + +} +</pre> + <h3><a name="RuleNode">Rule Node</a></h3> +Now we have to update the RuleNode code to know about the new property. First, +locate the PropertyCheckData array for the data that you added the new property +to. For this example, we add the following:<br> + <pre>static const PropertyCheckData UIResetCheckProperties[] = { + CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE), + CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE), + CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE) + <b>CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE)</b> +}; +</pre> +The first two arguments correspond to the structure and data member from +the CSSDeclaration, the third is the data type, the fourth indicates +whether it is a coord value that uses an explicit inherit value on the +style data struct that must be computed by layout.<br> + <br> +Next, we have to make sure the ComputeXXX method for the structure the property +was added to is updated to mange the new value. In this example we need to +modify the nsRuleNode::ComputeUIResetData method to handle the CSS Declaration +to the style struct:<br> + <pre> ... + // resizer: auto, none, enum, inherit + if (eCSSUnit_Enumerated == uiData.mResizer.GetUnit()) { + ui->mResizer = uiData.mResizer.GetIntValue(); + } + else if (eCSSUnit_Auto == uiData.mResizer.GetUnit()) { + ui->mResizer = NS_STYLE_RESIZER_AUTO; + } + else if (eCSSUnit_None == uiData.mResizer.GetUnit()) { + ui->mResizer = NS_STYLE_RESIZER_NONE; + } + else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) { + inherited = PR_TRUE; + ui->mResizer = parentUI->mResizer; + } + + <b>// force-broken-image-icons: integer, inherit, initial + if (eCSSUnit_Integer == uiData.mForceBrokenImageIcons.GetUnit()) { + ui->mForceBrokenImageIcons = uiData.mForceBrokenImageIcons.GetIntValue(); + } else if (eCSSUnit_Inherit == uiData.mForceBrokenImageIcons.GetUnit()) { + inherited = PR_TRUE; + ui->mForceBrokenImageIcons = parentUI->mForceBrokenImageIcons; + } else if (eCSSUnit_Initial == uiData.mForceBrokenImageIcons.GetUnit()) { + ui->mForceBrokenImageIcons = 0; + }</b> + + if (inherited) + // We inherited, and therefore can't be cached in the rule node. We have to be put right on the + // style context. + aContext->SetStyle(eStyleStruct_UIReset, *ui); + else { + // We were fully specified and can therefore be cached right on the rule node. + if (!aHighestNode->mStyleData.mResetData) + aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; + aHighestNode->mStyleData.mResetData->mUIData = ui; + // Propagate the bit down. + PropagateDependentBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode); + } + ... +</pre> + <h3><a name="DOM">DOM</a></h3> +Users in scripts, or anywhere outside of layout/ or content/ may need to access +the new property. This is done using the CSS OM, specifically +<code>nsIDOMCSSStyleDeclaration</code> and <code>CSS2Properties</code>. +By the magic of C++ pre-processing, the +CSS2Properties bits will be implemented automatically when you +<a href="#CSSPropList">add your property</a> to <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h"> +nsCSSPropList.h</a>. + <h3><a name="Layout">Layout</a></h3> +OK, finally the style system is supporting the new property. It is time to +actually make use of it now.<br> + <br> +In layout, retrieve the styleStruct that has the new property from the frame's +style context. Access the new property and get its value. It is that simple. +For this example, it looks like this, in nsImageFrame:<br> + <pre> PRBool forceIcon = PR_FALSE; + + if (StyleUIReset()->mForceBrokenImageIcon) { + forceIcon = PR_TRUE; + } + +</pre> +Create some testcases with style rules that use the new property, make sure +it is being parsed correctly. Test it in an external stylesheet and in inline +style. Test that it is inherited correctly, or not inherited as appropriate +to your property. Update this document with any further details, or correcting +any errors.<br> + </body></html> diff --git a/layout/doc/dd-template.html b/layout/doc/dd-template.html new file mode 100644 index 000000000..03903ed86 --- /dev/null +++ b/layout/doc/dd-template.html @@ -0,0 +1,116 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <title>Layout Detailed Design Template</title> + <meta name="author" content="Marc Attinasi (attinasi@netscape.com)"> +</head> + <body> + +<h1><font color="#cc0000">Gecko Layout Detailed Design Document Template</font></h1> + [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.]<br> + <br> + +<h1>[Component / Class Name] Detailed Design</h1> + +<h2>Overview</h2> + [Introduce the scope of this design document: what is being documented here. +Provide a reference back to the High Level design(s) that correspond.]<br> + +<hr width="100%" size="2"> +<h2>[Class / Component A]</h2> + [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.]<br> + <br> + +<h3>Public API</h3> + [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.]<br> + +<h3>Protected API</h3> + [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.]<br> + <br> + +<h3>Implementation Notes</h3> + [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.]<br> + +<h4>Algorithms</h4> + +<h5>[Interesting Algorithm 1: The internally maintained sorted list]</h5> + [explain the nature of the algorithm, the reason it was chosen, the types +of input it 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.]<br> + +<h5>[Interesting Algorithm 2: Handling overflow of the input buffer]</h5> + [your description here]<br> + +<h4></h4> + +<hr width="100%" size="2"> +<h2>[Class / Component B]</h2> + [Repeat the structure for the next class or component.]<br> + <br> + +<hr width="100%" size="2"> +<h2>Cross-Component Algorithms</h2> + [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.]<br> + +<h3>[Turning a byte-stream into a fully parsed token-tree]</h3> + [Detailed description, pesudo-code, state transitions, etc.]<br> + +<h3>[Managing updates to the document]</h3> + [Detailed description, pesudo-code, state transitions, etc.]<br> + <br> + +<hr width="100%" size="2"> +<h2>Tech Notes</h2> + [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.]<br> + +<ul> + <li>[<a href="link%20to%20tech%20note">Debugging buffer overflows</a> + ]</li> + <li>[<a href="link%20to%20tech%20note">Adding new element or attribute +types</a> + ]</li> + <li>[<a href="link%20to%20tech%20note">How To detect and fix problems +with the alignment of elements</a> + ]</li> + <li>[<a href="link%20to%20tech%20note">Fix for Bug 666: ownership of tokens +was mistakenly transferred</a> + ]</li> + +</ul> + <br> + +</body> +</html> diff --git a/layout/doc/debugtable.html b/layout/doc/debugtable.html new file mode 100644 index 000000000..9c2ce0f8e --- /dev/null +++ b/layout/doc/debugtable.html @@ -0,0 +1,245 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> + +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + + <style type="text/css"> + body {font-family:arial} +.log {background-color:silver; color:blue} +pre.log {display:table-cell} + </style> + + <title>Debugging facilities in HTML-Table code</title> +</head> +<body> + <h1>Debugging facilities in HTML-table code</h1> + <h2>Reflow</h2> + <p>The most efficient tool to claim that html-table code is the victim and not the source of layout bugs is a <a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/frame_reflow_debug.html">frame reflow debug log</a>. Look there especially how the maxElementsize (MES) and desired size are propagated. + + <h2>Block Reflow</h2> +<p> +Another way to debug the reflow process is implemented inside <a href="http://lxr.mozilla.org/seamonkey/source/layout/html/base/src/nsBlockFrame.cpp">nsBlockFrame.cpp</a>. It can be invoked by<p> +<code>set GECKO_BLOCK_DEBUG_FLAGS=reflow</code> +<p> +The available options are: +<ul> +<li><code>reflow</code> +<li> <code>really-noisy-reflow</code> +<li><code>max-element-size</code> +<li><code> space-manager</code> +<li><code>verify-lines</code> +<li><code>damage-repair</code> +<li><code>lame-paint-metrics</code> +<li><code>lame-reflow-metrics</code> +<li><code>disable-resize-opt</code> +</ul> +<p> +These options can be combined with a comma separated list +Messages generated by the <code>reflow</code> switch: +<ul> +<li><code> Block(div)(1)@00BE5AC4: reflowing dirty lines computedWidth=9000 computedHeight=1500</code> +<ul> +<li> this message is generated inside of <br> +<code>nsresult nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)</code> +<li> it first shows the Block ID and Address +<li>and then the computed width and Height from the HTMLReflowState. +</ul> +</ul> + +<h2>DEBUG_TABLE_STRATEGY</h2> +<p> +The table layout strategy can be visualized by defining in the <a href="http://lxr.mozilla.org/seamonkey/source/layout/html/table/src/Makefile.in">makefiles</a> the constant DEBUG_TABLE_STRATEGY. + +If one takes for instance the following table +<table cellspacing="10"><tr><th>rendering</th><th>code</th></tr> +<tr valign="top"><td valign="top" style="padding-top:10px"> +<table border width="300"> +<colgroup> +<col> +<col width="50%"> +<col width="1*"> +<col> +</colgroup> + <tr> + <td style="width:80px">cell 1</td> + <td>cell 2</td> + <td>cell 3</td> + <td>cell 4</td> + </tr> +</table> +</td> +<td valign="top"><pre class="log"> +<table border width="300"> +<colgroup> +<col> +<col width="50%"> +<col width="1*"> +<col> +</colgroup> + <tr> + <td style="width:80px">cell 1</td> + <td>cell 2</td> + <td>cell 3</td> + <td>cell 4</td> + </tr> +</table> +</pre> +</td> +</tr> +</table> +<p> +it will produce the following log at the entrance of <code>AssignNonPctColWidths</code>: +<p> +<table class="log"><tr><td> +<pre> +AssignNonPctColWidths en max=4500 count=0 +***START TABLE DUMP*** +mColWidths=-1 -1 -1 -1 + + col frame cache -> +0=00B93138 1=00B931F0 2=024DD728 3=024DD780 + **START COL DUMP** colIndex=0 isAnonymous=0 constraint=0 + widths=-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 **END COL DUMP** + **START COL DUMP** colIndex=1 isAnonymous=0 constraint=0 + widths=-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 **END COL DUMP** + **START COL DUMP** colIndex=2 isAnonymous=0 constraint=0 + widths=-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 **END COL DUMP** + **START COL DUMP** colIndex=3 isAnonymous=0 constraint=0 + widths=-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 **END COL DUMP** +***END TABLE DUMP*** +</pre> +</td></tr></table> + + +<p> +The <span class="log">en</span> stands for entrance (<span class="log">ex</span> for leaving a routine). The first line of the data dump shows that no width has yet been assigned to the columns <span class="log">mColWidths=-1 -1 -1 -1</span>, <code>-1</code> stands for: +<pre> +#define WIDTH_NOT_SET -1 +</pre> +<p> +This is followed by a reference to the column frame pointers: +<p> +<pre class="log"> +col frame cache -> +0=00B93138 1=00B931F0 2=024DD728 3=024DD780 +</pre> +<p> +This is followed by the information which width has been set for each column. The index of the column, whether it is anonymous and what kind of constrained has been applied<span class="log">colIndex=0 isAnonymous=0 constraint=0</span>. The following constraint types are known: +<p> +<pre> + eNoConstraint = 0, + ePixelConstraint = 1, // pixel width + ePercentConstraint = 2, // percent width + eProportionConstraint = 3, // 1*, 2*, etc. cols attribute assigns 1* + e0ProportionConstraint = 4 // 0*, means to force to min width +</pre> +<p> +After this follows the width information for each column: +<p> +<pre class="log"> +widths=-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +</pre> +<p> +The table code knows ten different width's: +<pre> +#define NUM_WIDTHS 10 +#define NUM_MAJOR_WIDTHS 3 // MIN, DES, FIX +#define MIN_CON 0 // minimum width required of the content + padding +#define DES_CON 1 // desired width of the content + padding +#define FIX 2 // fixed width either from the content or cell, col, etc. + padding +#define MIN_ADJ 3 // minimum width + padding due to col spans +#define DES_ADJ 4 // desired width + padding due to col spans +#define FIX_ADJ 5 // fixed width + padding due to col spans +#define PCT 6 // percent width of cell or col +#define PCT_ADJ 7 // percent width of cell or col from percent colspan +#define MIN_PRO 8 // desired width due to proportional <col>s or cols attribute +#define FINAL 9 // width after the table has been balanced, considering all of the others +</pre> +<p> +In the last log snippet none of these width's has been set. +Leaving AssignNonPctColWidths shows that already to all columns a width of 360 twips has been assigned +<pre class="log"> +AssignNonPctColWidths ex +***START TABLE DUMP*** +mColWidths=360 360 360 360 + + col frame cache -> +0=00B93138 1=00B931F0 2=024DD728 3=024DD780 + **START COL DUMP** colIndex=0 isAnonymous=0 constraint=0 + widths=360 540 1230 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** + **START COL DUMP** colIndex=1 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** + **START COL DUMP** colIndex=2 isAnonymous=0 constraint=3 + widths=360 540 -1 -1 -1 -1 -1 -1 540 360 **END COL DUMP** + **START COL DUMP** colIndex=3 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** +***END TABLE DUMP*** +</pre> +<p> +The first column has already the minimum content width, the table column can't shrink below that, the desired content width of <span class="log">540</span> twips, that's the space to layout <code>cell 1</code> without wrapping the text and the <span class="log">1230</span> which correspond to the <code>style="width:80px"</code> at the first cell. At this step the final size is <span class="log">360</span> twips. +<p> +<table cellpadding="8"> +<tr> +<th> MIN_CON</th><th>DES_CON</th><th>FIX</th><th>MIN_ADJ</th><th>DES_ADJ</th><th>FIX_ADJ</th><th>PCT</th><th> PCT_ADJ</th><th> MIN_PRO</th><th>FINAL</th> +</tr> +<tr align="center"> +<td>360</td><td> 540</td><td> 1230 </td><td>-1</td><td> -1 </td><td>-1</td><td> -1</td><td> -1</td><td> -1</td><td> 360</td></tr></table> +<p> +There was no change till the entrance of <code>BalanceColumnWidths +</code> +<p> +<pre class="log"> +BalanceColumnWidths en count=1 +***START TABLE DUMP*** +mColWidths=360 360 360 360 + + col frame cache -> +0=00B93138 1=00B931F0 2=024DD728 3=024DD780 + **START COL DUMP** colIndex=0 isAnonymous=0 constraint=0 + widths=360 540 1230 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** + **START COL DUMP** colIndex=1 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** + **START COL DUMP** colIndex=2 isAnonymous=0 constraint=3 + widths=360 540 -1 -1 -1 -1 -1 -1 540 360 **END COL DUMP** + **START COL DUMP** colIndex=3 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 -1 -1 -1 360 **END COL DUMP** +***END TABLE DUMP*** +</pre> +<p> +But at the end the final distribution between the columns has been reached. +<p> +<pre class="log"> +BalanceColumnWidths ex +***START TABLE DUMP*** +mColWidths=1230 2160 465 465 + + col frame cache -> +0=00B93138 1=00B931F0 2=024DD728 3=024DD780 + **START COL DUMP** colIndex=0 isAnonymous=0 constraint=0 + widths=360 540 1230 -1 -1 -1 -1 -1 -1 1230 **END COL DUMP** + **START COL DUMP** colIndex=1 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 2160 -1 -1 2160 **END COL DUMP** + **START COL DUMP** colIndex=2 isAnonymous=0 constraint=3 + widths=360 540 -1 -1 -1 -1 -1 -1 540 465 **END COL DUMP** + **START COL DUMP** colIndex=3 isAnonymous=0 constraint=0 + widths=360 540 -1 -1 -1 -1 -1 -1 -1 465 **END COL DUMP** +***END TABLE DUMP*** +</pre> +<p> +The column dump is implemented in <code>nsTableColFrame.cpp</code> in the routine: +<code>void nsTableColFrame::Dump(int32_t aIndent)</code>. + +<h2>DEBUG_TABLE_REFLOW_TIMING</h2> +<p>needs to be written + +<hr> +<p style="text-align:right">author: Bernd Mielke <br>2002-06-05</p> + +</body> + +</html> diff --git a/layout/doc/frame_reflow_debug.html b/layout/doc/frame_reflow_debug.html new file mode 100644 index 000000000..e85672650 --- /dev/null +++ b/layout/doc/frame_reflow_debug.html @@ -0,0 +1,224 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <style type="text/css"> + body {font-family:arial} +.log {background-color:silver; color:blue} + </style> + <title> Debugging Frame Reflow</title> + </head> + <body> +<h1>Debugging Frame Reflow HowTo</h1> +<h2>General Overview</h2> +<p> The frame reflow can be logged with the debug capabilities implemented in <a href="http://lxr.mozilla.org/seamonkey/source/layout/html/base/src/nsFrame.cpp"><code>nsFrame.cpp</code></a>. +It provides the following information for each frame at the +start of its reflow +<ul> +<li>reflow reason +<li>available width, available height +<li>computed width, computed height +<li>the previous and the next frame in flow +<li>and a count number. +</ul> +<p>When the frame's reflow is finished the following information is displayed :</p> +<ul> +<li>reflow metric (desired) width, height +<li>max. element size (MES) width +<li>maximum Width +<li>frame status +<li>overflow area +</ul> + +<h2>Getting the log</h2> +<ul> +<li>Make sure that your build is a <b>debug</b> build. +<li>Create a text file (for instance <code>reflow_rules.txt</code>). +<li>Enter this line in the text file <pre>* 1</pre> +<li>Save the text file in the <code>%DIST%</code> directory +<li>Go to the <code>%DIST%</code> directory +<li>enter from command line: <code>set GECKO_DISPLAY_REFLOW_RULES_FILE=reflow_rules.txt</code> +<li> Run <code>viewer > logfile.txt</code> and load your testcase. The +logfile will contain all the promised information. +</ul> +<h2>Log File analyis</h2> +<p>The logfile for a simple table like</p> +<pre> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> +</head> +<body> +<table width="100"> + <tbody> + <tr> + <td>foo</td> + </tr> + </tbody> +</table> +</body> +</html> +</pre> + +<p> will create the following log:</p> +<table class="log"><tr><td> +<pre> +VP 00B97C30 r=0 a=9180,4470 c=9180,4470 cnt=856 + scroll 00B97EE0 r=0 a=9180,4470 c=9180,4470 cnt=857 + scroll 00B97EE0 r=0 a=9180,4470 c=9180,4470 cnt=858 + canvas 00B97C6C r=0 a=9180,UC c=9180,4470 cnt=859 + area 02D7AFE4 r=0 a=9180,UC c=9180,UC cnt=860 + text 02D7B150 r=0 a=9180,UC c=UC,UC cnt=861 + text 02D7B150 d=0,0 + block 02D7B210 r=0 a=9180,UC c=8940,UC cnt=862 + block 02D7B210 d=8940,0 + area 02D7AFE4 d=9180,120 + canvas 00B97C6C d=9180,4470 + scroll 00B97EE0 d=9180,4470 + scroll 00B97EE0 d=9180,4470 +VP 00B97C30 d=9180,4470 +VP 00B97C30 r=1 a=9180,4470 c=9180,4470 cnt=863 + scroll 00B97EE0 r=1 a=9180,4470 c=9180,4470 cnt=864 + scroll 00B97EE0 r=1 a=9180,4470 c=9180,4470 cnt=865 + canvas 00B97C6C r=1 a=9180,UC c=9180,4470 cnt=866 + area 02D7AFE4 r=1 a=9180,UC c=9180,UC cnt=867 + block 02D7B210 r=1 a=9180,UC c=8940,UC cnt=868 + text 02D7B3F8 r=0 a=8940,UC c=UC,UC cnt=869 + text 02D7B3F8 d=0,0 + tblW 02D7B5F0 r=0 a=8940,UC c=0,0 cnt=870 + tbl 02D7B7EC r=0 a=8940,UC c=1500,UC cnt=871 + rowG 00B984A4 r=0 a=UC,UC c=UC,UC cnt=872 + row 02D7BAF8 r=0 a=UC,UC c=UC,UC cnt=873 + cell 02D7BC98 r=0 a=UC,UC c=UC,UC cnt=874 + block 02D7BCF8 r=0 a=UC,UC c=UC,UC cnt=875 + text 02D7BE84 r=0 a=UC,UC c=UC,UC cnt=876 + text 02D7BE84 d=300,285 me=300 + block 02D7BCF8 d=300,300 me=300 + cell 02D7BC98 d=330,330 me=330 + row 02D7BAF8 d=UC,330 + rowG 00B984A4 d=UC,330 + colG 02D7BFB0 r=0 a=UC,UC c=UC,UC cnt=877 + col 02D7C0D8 r=0 a=0,0 c=1500,UC cnt=878 + col 02D7C0D8 d=0,0 + colG 02D7BFB0 d=0,0 + rowG 00B984A4 r=2 a=1500,UC c=1500,UC cnt=879 + row 02D7BAF8 r=2 a=1500,UC c=1500,UC cnt=880 + cell 02D7BC98 r=2 a=1440,UC c=1410,UC cnt=881 + block 02D7BCF8 r=2 a=1410,UC c=1410,UC cnt=882 + block 02D7BCF8 d=1410,300 + cell 02D7BC98 d=1440,330 + row 02D7BAF8 d=1500,330 + rowG 00B984A4 d=1500,330 + colG 02D7BFB0 r=2 a=1500,UC c=1500,UC cnt=883 + col 02D7C0D8 r=0 a=0,0 c=1500,UC cnt=884 + col 02D7C0D8 d=0,0 + colG 02D7BFB0 d=0,0 + tbl 02D7B7EC d=1500,390 + tblW 02D7B5F0 d=1500,390 + text 02D7C130 r=0 a=8940,UC c=UC,UC cnt=885 + text 02D7C130 d=0,0 + block 02D7B210 d=8940,390 + area 02D7AFE4 d=9180,630 + canvas 00B97C6C d=9180,4470 + scroll 00B97EE0 d=9180,4470 + scroll 00B97EE0 d=9180,4470 +VP 00B97C30 d=9180,4470 +</pre> +</td></tr></table> +<p> +The first line shows the reflow of the viewport (<code class="log">VP</code>). This viewport has the address <code class="log">00B97C30</code>. It is the initial reflow: <code class="log">r=0</code>. Other reflow reasons are: </p> +<table> +<tr><td>1</td><td>incremental reflow</td></tr> +<tr><td>2</td><td>resize reflow</td></tr> +<tr><td>3</td><td>style change reflow</td></tr> +<tr><td>4</td><td>dirty reflow.</td></tr> +</table> + +<p>The available width is 9180 twips. The available height is 4470 twips (<code class="log">a=9180,4470</code>). The computed width is 9180 twips. The computed height is 4470 twips (<code class="log">c=9180,4470</code>). The line count is 856 (<code class="log">cnt=856</code>). +<p> +Below this is a line that reads:<p><code class="log">tblW 02D7B5F0 r=0 a=8940,UC c=0,0 cnt=870</code></p><p> Here the <code class="log">UC</code> shows that on initial reflow the available height for the table wrapper frame is unconstrained. +<p> +The table cell requires its children to compute the MES. It is reported back from the block as: +<p><code class="log">block 02D7BCF8 d=300,300 me=300</code></p> +<p>The block max. element size is 300 twips. +<p> The second table reflow is started at +<p><code class="log">rowG 00B984A4 r=2 a=1500,UC c=1500,UC cnt=879</code></p> +<p>where the previous information is used. +The block has been required to compute the max. element size only once and it reports now: +<p> <code class="log">block 02D7BCF8 d=1410,300</code></p> +<p>The block shows the same address as the previous one. +<p>Frames with children that overflow the parent will return <code>PR_TRUE</code> from <code>HasOverflowRect()</code>. For these frames +the overflow area is displayed as <code class="log">block 025ED8F0 d=8940,1020 o=(0,0) 9180 x 1020</code>. The overflow area is specified as (x,y) origin and width x height. +<p> The reflow finishes at the same level where it started. + +<h2>Advanced reflow debugging</h2> +<p>The previously described technique dumps the data for every frame. Sometimes the log is clearer if only the main frames are shown. +The entries in the reflow log can be controlled on a frame level. For instance adding <code>text 0</code> to the rules in <code>reflow_rules.txt</code> would hide the text entries from the reflow. The display of the following frames can be turned on by adding a line with the frame name and <code>1</code> or turned off by adding a line with the frame name and <code>0</code>:</p> +<table cellspacing="5"> + <tr><th style="text-align:left">short name</th><th style="text-align:left">layout tag</th></tr> + <tr><td>area</td><td>area</td></tr> + <tr><td>block</td><td>block</td></tr> + <tr><td>br</td><td>br</td></tr> + <tr><td>bullet</td><td>bullet</td></tr> + <tr><td>button</td><td>gfxButtonControl</td></tr> + <tr><td>hr</td><td>hr</td></tr> + <tr><td>frameI</td><td>htmlFrameInner</td></tr> + <tr><td>frameO</td><td>htmlFrameOuter</td></tr> + <tr><td>img</td><td>image</td></tr> + <tr><td>inline</td><td>inline</td></tr> + <tr><td>letter</td><td>letter</td></tr> + <tr><td>line</td><td>line</td></tr> + <tr><td>select</td><td>select</td></tr> + <tr><td>obj</td><td>object</td></tr> + <tr><td>page</td><td>page</td></tr> + <tr><td>place</td><td>placeholder</td></tr> + <tr><td>canvas</td><td>canvas</td></tr> + <tr><td>root</td><td>root</td></tr> + <tr><td>scroll</td><td>scroll</td></tr> + <tr><td>caption</td><td>tableCaption</td></tr> + <tr><td>cell</td><td>tableCell</td></tr> + <tr><td>bcCell</td><td>bcTableCell</td></tr> + <tr><td>col</td><td>tableCol</td></tr> + <tr><td>colG</td><td>tableColGroup</td></tr> + <tr><td> tbl</td><td>table</td></tr> + <tr><td>tblW</td><td>tableWrapper</td></tr> + <tr><td>rowG</td><td>tableRowGroup</td></tr> + <tr><td>row</td><td>tableRow</td></tr> + <tr><td>textCtl</td><td>textInput</td></tr> + <tr><td>text</td><td>text</td></tr> + <tr><td>VP</td><td>viewport</td></tr> +</table> +<p>Once the problem is reduced to a single frame level, placing a breakpoint at <code>DisplayReflowEnterPrint</code> in <a href="http://lxr.mozilla.org/seamonkey/source/layout/html/base/src/nsFrame.cpp"><code>nsFrame.cpp</code></a> is a very efficient way to step through + the reflow tree. + +<h2>Other reflow debug options</h2> + +<h3>GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS</h3> +<p> +Setting this option via <code>set GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS = 1</code> enables a verification for each coordinate value that the coordinates are aligned at pixel boundaries. +<table class="log"><tr><td> +<pre> + row 0268A594 r=0 a=UC,UC c=UC,20 cnt=870 +VALUE 20 is not a whole pixel + cell 0268A6C0 r=0 a=UC,UC c=UC,15 cnt=871 + block 0268A764 r=0 a=UC,UC c=UC,UC cnt=872 + block 0268A764 d=0,0 me=0 + cell 0268A6C0 d=0,0 me=0 + row 0268A594 d=UC,20 +VALUE 20 is not a whole pixel + rowG 0268A02C d=UC,695 +VALUE 695 is not a whole pixel</pre> +</td></tr></table> +<p> +While unaligned values at the entrance of a frame reflow can be ignored, when they appear at the exit of a routine this can cause display errors like stray lines. OS2 is very vulnerable to pixel alignement errors as text is drawn on pixel boundaries. + +<h3>GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES</h3> +<p> +Setting this option via <code>set GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES = 1</code> will cause an advance of the indent even for frames which are blocked via the reflow rules file. + </body> +</html> diff --git a/layout/doc/hld-template.html b/layout/doc/hld-template.html new file mode 100644 index 000000000..1d06ac9a1 --- /dev/null +++ b/layout/doc/hld-template.html @@ -0,0 +1,109 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <title>Layout High Level design Template</title> + + <meta name="author" content="Marc Attinasi (attinasi@netscape.com)"> +</head> + <body> + +<h1><font color="#cc0000">Gecko Layout High Level Design Document Template</font></h1> + [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.]<br> + <br> + +<h1>[Component/Class/System Name] High Level Design</h1> + <br> + +<h2>Overview</h2> + [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.]<br> + <br> + +<h2>Data Model</h2> + [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.]<br> + +<h4>Class/Component Diagram</h4> + +<blockquote> + <div align="Left"><img src="ExampleClassDiagram.jpg" alt="Example Class Diagram" width="324" height="270" title="Example Class Diagram"> + <br> + </div> + </blockquote> + + <ul> + <li>[Class/<a href="Link%20To%20Component%20A%20Detailed%20Design"> +Component A</a> + ]: This class is used to...</li> + <li>[Class/<a href="Link%20To%20Component%20B%20Detailed%20Design"> +Component B</a> + ]: This class works with Class A to...<br> + </li> + + </ul> + <br> + + <h2>Use Case</h2> + [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.]<br> + + <h4>[Use Case 1: Component is Created]</h4> + The component is created by a client with...<br> + [Image could go here if it were interesting enough...]<br> + <br> + + <h4>[Use Case 2: Component is Destroyed]</h4> + When the client is finished with the instance they created (or were given + ownership of) the destroy it by calling...<br> + <br> + + <h4>[Use Case 3: Component is used to find all invalid links on the page]</h4> + 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.<br> + [Picture of the component instance with annotations showing data flow, +ownership, etc. goes here]<br> + + <h2>State Transitions</h2> + [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.]<br> + <br> + <br> + + </body> + </html> diff --git a/layout/doc/index.html b/layout/doc/index.html new file mode 100644 index 000000000..c5c4bc2c9 --- /dev/null +++ b/layout/doc/index.html @@ -0,0 +1,126 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <title>Layout Documentation Index Page</title> + + <meta http-equiv="content-type" + content="text/html; charset=ISO-8859-1"> + + <style> + /* colors for status of documents */ + *.ood { color: red !important; } + *.good { color: black !important; } + *.wip { color: blue !important; } + *.unassigned { color: green !important; } + /* inherit the colors into the links */ + p > a { color: inherit; } + </style> +</head> +<body> + +<h1>Layout Technical Documentation: Primary Index</h1> +<p class="wip">Document Status: Work In Progress (attinasi) +<p>The goal of this document is to provide extensive links to documentation +on the Gecko Layout components and classes. There are two sections containing +links to the documents, and there is overlap between these sections by +design. First, there is a '<a href="#TopicIndex">Topics</a>' section, +where documentation is listed by generic topics, more or less free-form +and ad-hoc. Second, there is a '<a href="#ClasscomponentIndex">Class and +Component</a>' section, where specific classes and components are listed, +mapping naturally to the source code. All documents should be indexed in +both sections, so pick the index that corresponds to what you are thinking +about. A <a href="#HowTo">Tech Notes section</a> is also included to help +contributors find information on small topics and issues, including simple +'How To' cookbooks. + +<p><blockquote> +<i>For information about the structure of layout documents, see the <a + href="http://lxr.mozilla.org/seamonkey/source/layout/doc/overview.html">Layout + Documentation Overview</a> and the Layout DocumentationTemplates + (<a + href="http://lxr.mozilla.org/seamonkey/source/layout/doc/hld-template.html">High + Level Design Template</a> / <a + href="http://lxr.mozilla.org/seamonkey/source/layout/doc/dd-template.html">Detailed + Design Template</a>). +</i> +</blockquote> + +<hr width="100%" size="2"> + +<div align="left" + style="border: 1px solid blue; margin: auto; width: 65%;"><big><b>Legend</b></big> +<ul> + <li class="good">Black: complete and believed to be up to date (class='good')</li> + <li class="wip">Blue: incomplete or work in progress (class='wip')</li> + <li class="ood">Red: out of date or innacurate (class='ood', bug should be filed and bug number / link noted)</li> + <li class="unassigned">Green: unassigned work</li> + </li> +</ul> +</div> + +<h2><a name="TopicIndex"></a>Topic Indices</h2> + +<div style="border: 1px solid black; margin: 1em; padding: 1em;"> + <p class="wip">What is Layout? The High Level Layout Overview (attinasi) + <p class="wip">Debugging Layout (bernd) + <p class="unassigned">How Reflow works + <p class="wip">Tables balancing (karnaze) + <p class="wip">Table Borders collapsing (karnaze) + <p class="wip">Block in Inline situations (kin) + <p class="good"><a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/HLD-SpaceManager.html">Managing Floats</a> + <p class="unassigned">Text Measurement and Text Breaking + <p class="unassigned">Image loading and display + <p class="unassigned">Margin Collapsing + <p class="unassigned">Scrolling Blocks + <p class="unassigned">Box and Block interactions + <p class="wip">Printing and Print Preview (rods) + <p class="unassigned">Plugins: the object frame and related layout classes +</div> + +<h2><a name="ClasscomponentIndex"></a>Class and Component Indices</h2> + +<div style="border: 1px solid black; margin: 1em; padding: 1em;"> + <p class="unassigned">Presentation Shell and Context: High Level / Detailed + <p class="unassigned">Frames and the Frame Manager: High Level / Detailed + <p class="good">Reflow: <a href="http://www.mozilla.org/newlayout/doc/reflow.html">High Level (waterson)</a> / <span class="unassigned">Detailed</span> + <p class="unassigned">Block and Line layout: High Level / Detailed + <p class="unassigned">TextFrame - Text Measurement and Line Breaking: High Level / Detailed + <p class="wip">PageSequenceFrame and PageFrame: High Level / Detailed (rods) + <p class="unassigned">Object Frame: High Level / Detailed + <p class="good">Space Manager: + <a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/HLD-SpaceManager.html">High Level</a> / + <a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/DD-SpaceManager.html">Detailed</a> + <p class="wip">Layout Debug Plugin: high Level / Detailed (dcone) +</div> + +<h2><a name="HowTo"></a>How To / Tech Notes</h2> + +<div style="border: 1px solid black; margin: 1em; padding: 1em;"> + <p class="good"><a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/frame_reflow_debug.html">How to Debug Reflow </a> + <p class="good"><a href="http://www.mozilla.org/newlayout/doc/block-and-line.html">Waterson's Block and Line Cheat Sheet</a> + <p class="good"><a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/adding-style-props.html">How to add Style Properties</a> + <p class="unassigned">Measuring Layout Performance + <p class="wip"><a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/regression_tests.html">Running the Regression Tests (bernd/dcone)</a> + <p class="good"><a href="http://lxr.mozilla.org/seamonkey/source/layout/doc/debugtable.html">Debugging Table Reflow</a> +</div> + +<hr width="100%" size="2"> + <p>Authors: + <ul> + <li>Marc Attinasi (attinasi@netscape.com)</li> + </ul> + <p>Document History: + <ul> + <li>05/06/2002 - Marc Attinasi: created</li> + <li>05/13/2002 - Marc Attinasi: added Block and Line Cheat Sheet, and link to existing Reflow document</li> + <li>05/21/2002 - Marc Attinasi: added Bernd's Table Reflow Debugging How-To (thanks Bernd!)</li> + <li>05/21/2002 - Bernd Mielke: added Frame Reflow Debugging How-To</li> + <li>06/16/2002 - Bernd Mielke: added layout regression test description</li> + </ul> + +</body> +</html> diff --git a/layout/doc/object_diagram_template.sda b/layout/doc/object_diagram_template.sda Binary files differnew file mode 100644 index 000000000..bae50cf07 --- /dev/null +++ b/layout/doc/object_diagram_template.sda diff --git a/layout/doc/obsolete/block.html b/layout/doc/obsolete/block.html new file mode 100644 index 000000000..255b84cd6 --- /dev/null +++ b/layout/doc/obsolete/block.html @@ -0,0 +1,209 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.61 [en] (X11; I; Linux 2.2.5-22 i686) [Netscape]"> +</head> +<body> + +<h1> +<u>Block Layout</u></h1> +This document attempts to describe how "block" layout works in the mozilla +layout engine. +<p><tt>nsBlockFrame</tt> implements layout behavior that conforms to the +CSS "display:block" and "display: list-item" layout. It has several responsibilities: +<ol> +<li> + Line layout. The block is responsible for flowing inline elements +into "lines" and applying all of the css behavior as one might expect, +including line-height, vertical-align, relative positioning, etc.</li> + +<li> +Float management. The block is responsible for the reflow and placement +of floating elements.</li> + +<li> +Child block management. Blocks can contain inline elements and block elements. +Hence, blocks are responsible for reflowing child blocks. The majority +of that logic has been split out into nsBlockReflowContext, but a fair +amount remains here.</li> + +<li> +Supporting table reflow. The block has to carefully compute the "max-element-size" +information needed by tables. Hence, any time changes are made here one +should always run the table regression tests because the odds are you broke +one of them!</li> +</ol> + +<h3> +<u>The Big Picture for Block Reflow</u></h3> +The block frame uses a list of nsLineBox's to keep track of each "line" +of frames it manages. There are two types of lines: +<blockquote>"inline" lines which contain only inline elements +<br>"block" lines which contain exactly one block element</blockquote> +Each line has a "dirty" bit which indicates that it needs reflow. Reflow +consists of identifying which lines need to be marked dirty and then reflowing +all lines. For lines which are "clean" the reflow logic will endeavor to +recover the state of reflow <i>as if the line had been reflowed</i>. This +saves time and allows for a faster incremental reflow. For lines which +are dirty, the line is reflowed appropriately. +<p>The only special thing about incremental reflow command handling is +that it marks lines dirty before proceeding, and keeps track of the child +frame that is the next frame on the reflow command path. +<p>Here is a list of the various classes involved in block layout: +<p><b>nsBlockFrame</b> +<blockquote>The primary culprit.</blockquote> +<b>nsBlockReflowState</b> +<blockquote>This helper class is used to augment the nsHTMLReflowState +with other information needed by the block reflow logic during reflow. +It is a temporary object that is designed to live on the processor stack +and contains "running" state used by the blocks reflow logic.</blockquote> +<b>nsBlockBandData</b> +<blockquote>Another helper class that wraps up management of a space manager +(nsISpaceManager, nsSpaceManager) and nsBandData. It also assists in management +of floating elements. While nsSpaceManager is policy free, nsBlockBandData +provides specific HTML and CSS policy.</blockquote> +<b>nsBlockReflowContext</b> +<blockquote>A helper class that encapsulates the logic needed to reflow +a child block frame. This is used by the block code reflow a child block +and to reflow floating elements (which are to be treated as blocks according +to the CSS2 spec).</blockquote> +<b>nsLineBox</b> +<blockquote>A data class used to store line information for the block frame +code. Each line has a list of children (though the frames are linked together +across lines to maintain the sibling list for nsIFrame::FirstChild) and +some other state used to assist in incremental reflow.</blockquote> +<b>nsLineLayout</b> +<blockquote>This class is the line layout engine. Its a passive entity +in the sense that its the responsibility of the block/inline code to use +the class (this is done so that the line layout engine doesn't have to +manage child frame lists so that both nsBlockFrame and nsInlineFrame can +use the class).</blockquote> +<b>nsTextRun</b> +<blockquote>This is a data class used to store text run information. Text +runs are <i>logically</i> contiguous runs of text (they may or may not +be structurally contiguous). The block frame stores a pointer to a list +of nsTextRun's and during line layout provides the list to the nsLineLayout +engine so that when text is reflowed the text layout code (nsTextFrame) +can find related text to properly handle word breaking.</blockquote> + +<h3> +<u>Frame construction methods</u></h3> +When the blocks child list is modified (AppendFrames, InsertFrames, RemoveFrame) +the block code updates its nsLineBox list. Since each nsLineBox is typed +(some are marked "inline" and some are marked "block"), the update logic +maintains the invariant of "one block frame per block line". +<p>When structural changes are made to the blocks children (append/insert/remove) +the block code updates the line's and then marks the affected lines "dirty" +(each nsLineBox has a dirty bit). After the structural changes are finished +then the block will generate an incremental reflow command of type "ReflowDirty". +<h3> +<u>Line Layout</u></h3> +Line layout consists of the placement of inline elements on a line until +there is no more room on the line. At that point the line is "broken" and +continued on the next line. This process continues until all inline elements +have been exhausted. The block code maintains a list of "nsLineBox"'s to +facilitate this. These are used instead of frames because they use less +memory and because it allows the block to directly control their behavior. +<p>The helper class nsLineLayout provides the majority of the line layout +behavior needed by the block. +<p>The block does keep "text-run" information around for the nsLineLayout +logic to use during reflow. Text runs keep track of logically adjacent +pieces of text within a block. This information is essential for properly +computing line and word breaking. Why? Well, because in html you can write +something like this: +<p> <p>I <b>W</b>as thinking one day</p> +<p>Notice that the word "Was" is composed of two pieces of text, and that +they do <i>not</i> have the same parent (content or frame). To properly +reflow this and not break the word prematurely after the "W", the text-run +information is used by the text frame code to "look ahead" and prevent +premature breaking. +<p>Lines also keep track of the type of "break" that occurred on the line. +This is used, for example, to support html's "<br clear=left>" behavior. +<h3> +<u>Float Management</u></h3> +Since child block elements are containing blocks for floats, the only +place where a block frame will see a float is as part of an inline line. +Consequently, the nsLineBox will only keep track of floats on inline +lines (saving storage for block lines). +<p>The nsLineLayout class and the block frame cooperate in the management +of floats. Since the frame construction code leaves a "placeholder" frame +in-flow where the float was found, when nsLineLayout reflows a placeholder +frame it knows to inform the block about it. That triggers the blocks "AddFloat" +logic which then determines where the float should be placed (on the +current line or below the current line). +<p>The block frame uses the space manager to manage the effects of floats, +namely the consumption of available space. For example, for a left aligned +floating element, the inline elements must be placed to the right of the +float. To simplify this process, the spacemanager is used to keep track +of available and busy space. Floats when placed mark space as busy and +the spacemanager will them compute the available space. Most of this logic +is handled by the nsBlockReflowState which uses a helper class, nsBlockBandData, +in concert with the space manager, to do the available space computations. +<h3> +<u>Child Block Placement</u></h3> +Child block reflow is done primarily by using the nsBlockReflowContext +code. However, a key detail worth mentioning here is how margins are handled. +When the nsHTMLReflowState was created, we placed into it the logic for +computing margins, border and padding (among other things). Unfortunately, +given the css rules for sibling and generational margin collapsing, the +nsHTMLReflowState is unable to properly compute top and bottom margins. +Hence, the block frame and the nsBlockReflowContext code perform that function. +At the time that the nsBlockReflowContext was designed and implemented +we thought that it could compute the top-margin itself and then proceed +to place the child block element. However, that turned out to be wrong +(oh well) because the correct available space isn't known until <i>after</i> +the top margin is computed. Hence, there is some unfortunate duplication +of reflow state calculations present in the block frame code. +<h3> +<u>Bullets</u></h3> +Another type of block frame is the "display: list-item". List-items use +nsBulletFrame's to manage bullet reflow. However, the block is responsible +for bullet placement. In most situations, the nsLineLayout class is used +to do the placement. However, if the first effective child of the block +is another block, then the block has to do the placement itself. +<h3> +<u>Blank lines</u></h3> +Because our content model contains as much of the original source documents +content as possible, we end up with a lot of white space that ends up being +compressed into nothingness. This white space ends up impacting this logic +in several ways. For example: +<p> <div> +<br> <p>abc</p> +<br> <p>def</p> +<br> </div> +<p>In the content model for the above html, there is white space between +the various block elements (some after the <div>, some after the first +</p>, again after the second </p>). +<p>For css margin collapsing to work properly, each of those instances +of white space has to behave as if they didn't exist. Consequently, there +is special logic in the inline line reflow code, and in the nsBlockReflowContext +code and in the GetTopBlockChild method, to basically ignore such lines. +<h3> +<u>First-letter style</u></h3> +The block contributes, in a small way, to first-letter style reflow. The +frame construction code is responsible for creating the list of child frames +for all frames, including the block. It manages the creation of letter-frames, +where appropriate, so that all the block has to do is reflow them almost +normally like other inline frames. +<p>There are two things different that the block does: +<p>It is responsible for calling nsLineLayout::SetFirstLetterStyleOK +<br>It is responsible for continuing to place frames on a line, even after +a frame has said "it can't fit". Normally during inline reflow, if a frame +comes back and says it can't fit, the block will end the line, push all +remaining frames to the next line and pick up the reflow from there after +making sure the frame that didn't fit is continued. For letter-frames, +this would result in the first-letter being on one line with the remaining +text on subsequent lines. Hence, the block code handles this special case. +<br> +<h3> +<u>First-line style</u></h3> +First-line is handled entirely by the frame construction code. +<br> +<br> +</body> +</html> diff --git a/layout/doc/obsolete/layout-internals.html b/layout/doc/obsolete/layout-internals.html new file mode 100644 index 000000000..916f943c3 --- /dev/null +++ b/layout/doc/obsolete/layout-internals.html @@ -0,0 +1,101 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="Author" content="Nisheeth Ranjan"> + <meta name="GENERATOR" content="Mozilla/4.5 [en]C-NSCP (WinNT; U) [Netscape]"> + <title>HTML Layout Internals</title> +</head> +<body> + +<h1> +HTML Layout Internals</h1> + +<h2> +Big picture</h2> +An HTML document comes in from netlib into the HTML parser. The parser +creates parser nodes and feeds them to the content sink. The content +sink constructs a content model that represents the hierarchical structure +of the document. As different sub-trees in the content model are +fully available, the stylesheet processor iterates over them and creates +the corresponding frame hierarchy. The frames recursively layout +and render themselves. +<p>The part that we are going to drill down into is the code in the block +and inline frame classes. Block and inline are the two primary display +types specified in CSS and are used in the layout of most of the HTML tags. +The table related tags have their own display types like "table-cell", +"table-row", etc. and their implementation is a separate topic in itself. +<h2> +Block and inline code</h2> +The main classes involved in the layout of HTML documents are nsBlockFrame +and nsInlineFrame, both of which inherit from nsContainerFrame (why?). +These classes are persistent across reflows and are organized in a hierarchy +to constitute the frame model of the Gecko system. The frame model +is derived by applying style and presentation semantics to the content +model. Each frame in the frame model has a one to one correspondence +with a rectangular region on the presentation context (screen, printer, +etc.) and contains the formatting information needed to render that rectangle. +The block and inline frame classes implement the nsIFrame and nsIHTMLReflow +interfaces. The nsIFrame interface contains methods for managing +child frames and linkage with sibling frames, accessing the style context +associated with the frame, painting the frame, and handling events that +are passed in from the widget hierarchy. The nsIHTMLReflow interface +inherits from the nsIReflow interface and adds methods related to word +breaking and whitespace querying. The nsIReflow interface defines +the Reflow() method that initiates the reflow process along with the +DidReflow() method that get calledafter the reflow process. +nsReflowState and nsReflowMetrics are parameters to +the templatized nsIReflow interface: the former is used to hold state during +reflow of a frame and the latter is used to return the frame's desired +size and alignment to the parent frame during the reflow process. +<p>nsBlockReflowContext and nsBlockReflowState both hold state information +during the reflow process. nsBlockReflowContext encapsulates the +state and algorithm for reflowing child block frames. nsBlockReflowState +contains state and methods used by a block frame to reflow itself. +Both these classes are instantiated once per block frame. +<p>The nsLineLayout class is the engine used by the block and inline frame +classes to layout themselves on a line. Frames get passed in to the +nsLineLayout class via the BeginSpan() and EndSpan() methods. Each +span represents a run of frames with the same style data (???). Other +methods exist on the nsLineLayout class to position and size the frames +on the current line. +<p>nsBlockBandData is the class used to manage the processing of the space-manager +(nsSpaceManager) band data. It provides HTML/CSS specific semantics +on top of the general space management facilities provided by nsSpaceManager. +<p>nsSpaceManager is a class that is told about regions that reserve space +and exposes methods to query for available space in a given band. +<p>The nsLineBox class represents a horizontal line of frames and is singly +linked to the next line box in the document. It is basically a container +of a frame list that share the property of being on the same line in the +formatted output of the document. +<p>The nsTextRun class holds on to a list of frames containing pieces of +text that form a logical text run. This is needed because a single +text run can occur on leaves at many levels of the document's content tree. +This class gives the text layout process an efficient way to get access +to text runs and, so, determine where word breaks should occur. +<h2> +Questions</h2> +What are anonymous blocks (nsBlockFrame.h)? +<br>What is the difference between a span and a band (nsLineLayout)? +<br>Why do nsBlockFrame and nsInlineFrame both inherit from nsContainerFrame? +<h2> +To Do</h2> + +<ol> +<li> +Provide more information about methods and state of each of the classes +above.</li> + +<li> +Give a description of how the above classes interact with each other as +a simple HTML document is laid out. Then, add in different features +to the HTML that exercise different areas of the code, like floats, anonymous +blocks, etc.</li> +</ol> + +</body> +</html> diff --git a/layout/doc/obsolete/layout.css b/layout/doc/obsolete/layout.css new file mode 100644 index 000000000..854ab6c86 --- /dev/null +++ b/layout/doc/obsolete/layout.css @@ -0,0 +1,124 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@namespace xlink url("http://www.w3.org/1999/xlink"); + +Documentation { + display: block; + font-family: Verdana, sans-serif; + font-size: 11pt; + margin: 8px; +} +Author { + display: block; + font-size: 90%; +} +Author:before { + content: "Author: "; + font-weight: bold; +} +UpdateDate { + display: block; + font-size: 90%; +} +UpdateDate:before { + content: "Updated: "; + font-weight: bold; +} +Title { + display: block; + font-size: 250%; + font-weight: bold; + letter-spacing: -1.25pt; + margin-top: 0; + margin-bottom: .5em; +} +SectionHeading { + display: block; + font-size: 125%; + font-weight: bold; + margin-top: 2em; + margin-bottom: .5em; +} +Body { + display: block; + margin-top: 1em; + margin-bottom: .5em; +} +SectionHeading + Body { /* body after section heading */ + margin-top: 0; +} +Components { + display: block; + margin-top: 1em; + margin-left: .5in; + border: dotted 1px black; +} +:link:hover { + background-color: blue; + color: white; + cursor: pointer; +} + +/* workaround for above rule not working */ +*[xlink|type] { + cursor: pointer; +} + +/* workaround for above rule not working */ +*[xlink|show="replace"] { + cursor: pointer; +} + +Term { + display: block; + font-weight: bold; + background-color: lightyellow; + padding-left: .5em; +} +Definition { + display: block; + margin-left: 40px; +} +Interfaces, Characteristics, Items, Categories { + display: block; + margin-left: 40px; + list-style-position: outside; + list-style-type: disc; +} +Purposes { + display: block; + margin-left: 40px; + list-style-position: outside; + list-style-type: decimal; + counter-reset: -html-counter 0; +} +Interface, Characteristic, Purpose, Item, Category { + display: list-item; +} +RunIn { + display: inline; + font-weight: bold; +} +Note { + width: 2in; + height: auto; + float: right; + font-size: 90%; + margin-left: 1em; + margin-right: .5em; + border-top: solid 2px black; + border-bottom: solid 1px black; + padding: .5em 0; +} +Note:before { + content: "Note"; + font-weight: bold; + display: inline; + background-color: black; + color: white; + margin-right: .25em; + padding: .5em .25em 0 .25em; +} + diff --git a/layout/doc/obsolete/layout.xml b/layout/doc/obsolete/layout.xml new file mode 100644 index 000000000..9e4774aef --- /dev/null +++ b/layout/doc/obsolete/layout.xml @@ -0,0 +1,279 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="layout.css" type="text/css"?> +<!DOCTYPE Documentation> + +<Documentation xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:xlink="http://www.w3.org/1999/xlink"> + +<Title>Gecko Layout Engine</Title> +<Author xlink:type="simple" xlink:show="new" xlink:href="mailto:troy@netscape.com">Troy Chevalier</Author> +<UpdateDate>8 August 1999</UpdateDate> + +<SectionHeading>Overview</SectionHeading> +<Body>Gecko is Mozilla's new layout engine. It is based on the HTML4, CSS1, XML 1.0, +and DOM Internet standards, and it is built using a modular XPCOM-based +architecture.</Body> + +<Body>When we talk about layout, we're referring to the formatting process that applies +presentation styles to a source document. The formatting process is controlled +by the style specification.</Body> + +<SectionHeading>Components</SectionHeading> +<Body>Here are a list of components and terms that will be referenced by this document.</Body> + +<Components> +<Term>Parser</Term> +<Definition>Either the <A xlink:type="simple" xlink:show="replace" xlink:href="http://www.mozilla.org/newlayout/doc/parser.html">HTML</A> +or XML parser. Processes the document and makes calls to the content sink.</Definition> + +<Term>Content sink</Term> +<Definition>Called by the parser. Responsible for building the content model.</Definition> + +<Term><A xlink:type="simple" xlink:show="replace" xlink:href="http://www.mozilla.org/newlayout/doc/contentmodel.html">Content model</A></Term> +<Definition>Consists of document object and a tree of content objects. Changes to the +content model result in modifications of the frame model.</Definition> + +<Term>Frame model</Term> +<Definition><A xlink:type="simple" xlink:show="replace" xlink:href="#Frames">Frames</A> are formatting +objects. Each frame defines a particular set of formatting characteristics.</Definition> + +<Term><A xlink:type="simple" xlink:show="replace" xlink:href="#Reflow">Reflow</A></Term> +<Definition>The formatting process. Reflow of the frame model defines the visual appearance +of the formatted document.</Definition> + +<Term><A xlink:type="simple" xlink:show="replace" xlink:href="#FrameConstruction">Frame construction</A></Term> +<Definition>Initial creation and updating of the frame model in response to changes to the +content model and changes to the style data.</Definition> + +<Term><A xlink:type="simple" xlink:show="replace" xlink:href="http://www.mozilla.org/newlayout/doc/style.html">Style system</A></Term> +<Definition>Provide the mapping and management of style data onto document content in a given +presentation. Major components are style set, style sheets, style sheet and +rules, style context, and style sheet loader.</Definition> + +<Term>Presentation shell</Term> +<Definition>Controlling point for managing the presentation of a document.</Definition> + +<Term><A xlink:type="simple" xlink:show="replace" xlink:href="http://www.mozilla.org/newlayout/doc/viewsystem.html">View system</A></Term> +<Definition>Consists of a view manager and view objects arranged in a tree hierarchy. +Views support overlapped positioning, z-order sorting, and opacity levels.</Definition> +</Components> + +<SectionHeading>Document Loading</SectionHeading> +<Body>The basic flow of control is as follows: as the parser encounters tokens it notifies +the content sink that a new node (or child node) is encountered. The content sink +creates the appropriate type content object and inserts it into the content model.</Body> + +<Body>Whenever the content model changes the document's observers are notified. The presentation +shell is one of the document observers. The presentation shell forwards the document +change notification to the style set object</Body> + +<Body>The style set passes the notification to the frame construction code, the +frame construction code creates new frames and inserts them into the frame model. The +document is reflowed, and the formatted changes are displayed. +</Body> + +<Body> +The actual interfaces involved are: +<Interfaces> +<Interface>nsIDocument</Interface> +<Interface>nsIDocumentObserver</Interface> +<Interface>nsIPresShell</Interface> +<Interface>nsIStyleSet</Interface> +<Interface>nsIStyleFrameConstruction</Interface> +<Interface>nsIFrame</Interface> +</Interfaces> +</Body> + +<Body>All of the interface files are located in the mozilla/layout/base/public +directory.</Body> + +<SectionHeading>Object Lifetimes</SectionHeading> +<Body>Gecko supports multiple views of the same document. This means you can print the +same document that you're viewing on the screen, and there's only one content +model. Because there's just a single content model, each of the content objects +is referenced counted. The document holds a reference to the root content object, +and each content node holds a reference to its child content nodes.</Body> + +<Body>Each view of the document has a separate presentation shell, style manager, +style set, and frame hierarchy. The presentation shell is the controlling point for +the presentation of a document, and it holds a reference to the document object.</Body> + +<Body>Frames and views are not referenced counted. The lifetime of the frame hierarchy +is bounded by the lifetime of the presentation shell which owns the frames. The +lifetime of the view hierarchy is bounded by the lifetime of the view manager +that owns the views.</Body> + +<SectionHeading><html:a name="Frames">Frames</html:a></SectionHeading> +<Body>Each frame defines a particular set of formatting characteristics. Frames have +the opportunity to: +<Characteristics> +<Characteristic>reflow (format) their child frames</Characteristic> +<Characteristic>render their appearance</Characteristic> +<Characteristic>handle mouse and keyboard events</Characteristic> +<Characteristic>display a cursor</Characteristic> +<Characteristic>have an associated view object</Characteristic> +</Characteristics> +</Body> + +<Body>Frames can have multiple child lists, the default unnamed child list +(referred to as the principal child list) and additional named child lists. +There is an ordering of frames within a child list, but no ordering +between frames in different child lists of the same parent frame.</Body> + +<Body>The principal child list contains the flowed children, and the additional +child lists are for out-of-flow frames like floated elements and absolutely +positioned elements.</Body> + +<Body>Child frames are linked together in a singly linked list. Each frame +defines its own local coordinate space. Frame bounding rects are in twips, +and the origin is relative to the upper-left corner of its parent frame. +The bounding rect includes the content area, borders, and padding.</Body> + +<SectionHeading><html:a name="FrameConstruction">Frame Construction</html:a></SectionHeading> +<Body>The frame construction process begins with a notification that content +has been added or removed or that style has changed.</Body> + +<Body>The first step is to resolve style information for the content element. +This process creates a style context that is stored in the frame (see +nsIStyleContext).</Body> + +<Body>Once style is resolved construction rules are used to decide the type of +frame to create. First we look at the element's tag and special case some +things like IMG elements. If we don't create a frame that way, then we use +the 'display' property to dictate what type of frame to create. Typically +it's a block or inline frame.</Body> + +<Body>For a 'display' value of 'none' no frame is created. For elements that are +out of the flow (for example, a floated element or an absolutely positioned +element), a placeholder frame is also created. The placeholder frame is inserted +into the flow exactly where the out-of-flow frame would have been inserted. +The out-of-flow frame is then inserted as a child of its containing block in +one of the additional child lists. Floated frames are inserted into the +"Float-list" and absolutely positioned frames are inserted into the +"Absolute-list".</Body> + +<SectionHeading>Frame Manager</SectionHeading> +<Body>The frame manager is owned by the presentation shell and used by both the +presentation shell and the frame construction code. It serves two main +purposes: +<Purposes> +<Purpose>provides a service for mapping from content object to frame and from out-of-flow +frame to placeholder frame</Purpose> +<Purpose>coordinates structural modifications to the frame model</Purpose> +</Purposes> +</Body> + +<Body>In many places in the frame code we need to find the frame associated with +a particular content object. In order to quickly implement this operation we +maintain a mapping from content objects to frames. The frame construction adds +and removes entries from the map as frames are created and destroyed.</Body> + +<Body>When creating new frames and removing existing frames, the frame construction +code doesn't directly modify the frame hierarchy. Instead if informs the frame +manager and has it coordinate the request. If the frame model lock is available, +the change is processed immediately; otherwise, the request is queued and +processed later.</Body> + +<Body>The frame manager also coordinates processing of replaced elements that can't +be rendered (for example, an IMG or OBJECT element), and it allows client to +register to be notified when a particular frame is being destroyed. This is +needed because frames are not reference counted. It's used by the event manager +and other clients to ensure that any outstanding references to the frame are +cleaned up.</Body> + +<SectionHeading><html:a name="Reflow">Reflow</html:a> Process</SectionHeading> +<Note>The fact that are two reflow interfaces reflects an early +goal of having core layout and HTML specific layout. The core reflow process would +be the same for all frames, and each class of formatting objects (for +example, CSS and DSSSL) would have their own reflow additions.</Note> + +<Body>The reflow process is a top-down protocol where a frame is given some +available space and asked to reflow its child frames and return a desired +size.</Body> + +<Body>The reflow process is not part of the nsIFrame interface. The generic reflow +interface is defined in the nsIFrameReflow interface, and the HTML/CSS specific +reflow interface is defined in the nsIHTMLReflow interface.</Body> + +<Body>An important part of the reflow process is the calculation of the computed +values for the CSS properties. This includes things like 'width', 'height', +and 'margin', and involves calculation of the containing block width and height +and percentage based values and properties whose value is inherited.</Body> + +<Body>This process is encapsulated in the HTML specific reflow state struct +(struct nsHTMLReflowState) that is passed in as part of reflow. The reflow +states are linked together with the reflow state for a child frame pointing +to its parent frame's reflow state. This allows us to walk up the reflow state +structures and calculate containing block width and height and percentage +based values.</Body> + +<Body>In addition to the computed values for the CSS box model properties, the +following items are also included: +<Items> +<Item>reflow reason that indicates why the frame is being reflowed</Item> +<Item>a rendering context that can be used to measure text</Item> +<Item>reflow command (only used for incremental reflow)</Item> +<Item>space manager</Item> +</Items> +</Body> + +<Body>The most common reflow reasons are 'eReflowReason_Resize' (the viewport +has changed size) and 'eReflowReason_Incremental' (processing of an incremental +reflow command).</Body> + +<Body>Reflow commands (see nsHTMLReflowCommand in mozilla/layout/html/base/src) are used +to kick off an incremental reflow. They're generated either by the style system +(in response to a style change) or by a frame itself (for example, if a frame has +dirty child frames that need to be reflowed it will generate a reflow command).</Body> + +<Body>Reflow commands are queued by the presentation shell and then dispatched. Reflow +commands have a target frame, which is the frame for which the reflow command +is destined. In the example above the target frame is the frame with dirty child +frames that need to be reflowed. Reflow command processing follows a path from +the root frame down to the target frame.</Body> + +<Body>The space manager (see nsISpaceManager in mozilla/layout/base/public) is used +when flowing text around floated elements. It has an API for managing bands of +unavailable space (space that is reserved for a floated element). Internally it +organizes the band data similar to how a region data structure works.</Body> + +<SectionHeading>Frame Classes</SectionHeading> +<Body>There are four main categories of frame classes, all of which are located +in mozilla/layout/html/src: + +<Categories> +<Category>core frame classes</Category> +<Category>table frame classes</Category> +<Category>form frame classes</Category> +<Category>frameset frame classes</Category> +</Categories> +</Body> + +<Body><RunIn>The core frame classes</RunIn> implement the CSS viewport abstraction, scrolling, +block and inline display of flowed elements, floats, and absolute positioning.</Body> + +<Body>For more information on block layout, click +<A xlink:type="simple" xlink:show="replace" xlink:href="block.html">here</A>. For more information about +line layout, click <A xlink:type="simple" xlink:show="replace" xlink:href="line-layout.html">here</A>.</Body> + +<Body><RunIn>The table frame classes</RunIn> correspond to the HTML4 table spec, and in addition +to the table frame there are row group frames, row frames, column group frames, +column frames, and cell frames. There is an "outer" table frame as well that's +really an anonymous frame that contains the caption frame and the table frame +itself.</Body> + +<Body>Table layout is determined in a 3-step process. In the first step, the table +is flowed into an infinitely wide and tall space. This gives us the minimum and +desired sizes for every cell in the table. In the second step, the table constraints +are factored in and widths are assigned to every cell. In the third step, heights are +assigned to every cell based on the computed width constraint. The results of the first +step are cached and only need to be recomputed when content or constraints are changed.</Body> + +<SectionHeading>Event Manager</SectionHeading> +<Body>To be written</Body> + +</Documentation> diff --git a/layout/doc/obsolete/line-layout.html b/layout/doc/obsolete/line-layout.html new file mode 100644 index 000000000..3a1bd17fa --- /dev/null +++ b/layout/doc/obsolete/line-layout.html @@ -0,0 +1,118 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name="GENERATOR" content="Mozilla/4.61 [en] (X11; I; Linux 2.2.5-22 i686) [Netscape]"> +</head> +<body> + +<h1> +<u>Line Layout</u></h1> +Line layout is the process of placing inline frames horizontally (left +to right or right to left depending on the CSS direction property value). +An attempt is made to describe how it works. +<p>nsLineLayout is the class that provides support for line layout. The +container frames nsBlockFrame and nsInlineFrame use nsLineLayout to perform +line layout and span layout. Span layout is a subset of line layout used +for inline container classes - for example, the HTML "B" element). Because +of spans, nsLineLayout handles the nested nature of line layout. +<p>Line layout as a process contains the following steps: +<ol> +<li> +Initialize the nsLineLayout object (done in nsBlockFrame). This prepares +the line layout engine for reflow by initializing its internal data structures.</li> + +<br> +<li> +Reflowing of inline frames. The block code uses nsLineLayout's <b>ReflowFrame</b> +method to reflow each inline frame in a line. This continues until the +line runs out of room or the block runs out of frames. The block may be +reflowing a span (an instance of nsInlineFrame) which will recursively +use nsLineLayout for reflow and placement of the frames in the span.</li> + +<p><br>Note that the container frames (nsBlockFrame/nsInlineFrame) call +nsLineLayout's ReflowFrame method instead of having the line layout code +process a list of children. This is done so that the container frames can +handle the issues of "pushing" and "pulling" of frames across continuations. +Because block and inline maintain different data structures for their child +lists, and because we don't want to mandate a common base class, the line +layout code doesn't control the "outer loop" of frame reflow. +<br> +<li> +Finish line layout by vertically aligning the frames, horizontally aligning +the frames and relatively positioning the frames on the line.</li> +</ol> +nsLineLayout is also used by nsBlockFrame to construct text-run information; +this process is independent of normal line layout is pretty much a hack. +<p>When frames are reflowed they return a reflow status. During line layout, +there are several additions to the basic reflow status used by most frames: +<ul> +<li> +NS_FRAME_COMPLETE - this is a normal reflow status and indicates that the +frame is complete and doesn't need to be continued.</li> + +<li> +NS_FRAME_NOT_COMPLETE - this is another normal reflow status and indicates +that the frame is not complete and will need a continuation frame created +for it (if it doesn't already have one).</li> + +<li> +NS_INLINE_BREAK - some kind of break has been requested. Breaks types include +simple line breaks (like the BR tag in html sometime does) and more complex +breaks like page breaks, float breaks, etc. Currently, we only support +line breaks, and float clearing breaks. Breaks can occur before the frame +(NS_INLINE_IS_BREAK_BEFORE) or after the frame (NS_INLINE_IS_BREAK_AFTER)</li> +</ul> +The handling of the reflow status is done by the container frame using +nsLineLayout. +<h3> +<u>Line Breaking</u></h3> +Another aspect of nsLineLayout is that it supports line breaking. At the +highest level, line breaking consists of identifying where it is appropriate +to break a line that doesn't fit in the available horizontal space. At +a lower level, some frames are breakable (e.g. text) and some frames are +not (e.g. images). +<p>In order to break text properly, some out-of-band information is needed +by the text frame code (nsTextFrame). In particular, because a "word" (a +non-breakable unit of text) may span several frames (for example: <b>"<B>H</B>ello +there"</b> is breakable after the <b>"o"</b> in "<b>ello</b>" but not after +the <b>"H"</b>), text-run information is used to allow the text frame to +find adjacent text and look at them to determine where the next breakable +point is. nsLineLayout supports this by keeping track of the text-runs +as well as both storing and interrogating "word" state. +<h3> +<u>White-space</u></h3> +To support the white-space property, the line layout logic keeps track +of the presence of white-space in the line as it told to reflow each inline +frame. This allows for the compression of leading whitespace and the compression +of adjacent whitespace that is in separate inline elements. +<p>As a post-processing step, the TrimTrailingWhiteSpace logic is used +to remove those pesky pieces of white-space that end up being placed at +the end of a line, that shouldn't really be seen. +<p>To support pre-formatted text that contains tab characters, the line +layout class keeps track of the current column on behalf of the text frame +code. +<h3> +<u>Vertical Alignment</u></h3> +Vertical alignment is peformed as a two and a half pass process. The first +pass is done during nsInlineFrame reflow: the child frames of the nsInlineFrame +are vertically aligned as best as can be done at the time. There are certain +values for the vertical-align property that require the alignment be done +after the lines entire height is known; those frames are placed during +the last half pass. +<p>The second pass is done by the block frame when all of the frames for +a line are known. This is where the final height of the line +<br>(not the line-height property) is known and where the final half pass +can be done to place all of the top and bottom aligned elements. +<br> +<h3> +<u>Horizontal Alignment</u></h3> +After all frames on a line have been placed vertically, the block code +will use nsLineLayout to perform horizontal alignment within the extra +space. +</body> +</html> diff --git a/layout/doc/obsolete/nav4-html.html b/layout/doc/obsolete/nav4-html.html new file mode 100644 index 000000000..92aaebabd --- /dev/null +++ b/layout/doc/obsolete/nav4-html.html @@ -0,0 +1,902 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<HTML> +<HEAD> + <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> + <META NAME="Author" CONTENT="Kipp E.B. HIckman"> + <META NAME="GENERATOR" CONTENT="Mozilla/4.03 [en] (WinNT; I) [Netscape]"> + <TITLE>HTML</TITLE> + <BASE HREF="file:///s|/ns/xena/htmlpars/testhtml/"> +</HEAD> +<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#FF0000" VLINK="#800080" ALINK="#0000FF"> + +<H2> +HTML</H2> +This documents describes the complete handling of HTML in magellan. The +document covers the parsing process - how HTML is lexically analysized +and then interprted. After the parsing process is discussed we give a detailed +analysis of each HTML tag and the attributes that are supported, the values +for the attributes and how the tag is treated by magellan. +<H2> +Parsing</H2> +HTML is tokenized by an HTML scanner. The scanner is fed unicode data to +parse. Stream converters are used to translate from various encodings to +unicode. The scanner separates the input stream into tokens which consist +of: +<UL> +<LI> +text</LI> + +<LI> +tags</LI> + +<LI> +entities</LI> + +<LI> +script-entities</LI> + +<LI> +comments</LI> + +<LI> +conditional comments</LI> +</UL> +The HTML parsing engine uses the HTML scanner for lexical anlaysis. The +parsing engine operates by attacking the input stream in a set of well +defined steps: +<UL> +<LI> +The parser processes the head portion of the document first, without emitting +any output. This is done to discover a few special features of html:</LI> + +<UL> +<LI> +The parser processes META tags looking for META TARGET</LI> + +<LI> +The parser processes META tags looking for META tags which affect the character +set. Nav4 handles the very first character set defining meta tag (all others +are ignored) by reloading the document with the proper character conversion +module inserted into the stream pipeline.</LI> +</UL> + +<LI> +After the head portion is processed the parser then proceeds to process +the body of the document</LI> +</UL> + +<H3> +Tag Processing</H3> +Tags are processed by the parser by locating a <B>"tag handler"</B> for +the tag. The HTML parser serves as the tag handler for all of the builtin +tags documented below. Tag attribute handling is done during translation +of tags into content. This mapping translates the tag attributes into content +data and into style data. The translation to style data is documented below +by indicating the mapping from tag attributes to their CSS1 (plus extensions) +equivalents. +<H3> +Special Hacks</H3> +The following list describes hacks added to the magellan parsing engine +to deal with navigator compatibility. These are just the parser hacks, +not the layout or presentation hacks. Most hacks are intriduced for HTML +syntax error recovering. HTML doesn't specify much how to handle those +error conditions. Netscape has made big effort to render pages with non-prefect +HTML. For many reasons, new browsers need to keep compatible in thsi area. +<UL> +<LI> +Entities can be used as escape in quoted string. For value string in name-value +pair, see <A HREF="../testhtml/quote001.html">compatibility test +quote001.html</A>. Test line 70 shows that an entity quote at the begining +means the value is NOT quoted. Test line 90 shows that if the value is +started with a quote, then an entity quote does NOT terminate the value +string.</LI> + +<LI> +Wrapping tags are special tags such as title, textarea, server, script, +style, and etc.. The comment in ns\lib\libparse\pa_parse.c says:</LI> + +<BR> /* +<BR> * These tags are special in that, after opening one of +them, all other tags are ignored until the matching +<BR> * closing tag. +<BR> */ +<BR>During the searching of an end tag, comments and quoted strings are +observed. see <A HREF="../testhtml/title01.html">compatibility test title01.html</A>. +6.0 handles comments now, need to add quoted string. +<LI> +If a <tr> or <td> tag is seen outside any <table> scope, it is +ignored. see <A HREF="../testhtml/table110.htm">compatibility test table110.htm</A>.</LI> + +<LI> +<FONT COLOR="#000000">In case of table in table but not in cell, table +tags before the last table tag are ignored. We found this problem in some +Netscape public pages, see bug #85118. For example, <table> <table +border> .....,or <table> <tr> <table border>..., the table +will be displayed with border. </FONT> <A HREF="../testhtml/table201.html">compatibility +test table201.html</A>. There table and tr tags are buffered for this recovery. +When a TD or CAPTION tag is open, the buffer is flushed out, because we +cannot buffer contents of TD or CAPTION for performance and memory constrains. +They are subdoc's and can be very big. If we see a <table> outside cell +after previous table is flushed out, the new <table> tag is ignored. +Nav4.0 can discard previous table in such case. <A HREF="../testhtml/tableall.html">tableall.html +</A>is the index for table test cases.</LI> + +<LI> +Caption is not a commonly used feature. In Nav4.0, captions can be anywhere. +For Captions outside cells, the first one takes effect. For captions inside +cells, the last one takes effect, and they also close TD and TR. In 6.0, +caption is limited to the standard position: after <table>. Captions +in other places are ignored, their contents are treated as text. See test +case table05a.html to table05o.html.</LI> + +<LI> +<FONT COLOR="#000000">For <table> <tr> <tr>, the first <tr> +takes effect.</FONT></LI> + +<LI> +The nav4 parser notices when it hits EOF and it's in the middle of scanning +in a comment. When this happens, the parser goes back and looks for an +improperly closed comment (e.g. a simple > instead of a -->). If it finds +one, it reparses the input after closing out the comment.</LI> + +<LI> +<FONT COLOR="#FF0000">XXX Brendan also pointed out that there is something +similar done for tags, but I don't recall what it is right now.</FONT></LI> + +<LI> +<FONT COLOR="#000000">When Nav4.0 sees the '<' sign, it searchs for +'>', observing quoted values. If it cannot find one till EOF, the '<' +sign is treated as text. In Xena 6.0, a limit is set for how far the '>' +is searched. the default limit is 4096 char, and there is a API HTMLScanner.setMaxTagLength() +to changed it. setting -1 means no limit, which is same as Nav4.0.</FONT></LI> +</UL> +<FONT COLOR="#FF0000">TODO:</FONT> +<UL><FONT COLOR="#FF0000">Document the mapping of tag attributes into CSS1 +style, including any new "css1" attributes</FONT> +<BR> </UL> +<B>List of 6.0 features incompatible with 4.0</B> +<UL> +<LI> +Navigator 4.0 value string is truncated at 82 characters. XENA60 limit +is MAX_STRING_LENGTH = 2000.</LI> + +<BR> </UL> + +<HR WIDTH="100%"> +<H2> +Tags (Categorically sorted)</H2> +All line breaks are conditional. If the x coordinate is at the current +left margin then a soft line break does nothing. Hard line breaks are ignored +if the last tag did a hard line break. + +<P><B>divalign</B> = left | right | center | justify +<BR><B>alignparam</B> = abscenter | left | right | texttop | absbottom +| baseline | center | bottom | top | middle | absmiddle +<BR><B>colorspec</B> = named-color | #xyz | #xxyyzz | #xxxyyyzzz | #xxxxyyyyzzzz +<BR><B>clip</B> = [auto | value-or-pct-xy](1..4) (pct of width for even +coordinates; pct of height for odd coordinates) +<BR><B>value-or-pct = </B>an integer with an optional %; ifthe percent +is present any following characters are ignored! +<BR><B>coord-list</B> = <FONT COLOR="#DD0000">XXX</FONT> +<BR><FONT COLOR="#000000"><B>whitespace-strip</B> = remove leading and +trailing and any embedded whitespace that is not an actual space (e.g. +newlines)</FONT> +<H1> +Head objects:</H1> +<B>TITLE</B> +<UL>The TITLE tag is a container tag whose contents are not HTML. The contents +are pure text and are processed by the parser until the closing tag is +found. There are no attributes on the tag and any whitespace present in +the tag is compressed down with leading and trailing whitespace eliminated. +The first TITLE tag found by the parser is used as the document's title +(subsequent tags are ignored).</UL> +<B>BASE</B> +<UL>Sets the base element in the head portion of the document. Defines +the base URL for <FONT COLOR="#DD0000">all</FONT>? links in the document. +<BR>Attributes: +<UL><B>HREF</B>=url [This is an absolute URL] +<BR><B>TARGET</B>=string [must start with XP_ALPHA|XP_DIGIT|underscore +otherwise nav4 ignores it]</UL> +</UL> +<B>META</B> +<UL>Can define several header fields (content-encoding, author, etc.) +<BR>Attributes: +<UL><B>REL</B>=SMALL_BOOKMARK_ICON|LARGE_BOOKMARK_ICON +<UL><B>SRC</B>=string</UL> +<B>HTTP-EQUIV</B>="header: value" +<UL><B>CONTENT</B>=string</UL> +</UL> +HTTP-EQUIV values (from libnet/mkutils.c NET_ParseMimeHeader): +<UL>ACCEPT-RANGES +<BR>CONTENT-DISPOSITION +<BR>CONTENT-ENCODING +<BR>CONTENT-RANGE +<BR>CONTENT-TYPE [ defines character set only ] +<BR>CONNECTION +<BR>DATE +<BR>EXPIRES +<BR>EXT-CACHE +<BR>LOCATION +<BR>LAST-MODIFIED +<BR>LINK +<BR>PROXY-AUTHENTICATE +<BR>PROXY-CONNECTION +<BR>PRAGMA +<BR>RANGE +<BR>REFRESH +<BR>SET-COOKIE +<BR>SERVER +<BR>WWW-AUTHENTICATE +<BR>WWW-PROTECTION-TEMPLATE +<BR>WINDOW-TARGET</UL> +Style sheets and HTML w3c spec adds this: +<UL>CONTENT-STYLE-TYPE [ last one wins; overrides header from server if +any ]</UL> +</UL> +<B>LINK</B> +<UL>List related resources. Used by extensions mechanism to find tag handlers. +<FONT COLOR="#0000FF">/LINK == LINK!</FONT> +<BR>Attributes: +<UL><B>REL</B>=FONTDEF +<UL><B>SRC</B>=url</UL> +<B>REL</B>=STYLESHEET [ If MEDIA param is defined it must ==nc screen ] +<UL><B>LANGUAGE</B>=LiveScript|Mocha|JavaScript1.1|JavaScript1.2 +<BR><B>TYPE</B>="text/javascript" | "text/css" +<BR><B>HREF</B>=url +<BR><B>ARCHIVE</B>=url +<BR><B>CODEBASE</B>=url +<BR><B>ID</B>=string +<BR><B>SRC</B>=url</UL> +</UL> +Note: HREF takes precedence over SRC in nav4.</UL> +<B>HEAD</B> +<UL>/HEAD clears the "in_head" flag (but leaves the "in_body" flag alone. +<BR>Text in head clears in_head, and set in_body true, just as if the author +forgot the /HEAD tag. +<BR>Attributes: none</UL> +<B>HTML</B> +<UL>Ignored. +<BR>Attributes: none</UL> +<B>STYLE</B> +<UL>Allowed anywhere in the document. Note that entities are not parsed +in the style tag's content. +<BR>Attributes: +<UL><B>LANGUAGE</B>=LiveScript|Mocha|JavaScript1.1|JavaScript1.2 +<BR><B>TYPE</B>="text/javascript" | "text/css" +<BR><B>HREF</B>=url +<BR><B>ARCHIVE</B>=url +<BR><B>CODEBASE</B>=url +<BR><B>ID</B>=string +<BR><B>SRC</B>=url</UL> +</UL> +<B>FRAMESET</B> +<UL>Frameset with rows=1 and cols=1 is ignored. +<BR>Attributes: +<UL><B>FRAMEBORDER</B>= no | 0 (zero) [default is no_edges=false] +<BR><B>BORDER</B>= int [clamped: >= 0 && <= 100] +<BR><B>BORDERCOLOR</B>= color +<BR><B>ROWS</B>= pct-list +<BR><B>COLS</B>= pct-list</UL> +</UL> +<B>FRAME</B> +<UL>Border width of zero disables edges. +<BR>Attributes: +<UL><B>FRAMEBORDER</B>= no | 0 (zero) [default is framesets value] +<BR><B>BORDER</B>= int [clamped; >= 0 && <= 100] +<BR><B>BORDERCOLOR</B>= color +<BR><B>NORESIZE</B>= true [default is false] +<BR><B>SCROLLING</B>= yes | scroll | on | no | noscroll | off +<BR><B>SRC</B>= url [clamped: prevent recursion by eliminating any anscestor +references] +<BR><B>NAME</B>= string +<BR><B>MARGINWIDTH</B>= int (clamped: >= 1) +<BR><B>MARGINHEIGHT</B>= int (clamped: >= 1)</UL> +</UL> +<B>NOFRAMES</B> +<UL>Used when frames are disabled or for backrev browsers. Has no stylistic +consequences.</UL> + +<H1> + +<HR WIDTH="100%">Body objects:</H1> + <B>BODY</B> +<UL>The tag is only processed on open tags and it is always processed. +See ns\lib\layout\laytags.c, searching for "case P_BODY". During tag processing +the in_head flag is set to false and the in_body flag is set to true. An +attribute is ignored if the document already has that attribute set. Attributes +can be set by style sheets, or by previous BODY tags. see <A HREF="../testhtml/head02.html">test +head02.html</A>. +<BR>Attributes: +<UL><B>MARGINWIDTH</B>=int [clamped: >= 0 && < (windowWidth/2 +- 1)] +<BR><B>MARGINHEIGHT</B>=int [clamped: >= 0 && < (windowHeight/2 +- 1)] +<BR><B>BACKGROUND</B>=url +<BR><B>BGCOLOR</B>=colorspec +<BR><B>TEXT</B>=colorspec +<BR><B>LINK</B>=colorspec +<BR><B>VLINK</B>=colorspec +<BR><B>ALINK</B>=colorspec +<BR><B>ONLOAD, ONUNLOAD, UNFOCUS, ONBLUR, ONHELP</B>=script +<BR><B>ID</B>=string</UL> +</UL> +<B>LAYER, ILAYER</B> +<UL>Open layer/ilayer tag automaticly close out an open form if one is +open. It does something to the soft linebreak state too. +<BR>Attributes: +<UL><B>LEFT</B>=value-or-pct (pct of <TT>right-left</TT> margin) +<BR><B>PAGEX</B>=x (if no LEFT) +<BR><B>TOP</B>=value-or-pct +<BR><B>PAGEY</B>=y (if no TOP) +<BR><B>CLIP</B>=clip +<BR><B>WIDTH</B>=value-or-pct (pct of <TT>right-left</TT> margin) +<BR><B>HEIGHT</B>=value-or-pct +<BR><B>OVERFLOW</B>=string +<BR><B>NAME</B>=string +<BR><B>ID</B>=string +<BR><B>ABOVE</B>=string +<BR><B>BELOW</B>=string +<BR><B>ZINDEX</B>=int [any value] +<BR><B>VISIBILITY</B>=string +<BR><B>BGCOLOR</B>=colorspec +<BR><B>BACKGROUND</B>=url</UL> +</UL> +<B>NOLAYER</B> +<UL>Container for content which is used when layers are disabled or unsupported. +The content has no style consequences (though it could if somebody stuck +in some CSS1 style rules for it).</UL> +<B>P</B> +<UL>Closes the paragraph. If the attribute is present then an alignment +gets pushed on the alignment stack. All values are supported by nav4. +<BR>Attributes: +<UL><B>ALIGN</B>=divalign</UL> +</UL> +<B>ADDRESS</B> +<UL>There are no attributes. ADDRESS closes out the open paragraph. The +open tag does a conditional soft line break and then pushes a merge of +the current style with italics enabled onto the style stack. The close +always pop the style stack and also does a conditional soft line break.</UL> +<B>PLAINTEXT, XMP</B> +<UL>PLAINTEXT causes the remaining content to no longer be parsed. XMP +causes the content to not parse entities or other tags. The XMP can be +closed by it's own tag (on any boundary); PLAINTEXT is not closed (html3.2 +allows it to be closed). Both tags change the style to a fixed font of +a</UL> +<B>LISTING</B> +<UL>Closes the paragraph. Does a hard line break on open and close. Open +pushes a fixed width font style of a particular font size on the style +stack. The close tag pops the top of the style stack. +<BR>Attributes: none</UL> +<B>PRE</B> +<UL>Closes the paragraph. The open tag does a hard line break. A fixed +font style (unless VARIABLE is present) is pushed on the style stack. The +close tag pops the top of the style stack. It also does a hard line break. +<BR>Attributes: +<UL><B>WRAP</B> +<BR><B>COLS</B>=int [clamped: >= 0] +<BR><B>TABSTOP</B>=int [clamped: >= 0; clamped value is replaced with default +value] +<BR><B>VARIABLE</B></UL> +</UL> +<B>NOBR</B> +<UL>This tag doesn't nest. Instead it just sets or clears a flag in the +state machine. It has no effect on any other state.</UL> +<B>CENTER</B> +<UL>Closes the paragraph. Always does a conditional soft line break. The +open tag pushes an alignment on the aligment stack. The close tag pops +the top alignment off. +<BR>Attributes: none</UL> +<B>DIV</B> +<UL>Closes the paragraph. Always does a conditional soft line break. COLS +defines the number of columns to layout in (like MULTICOL). The open tag +pushes an alignment on the alignment stack (if COLS > 1 then it pretends +to be a MULTICOL tag). The close tag pops an aligment from the alignment +stack. +<BR>Attributes: +<UL><B>ALIGN</B>=divalign +<BR><B>COLS</B>=int [if cols > 1 then DIV acts like a MULTICOL tag else +DIV is just a container] +<UL><B>GUTTER</B>= int (clamped: >= 1) +<BR><B>WIDTH</B>= value-or-pct [pct of right-left margin; clamped >= 1/0 +(strange code)]</UL> +</UL> +</UL> +<B>H1-H6</B> +<UL>Closes the paragraph. The open tag does a hard line break and pushes +a style item which enables bold and disables fixed and italic. The close +tag always pops the top item from the style stack. It also does a hard +line break. If the <B>ALIGN</B> attribute is present then the open tag +pushes an alignment on the alignment stack. The close tag will look at +the top of the alignment stack and if its a header of any kind (H1 through +H6) then the alignment is popped. In either case the close tag also does +a conditional soft line break (this happens before the hard line break). +<BR>Attributes: +<UL><B>ALIGN</B>=divalign</UL> +</UL> +A note regarding closing paragraphs: Any time a close paragraph is done +(for any tag) if the top of the alignment stack has a tag named "P" then +a conditional soft line break is done and the alignment is popped. +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>TABLE</B> +<UL>Close the paragraph. +<BR>Attributes: +<UL><B>ALIGN=</B>left|right|center|abscenter +<BR><B>BORDER</B>=int [clamped: if null then -1, if < 1 then 1 ] +<BR><B>BORDERCOLOR</B>=string [if not supplied then set to the text color +] +<BR><B>VSPACE</B>=int [ clamped: >= 0 ] +<BR><B>HSPACE</B>=int [ clamped: >= 0 ] +<BR><B>BGCOLOR</B>=color +<BR><B>BACKGROUND</B>=url +<BR><B>WIDTH</B>=value-or-pct [ % of win.width minus margins; clamped: +>= 0 ] +<BR><B>HEIGHT</B>=value-or-pct [ % of win.height minus margins; clamped: +>= 0 ] +<BR><B>CELLPADDING</B>=int [clamped: >= 0; separate pads take precedence +] +<BR><B>TOPPADDING</B>= int [clamped: >= 0 ] +<BR><B>BOTTOMPADDING</B>= int [clamped: >= 0 ] +<BR><B>LEFTPADDING</B>= int [clamped: >= 0 ] +<BR><B>RIGHTPADDING</B>= int [clamped: >= 0 ] +<BR><B>CELLSPACING</B>= int [clamped: >= 0 ] +<BR><B>COLS</B>=int [clamped: >= 0]</UL> +The code supports more attributes in the Table attribute handler than it +does in the code that gets the attributes from the tag! They are border_top, +border_left, border_right, border_bottom, border_style (defaults to outset; +allows for outset/dotted/none/dashed/solid/double/groove/ridge/inset).</UL> +<B>TR</B> +<UL>Open TR automatically closes an open table row (and an open table cell +if one is open). It also automatically closes a CAPTION tag. +<BR>Attributes: +<UL><B>BGCOLOR</B>=color +<BR><B>BACKGROUND</B>=url +<BR><B>VALIGN</B>=top|bottom|middle|center(==middle)|baseline; default +is top +<BR><B>ALIGN</B>=left|right|middle|center(==middle); default is left</UL> +</UL> +<B>TH, TD</B> +<UL>If no table then the tag is ignored (open or close). If no row is currently +opened or the current row is current done (because of a </TR> tag) then +a new row is begun. Oddly enough the tag parameters for the row come from +the TH/TD tag in this case. An open of either of these tags will automatically +close the previous cell. +<BR>Attributes: +<UL><B>COLSPAN</B>=int [clamped: >= 1 && <= 1000 ] +<BR><B>ROWSPAN</B>=int [clamped: >= 1 && <= 10000 ] +<BR><B>NOWRAP</B> [boolean: disables wrapping ] +<BR><B>BGCOLOR</B>=color [default: inherit from the row; if not row then +table; if not table then inherit from an outer table cell; this works because +the style is flattened so the outer table cell will have a color] +<BR><B>BACKGROUND</B>=url [same rules as bgcolor for inheritance; tile +mode is inherited too and not settable by TH/TD attributes (have to use +style sheets for that)] +<BR><B>VALIGN</B>=top|bottom|middle|center(==middle)|baseline; default +is top +<BR><B>ALIGN</B>=left|right|middle|center(==middle); default is left +<BR><B>WIDTH</B>=value-or-pct [ clamped: >= 0 ] +<BR><B>HEIGHT</B>=value-or-pct [ clamped: >= 0 ]</UL> +</UL> +<B>CAPTION</B> +<UL>An open caption tag will automatically close an open table row (and +an open cell). +<BR>Attributes: +<UL><B>ALIGN</B>=bottom</UL> +The code sets the vertical alignment to top w/o providing a mechanism for +the user to set it (there is no VALIGN attribute).</UL> +<B>MULTICOL</B> +<UL>The open tag does a hard line break. The close tag checks to see if +the state machine has an open multicol and if it does then it does a conditional +soft line break and then continues to break until both margins are cleared +of floating elements. It recomputes the margins based on the list indenting +level (?). After the synthetic table is output the close tag does a hard +line break. + +<P>This tag will treat the input as source for a table with one row and +COLS columns. The data is laid out using the width divided by the number +of columns. After the total height is known, the content is partitioned +as evenly as possible between the columns in the table. +<BR>Attributes: +<UL><B>COLS</B>=int [clamped: values less than 2 cause the tag to be ignored] +<BR><B>GUTTER</B>=int [clamped: >= 1] +<BR><B>WIDTH</B>=value-or-pct [pct of right-left margin; clamped: >= 1/0 +(strange code)]</UL> +</UL> + +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>BLOCKQUOTE</B> +<UL>Closes the paragraph. The open tag does a hard line break. A list with +the empty-bullet style is pushed on the list stack (unless TYPE=cite/jwz +then a styled list is pushed). The close tag pops any list and does a hard +line break. +<BR>Attributes: +<UL><B>TYPE</B>=cite | jwz</UL> +</UL> +<B>UL, OL, MENU, DIR</B> +<UL>For top-level lists (lists not in lists) a hard break is done on the +open tag, otherwise a conditional-soft-break is done. Tag always does a +close paragrah. The close tag does a conditional soft line break when nested; +when not nested the close tag does a hard line break (even if no list is +open). The open tag pushes the list on the list stack. The close tag pops +any list off the list stack. +<BR>Attributes: +<UL><B>TYPE</B>= none | disc | circle | round | square | decimal | lower-roman +| upper-roman | lower-alpha | upper-alpha | A | a | I | i [clamped: if +none of the above is picked and OL then the bullet type is "number" otherwise +the bullet type is "basic"] +<BR><B>START</B>=int [clamped: >= 1] +<BR><B>COMPACT</B></UL> +</UL> +<B>DL</B> +<UL>Closes the paragraph. For the open tag, if the list is nested then +a conditional soft line break is done otherwise a hard line break is done. +The open tag pushes a list on the list stack. The close tag pops any list +from the list stack. Closing the list acts like other lists closes. +<BR>Attributes: +<UL><B>COMPACT</B></UL> +</UL> +<B>LI</B> +<UL>Closes the paragraph. The open tag does a conditional soft line break. +Close tags are ignored (except for closing the paragraph). +<BR>Attributes: +<UL><B>TYPE</B>= A | a | I | i (if the containing list is an <B>OL</B>) +<BR><B>TYPE</B>= round | circle | square (if the containing list is not +<B>OL</B> and not <B>DL</B>) +<BR><B>VALUE</B>=int [clamped: >= 1]</UL> +The magellan html parser allows the full set of list item styles from the +OL/DL tag instead of just the limited set that nav4 allows.</UL> +<B>DD</B> +<UL>Closes the paragraph. Close tags are ignored (except for closing the +paragraph). DD outside a DL just advances the X coordinate of layout by +a small constant. DD inside a DL does a conditional soft line break and +other margin crud. +<BR>Attributes: none.</UL> +<B>DT</B> +<UL>Closes the paragraph (open or close). Close tags are otherwise ignored. +Does a conditional soft line break. Moves the X layout coordinate to the +left margin. +<BR>Attributes: none</UL> + +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>A</B> +<UL>Open anchors push a style on the style stack if the anchor has an <B>HREF</B>. +Close anchors pop as many styles off the top of the style stack that are +anchor tags (anchor tags don't nest in other words). In addition, any styles +on the stack that have the ANCHOR bit set have it cleared and fiddle with +the foreground and background colors. +<BR>Attributes: +<UL><B>NAME</B>=string +<BR><B>HREF</B>=url +<UL><B>TARGET</B>=target +<BR><B>SUPPRESS</B>=true</UL> +</UL> +</UL> +<B>STRIKE, S, TT, CODE, SAMPLE, KBD, B, STRONG, I, EM, VAR, CITE, BLINK, +BIG, SMALL, U, INLINEINPUT, SPELL</B> +<UL>The open tag pushes onto the style stack. The close tag always pops +the top item from the style stack. +<BR>Attributes: none</UL> +<B>SUP, SUB</B> +<UL>The open tag pushes a font size descrease on the style stack. The close +tag always pops the top of the style stack. The open and close tag impacts +the baselineThe only difference between SUP and SUB is how they impact +the baseline. Note that the baseline information is forgotten after a line +break; therefore a close SUP/SUB on the next line will do strange things. +<BR>Attributes: none</UL> +<B>SPAN</B> +<UL>Ignored by the navigator. +<BR>Attributes: none</UL> +<B>FONT</B> +<UL>The open font tag with no attributes resets the font size to the base +font size. The open tag always pushes a style stack entry. The close tag +always pops the top item off the style stack. +<BR>Attributes: +<UL><B>SIZE</B>=[+ int | - int | int ] [clamped: >=1 && <= +7] +<BR><B>POINT-SIZE=</B>[+ int | - int | int ] [clamped: >= 1 && +<= 1600] +<BR><B>FONT-WEIGHT</B>=[+ int | - int | int ] [clamped: >= 100 && +<= 900] +<BR><B>COLOR</B>=colorspec +<BR><B>FACE</B>=string</UL> +</UL> +A note regarding the style stack: The pop of the stack checks to see if +the top of the stack is an ANCHOR tag. If it is not an anchor then the +top item is unconditionally popped. If the top of the style stack is an +anchor tag then the code searches for either the bottom of the stack or +the first style stack entry not created by an anchor tag. If the entry +is followed by another entry then the entry is removed from the stack (an +out-of-order pop in other words). In this case the anchor style stack entry +is left untouched. +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>text, entities</B> +<UL>These are basic content objects that get fed directly to the output. +In navigator the text is processed by doing line-breaking (entities have +been converted to text already by the parser). The line-breaking is controlled +by the margin settings and the list depth, the floating elements, the style +attributes (font size, etc.), the preformatted flag, the no-break flag +and so on.</UL> +<B>IMG, IMAGE</B> +<UL>Close tag is ignored. +<BR>Attributes: +<UL><B>ISMAP</B> +<BR><B>USEMAP</B>=url +<BR><B>ALIGN</B>=alignparam +<BR><B>SRC</B>=url [ whitespace is stripped ] +<BR><B>LOWSRC</B>=url +<BR><B>ALT</B>=string +<BR><B>WIDTH</B>=value-or-pct (pct of <TT>right-left</TT> width) +<BR><B>HEIGHT</B>=value-or-pct (pct of window height) +<BR><B>BORDER</B>=int [clamped: >= 0] +<BR><B>VSPACE</B>=int [clamped: >= 0] +<BR><B>HSPACE</B>=int [clamped: >= 0] +<BR><B>SUPPRESS</B>=true | false (only in blocked image layout???)</UL> +</UL> +<B>HR</B> +<UL>Closes the paragraph. If an open tag then does a conditional soft line +break. The rule inherits alignment from the parent container unless there +is no container (then it's centered) or if the tag defines it's own alignment. +After the object is inserted into the layout stream a soft line break is +inserted as well. +<BR>Attributes: +<UL><B>ALIGN</B>=divalign (sort of; in laytags.c it's divalign; in layhrule.c +it's left or right only) +<BR><B>SIZE</B>=int (1 to 100 inclusive) +<BR><B>WIDTH</B>=val-or-pct (pct of <TT>right-left</TT> width) +<BR><B>NOSHADE</B></UL> +</UL> +<B>BR</B> +<UL>Does an unconditional soft break. If clear is set then it will also +soft break until either the left or right or both margins are clear of +floating elements. Note that<FONT COLOR="#0000FF"> /BR == BR!</FONT> +<BR>Attributes: +<UL><B>CLEAR</B>=left | right | all | both</UL> +</UL> +<B>WBR</B> +<UL>Soft word break. +<BR>Attributes: none</UL> +<B>EMBED</B> +<UL>Close tag does nothing. Embed's operate inline just like images (they +don't close the paragraph). +<BR>Attributes: +<UL><B>HIDDEN</B>=no | false | off +<BR><B>ALIGN</B>=alignparam +<BR><B>SRC</B>=url +<BR><B>WIDTH</B>=val-or-pct (pct of <TT>right-left</TT> width) +<BR><B>HEIGHT</B>=val-of-pct; if val is < 1 (sometimes) the element +gets HIDDEN automatically +<BR><B>BORDER</B>=int (unsupported by navigator) +<BR><B>VSPACE</B>=int [clamped: >= 0] +<BR><B>HSPACE</B>=int [clamped: >= 0]</UL> +</UL> +<B>NOEBMED</B> +<UL>Used when EMBED's are disabled. It is a container for regular content +that has no stylistic consequences (no line breaking, no style stack effect, +etc.).</UL> +<B>APPLET</B> +<UL>Applet tags don't nest (there is a notion of current_applet). The open +tag automatically closes an open applet tag. +<BR>Attributes: +<UL><B>ALIGN</B>=alignparam +<BR><B>CODE</B>=string +<BR><B>CODEBASE</B>=string +<BR><B>ARCHIVE</B>=string +<BR><B>MAYSCRIPT</B> +<BR><B>NAME</B>=string [clamped: white space is stripped out] +<BR><B>WIDTH</B>=value-or-pct [pct of right-left width; clamped: >= 1] +<BR><B>HEIGHT</B>=value-or-pct [pct of window height; clamped >= 1] +<BR><B>BORDER</B>=int [clamped: >= 0] +<BR><B>HSPACE</B>=int [clamped: >= 0] +<BR><B>VSPACE</B>=int [clamped: >= 0]</UL> +If no width is provided: +<UL>if a height was provided, use the height. Otherwise, use 90% of the +window width if percentage widths are allowed, otherwise use a value of +600. +<BR> </UL> +If no height is provided: +<UL>if a width was provided, use the width. Otherwise, use 50% of the window +height if percentage widths are allowed, otherwise use a value of 400.</UL> +If the applet is hidden, then the widht/height get forced to zero.</UL> +<B>PARAM</B> +<UL>The param tag is supported when contained by the APPLET tag or the +OBJECT tag. It has no stylistic consequences. The attribute values from +the tag are passed to the containing APPLET or OBJECT. Note that <FONT COLOR="#0000FF">/PARAM +== PARAM</FONT>. +<BR>Attributes: +<UL><B>NAME</B>=string [clamped: white space is stripped out] +<BR><B>VALUE</B>=string [clamped: white space is stripped out]</UL> +White space being stripped is done as follows: leading and trailing whitespace +is removed. Any embedded whitespace is left alone except if it's a non-space +whitespace in which case it is removed.</UL> +<B>OBJECT</B> +<UL>The open tag pushes an object onto the object stack. The close tag +pops from the object stack. I don't understand how the data stuff works. +<BR>Attributes: +<UL><B>CLASSID</B>=string (clsid:, java:, javaprogram:, javabean: are the +supported prefixes; maybe it's a url if no prefix shown?) +<BR><B>TYPE</B>=string (a mime type) +<BR><B>DATA</B>=string (data: prefix mentions a url)</UL> +There are more attributes that depend on the type of object being embedded +in the page. If the object is a java bean (?) then the applet parameters +are supported: +<UL>CLASSID +<BR>HIDDEN +<BR>ALIGN +<BR>CLASSID (instead of CODE) +<BR>CODEBASE +<BR>ARCHIVE +<BR>MAYSCRIPT +<BR>ID (applets use NAME) +<BR>WIDTH +<BR>HEIGHT +<BR>BORDER +<BR>HSPACE +<BR>VSPACE</UL> +</UL> +<B>MAP</B> +<UL>The open tag automatically closes an open map (maps don't nest). There +is no stylistic consequence of the map nor does it provide any visible +presentation in the normal layout case (an editor would do something different). +The map can be declared anywhere in the document. +<BR>Attributes: +<UL><B>NAME</B>=string [clamped: white space is stripped out]</UL> +</UL> +<B>AREA</B> +<UL>Does nothing if there is no current map or the tag is a close tag. +<BR>Attributes: +<UL><B>SHAPE</B>=default | rect | circle | poly | polygon +<BR><B>ALT</B>=string [clamped: newlines are stripped] +<BR><B>COORDS</B>=coord-list +<BR><B>HREF=</B>url +<UL><B>TARGET</B>=target (only if HREF is specified)</UL> +<B>SUPPRESS</B></UL> +</UL> +<B>SERVER</B> +<UL>A container for server-side javascript. Not evaluated by the client +(parsed and ignored). Note: The navigator parser doesn't expand entities +in a <B>SERVER </B>tag.</UL> +<B>SPACER</B> +<UL>Close tag is ignored. Open tag provides whitespace during layout: <B>TYPE</B>=line/vert/vertical +causes a conditional soft line break and then adds <B>SIZE </B>to the Y +layout coordinate. <B>TYPE</B>=word causes a conditional soft word break +and then adds <B>SIZE </B>to the X layout coordinate. <B>TYPE</B>=block +causes <FONT COLOR="#DD0000">blockish </FONT>layout stuff to happen. +<BR>Attributes: +<UL><B>TYPE</B>=line | vert | vertical | block (default: word) +<UL><B>ALIGN</B>=alignparam (these 3 params are only for <B>TYPE</B>=block) +<BR><B>WIDTH</B>=value-or-pct +<BR><B>HEIGHT</B>=value-or-pct</UL> +<B>SIZE</B>=int [clampled: >= 0]</UL> +</UL> + +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>SCRIPT</B> +<UL>Note: The navigator parser doesn't expand entities in a SCRIPT tag. +<BR>Attributes: +<UL><B>LANGUAGE</B>=LiveScript | Mocha | JavaScript1.1 | JavaScript1.2 +<BR><B>TYPE</B>="text/javascript" | "text/css" +<BR><B>HREF</B>=url +<BR><B>ARCHIVE</B>=url +<BR><B>CODEBASE</B>=url +<BR><B>ID</B>=string +<BR><B>SRC</B>=url</UL> +</UL> +<B>NOSCRIPT</B> +<UL>Used when scripting is off or by backrev browsers. It is a container +that has no stylistic consequences.</UL> + +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>FORM </B> +<UL>Attributes: +<UL><B>ACTION</B>=href +<BR><B>ENCODING</B>=string +<BR><B>TARGET</B>=string +<BR><B>METHOD</B>=get | post</UL> +</UL> +<B>ISINDEX </B> +<UL>This tag is a shortcut for creating a form element with a submit button +and a single text field. If the PROMPT attribute is not present in the +tag then the value used is <B>"This is a searchable index. Enter search +keywords:"</B>. + +<P>Attributes: +<UL><B>PROMPT</B>=string +<BR><B>ACTION</B>=href +<BR><B>ENCODING</B>=string +<BR><B>TARGET</B>=string +<BR><B>METHOD</B>=get | post</UL> +</UL> +<B>INPUT </B> +<UL>Attributes vary according to type: +<UL><B>TYPE</B>= text | radio | checkbox | hidden | submit | reset | password +| button | image | file | jot | readonly | object +<BR><B>NAME</B>= string +<BR> </UL> +<B>TYPE</B>=image +<UL>attributes are from the IMG tag (!)</UL> +<B>TYPE</B>= text | password | file +<UL>font style is forced to fixed +<BR><B>VALUE</B>= string +<BR><B>SIZE</B>= int (clamped; >= 1) +<BR><B>MAXLENGTH</B>= int (not clamped!)</UL> +<B>TYPE</B>= submit | reset | button | hidden | readonly +<UL><B>VALUE</B>=string; default if no value to the attribute varies according +to the type: +<UL><B>submit</B> -> "Submit Query" +<BR><B>reset</B> -> "Reset" +<BR>others -> " " (2 spaces) +<BR>Note also that the value has newlines stripped from it</UL> +<B>WIDTH</B>=int (clamped >=0 && <= 1000) (only for submit, +reset or button) +<BR><B>HEIGHT</B>=int (clamped >=0 && <= 1000) (only for submit, +reset or button)</UL> +<B>TYPE</B>=radio | checkbox +<UL><B>CHECKED</B> (flag - if present then set to true) +<BR><B>VALUE</B>= string (the default value is "on")</UL> +</UL> +<B>SELECT </B> +<UL>Attributes: +<UL><B>MULTIPLE</B> (boolean) +<BR><B>SIZE</B>= int (clamped >= 1) +<BR><B>NAME=</B> string +<BR><B>WIDTH</B>= int (clampled >= 0 && <= 1000) +<BR><B>HEIGHT</B>= int (clamped >= 0 && <= 1000; only examined +for single entry lists (!multiple || size==1))</UL> +</UL> +<B>OPTION </B> +<UL>Lives inside the SELECT tag (ignored otherwise). +<BR>Attributes: +<UL><B>VALUE</B>=string +<BR><B>SELECTED</B> boolean</UL> +</UL> +<B>TEXTAREA </B> +<UL>Attributes: +<UL><B>NAME</B>=string +<BR><B>ROWS</B>=int (clamped; >= 1) +<BR><B>COLS</B>=int (clamped; >= 1) +<BR><B>WRAP</B>= off | hard | soft (default is off; any value which is +not known turns into soft)</UL> +</UL> +<B>KEYGEN </B> +<UL>Attributes: +<UL><B>NAME</B>=string +<BR><B>CHALLENGE</B>=string +<BR><B>PQG</B>=string +<BR><B>KEYTYPE</B>=string</UL> +</UL> + +<H3> + +<HR ALIGN=LEFT WIDTH="50%"></H3> +<B>BASEFONT </B> +<UL>Sets the base font value which +/- size values in FONT tags are relative +to. +<BR>Attributes: +<UL>SIZE=+ int | - int | int (just like FONT)</UL> +</UL> + +<H2> + +<HR WIDTH="100%">Unsupported</H2> +<B>NSCP_CLOSE, NSCP_OPEN, NSCP_REBLOCK, MQUOTE, CELL, SUBDOC, CERTIFICATE, +INLINEINPUTTHICK, INLINEINPUTDOTTED, COLORMAP, HYPE, SPELL, NSDT</B> +<UL>These tags are unsupported because they are used internally by netscape +and are never seen in real content. If somebody does use them between 4.0 +and magellan, tough beans. We never documented them so they lose.</UL> + +</BODY> +</HTML> diff --git a/layout/doc/overview.html b/layout/doc/overview.html new file mode 100644 index 000000000..93ff4891b --- /dev/null +++ b/layout/doc/overview.html @@ -0,0 +1,180 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> + <title>Layout Documentation Overview</title> +</head> + <body> + +<h1>Layout Documentation Overview</h1> +<blockquote> Authors: <br> + <ul> + <li>Marc Attinasi (attinasi@netscape.com)</li> + </ul> +History: <br> + <ul> + <li>12/17/2001 - created<br> + </li> + </ul> + </blockquote> + <h2>Background</h2> + 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.<br> + <br> + + <h2>Strategy:</h2> + 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 <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=115310"> + bug 115310</a> + . 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. <br> + <br> + + <h2>Scope:</h2> + 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.<br> + <br> + + <h3>High Level Designs</h3> + 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. <br> + <br> + A fundamental piece of the high-level design is the<b> data model</b>. 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.<br> + <br> + Another important piece of the high-level design is a set of <b>use-cases</b> + 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.<br> + <b><br> + State Transition Diagrams</b> 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.<br> + <br> + 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. + <br> + <br> + + <h3>Detailed Designs</h3> + 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.<br> + <br> + + <h4>Public API</h4> + 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:<br> + + <ul> + <li>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)?<br> + </li> + <li>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?</li> + <li>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?</li> + <li>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?</li> + + </ul> + 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.<br> + <br> + + <h4>Algorithms</h4> + 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.<br> + <br> + <br> + 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.<br> + + <h4></h4> + <h4> Tech Notes</h4> +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 publicly accessible +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.<br> + <br> + + </body> + </html> diff --git a/layout/doc/raptor.jpg b/layout/doc/raptor.jpg Binary files differnew file mode 100644 index 000000000..243ba9e2d --- /dev/null +++ b/layout/doc/raptor.jpg diff --git a/layout/doc/regression_tests.html b/layout/doc/regression_tests.html new file mode 100644 index 000000000..f1a8ba52c --- /dev/null +++ b/layout/doc/regression_tests.html @@ -0,0 +1,212 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>Layout Regression tests</title> +<style type="text/css"> + body {font-family:arial} +.screen {background-color:silver; color:blue} +pre.screen {display:table-cell} + </style> + +</head> +<body> + +<h1>Table Regression Tests</h1> +<h6>Bernd Mielke</h6> +<h2>About This Document</h2> +<p> +This document describes my guerrilla approach to successfully running the table layout regression tests. It should encourage more people to run those tests. + +<h2>Subject Overview</h2> +<p> +The table element and its children are one of the major layout components that can create some structure on the screen. They are widely (ab)used by page authors. Every small change in the table code can generate a bunch of bugzilla entries and a lot of seemingly unrelated dupes. With the high frequency of checkins in to the source tree it is difficult and time consuming to track the regression down to a single checkin. The risk of becoming very infamous can be reduced by running the layout regression tests. + +<h2>Prerequisites</h2> +<p> +In order to run these tests, you will need to have: +<ol> +<li>a debug build with a working viewer, an optimized build will not work! +<li>a mozilla tree with the testfiles at <code>%MOZ_SRC%/layout/html/tests</code>, +<li> <code>DISABLE_TESTS</code> should not be defined, +<li>patience and time. +</ol> + +<h2>Test Runs</h2> + +<ul> +<li>Go to the <code>%MOZ_SRC%/layout/html/tests/block</code> directory. +<li> Avoid the nasty assertions to pop up by <code>set XPCOM_DEBUG_BREAK=warn</code>, the world would be a much better place if we could <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=152015">first fix those assertions</a>. +<li>The following shell scripts need a <code>sh</code> before the command under WinXX. +<li>Execute <code>rtest.sh baseline</code> +<li>Execute <code>rtest.sh verify>outputfile.txt</code> +<li>Make a note which tests have failed (these are false positives. If you are in bad mood file a bug against Chris Waterson about them) +<li>you can grep the failures by:<br> +<code>grep 'rgd failed' <outputfile.txt >false_positive.txt</code> +<li> Make a copy of <code>gklayout.dll</code> and <code>gkcontent.dll</code> in the <code>dist</code> directory. If you would like to switch back, you will need them. +<li>Make your changes to the source, compile and install. +<li>execute in the <code>layout/html/tests/block</code> directory <code>rtest.sh verify >regression.txt</code> +<li>Check how many tests have failed and analyse your results: +<ul> +<li>If the regression tests have failed at the same place as the previous diagnosed false positives => ignore +<ol> +<li>copy <code>rtest.sh</code> to <code>my_rtest.sh</code> +<li>create a new directory <code>my_files</code>. +<li>create in this directory a file <code>file_list.txt</code>, where you put the url's of your remaining test failures +<li>change <code>my_rtest.sh</code> to use only directory <code>my_files</code> +<li>go back to the original gklayout.dll and gkcontent.dll and repeat the regression test procedure on a much smaller set now. +</ol> +<li>Try to figure out what the other regressions are: Are they + improving the picture or are they regressions? +<li>Note the difficult to explain testfailures. +</ul> +<li> Change the source if necessary until the regression tests indicate that your patch does not hork the block and table layout +<li> Submit your patch and lists the remaining differences in the bug +</ul> + +<p>Be prepared to cycle. + +<h2>How the layout regression tests work</h2> + +<p>First the URL's to test are red from <code>file_list.txt</code>.<p> +<table><caption>snippet from file_list.txt</caption><tr><td> +<pre>file:///s|/mozilla/layout/html/tests/table/dom/appendCells1.html +file:///s|/mozilla/layout/html/tests/table/dom/appendCellsRebuild1.html +file:///s|/mozilla/layout/html/tests/table/dom/appendCol1.html +file:///s|/mozilla/layout/html/tests/table/dom/appendCol2.html +file:///s|/mozilla/layout/html/tests/table/dom/appendColGroup1.html +file:///s|/mozilla/layout/html/tests/table/dom/appendRowsExpand1.html</pre> +</td></tr></table> +<p>The regression tests compare the frame tree dumps recorded at two different times. The URL's to test are red from <code>file_list.txt</code> +For every file in <code>file_list.txt</code>viewer takes the root frame and dumps the whole tree via +<a href="http://lxr.mozilla.org/seamonkey/search?string=nsFrame%3A%3ADumpRegression"> +nsFrame::DumpRegression</a>. +<p> + The frame tree dumps are invoked by the <code>-o</code> switch to the <code>viewer</code> (see <a href="http://lxr.mozilla.org/seamonkey/ident?i=PrintHelpInfo">commandline arguments </a>). +When <code>-o</code> is specified together with a output directory for instance (<code>-o s:\mozilla\layout\html\tests\table\dom\</code>), +the frame trees are dumped to separate files in that directory for all URL's in <code>file_list.txt</code> (see: +<a href="http://lxr.mozilla.org/seamonkey/search?string=nsWebCrawler%3A%3ADumpRegression"> +nsWebCrawler::DumpRegressionData</a>) . +<p>Their name is generated by replacing the old extension <code>.html</code> or <code>.xml</code> with <code>.rgd</code>. For <code>file:///s|/mozilla/layout/html/tests/table/dom/appendCells1.html</code> a file <code>appendCells1.rgd</code> will be created in the <code>s:\mozilla\layout\html\tests\table\dom\</code> directory. + +<p> + There is a special type of frame dumps - the printing regression tests, they are invoked by the <code>-Prt</code> command line argument to the <code>viewer</code> and include first a display then a frame dump taking into account the printer pages. A typical beginning of a dump (<code>*.rgd</code> file) looks like:<p> +<pre class="screen"> +<frame va="15022440" type="Viewport(-1)" state="270340" parent="0"> + <view va="47171904"> + </view> + <stylecontext va="15022232"> + <font serif 240 240 0 /> + <color data="-16777216"/> + <background data="0 2 3 -1 0 0 "/> + <spacing data="left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0" /> + <list data="100 100 " /> + <position data="left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto " /> + <text data="0 0 0 Normal Normal 0[0x0]tw Normal " /> + <textreset data="0 10[0xa]enum " /> + <display data="0 1 0 0 0 0 0 0 0 0 0 0 " /> + <visibility data="0 1 1.000000" /> + <table data="0 0 4 -1 1 " /> + <tableborder data="1 Null Null 0 2 " /> + <content data="0 0 0 Null " /> + <quotes data="0 " /> + <ui data="3 0 0 1 " /> + <uireset data="7 0 4" /> + <xul data="0 0 0 0 0 1 <svg data="0 1.000000 1.000000 0 1.000000" /> + </stylecontext></pre> +<p>The first run of the regression tests is started with the argument <code>baseline</code> and it creates the reference frame dumps. +<p>The <code>baseline</code> log will look like: +<pre class="screen"> +Type Manifest File: C:\MOZ_SOUR\MOZILLA\MOZILLA\DIST\WIN32_D.OBJ\BIN\components\xpti.dat +nsNativeComponentLoader: autoregistering begins. +nsNativeComponentLoader: autoregistering succeeded +Going to create the event queue +WEBSHELL+ = 1 +Note: verifyreflow is disabled +Note: styleverifytree is disabled +Note: frameverifytree is disabled ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCells1.html: done loading (11810 msec) +appendCells1.rgd - being written ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCellsRebuild1.html: done loading (1260 msec) +appendCellsRebuild1.rgd - being written ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCol1.html: done loading (270 msec) +appendCol1.rgd - being written ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCol2.html: done loading (220 msec) +appendCol2.rgd - being written ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendColGroup1.html: done loading (390 msec) +appendColGroup1.rgd - being written ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendRowsExpand1.html: done loading (220 msec) +appendRowsExpand1.rgd - being written +</pre> +<p> +The second run with the argument <code>verify</code> creates first the frame dumps in a subdirectory (<code>verify</code>) and <a href="http://lxr.mozilla.org/seamonkey/search?string=nsFrameUtil%3A%3ACompareTrees">compares</a> each frame dump with the corresponding reference frame dump. If they differ in critical points the test fails. +<p>A typical part of the <code>verify</code> log would look like: +<pre class="screen"> +Type Manifest File: C:\MOZ_SOUR\MOZILLA\MOZILLA\DIST\WIN32_D.OBJ\BIN\components\xpti.dat +nsNativeComponentLoader: autoregistering begins. +nsNativeComponentLoader: autoregistering succeeded +Going to create the event queue +WEBSHELL+ = 1 +Note: verifyreflow is disabled +Note: styleverifytree is disabled +Note: frameverifytree is disabled ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCells1.html: done loading (2200 msec) +frame bbox mismatch: 0,285,930,435 vs. 0,285,1305,435 +Node 1: + TableOuter(table)(1) 0x10004 0,285,930,435, |null attr|-16777216|left: 0[0x0]tw top: 0[0x0]tw right: 0[0x0]tw bottom: 0[0x0]tw left: 0[0x0]tw top: 0[0x0]tw right: 0[0x0]tw bottom: 0[0x0]tw left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Inherit top: Inherit right: Inherit bottom: Inherit 0[0x0]tw 0[0x0]tw Null 0[0x0]tw 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 8 0 0 0 0 0 1 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +Node 2: + TableOuter(table)(1) 0x10004 0,285,1305,435, |null attr|-16777216|left: 0[0x0]tw top: 0[0x0]tw right: 0[0x0]tw bottom: 0[0x0]tw left: 0[0x0]tw top: 0[0x0]tw right: 0[0x0]tw bottom: 0[0x0]tw left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Inherit top: Inherit right: Inherit bottom: Inherit 0[0x0]tw 0[0x0]tw Null 0[0x0]tw 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 8 0 0 0 0 0 1 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +frame bbox mismatch: 0,0,930,435 vs. 0,0,1305,435 +Node 1: + Table(table)(1) 0x10004 0,0,930,435, |null attr|-16777216|left: Null top: 0[0x0]tw right: Null bottom: 0[0x0]tw left: Null top: Null right: Null bottom: Null left: 15[0xf]tw top: 15[0xf]tw right: 15[0xf]tw bottom: 15[0xf]tw left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 2 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 8 0 0 0 0 0 0 0 0 0 0 |0 8 4 -1 1 |0 0 0 Null +Node 2: + Table(table)(1) 0x10004 0,0,1305,435, |null attr|-16777216|left: Null top: 0[0x0]tw right: Null bottom: 0[0x0]tw left: Null top: Null right: Null bottom: Null left: 15[0xf]tw top: 15[0xf]tw right: 15[0xf]tw bottom: 15[0xf]tw left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 2 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 8 0 0 0 0 0 0 0 0 0 0 |0 8 4 -1 1 |0 0 0 Null +frame bbox mismatch: 45,15,840,405 vs. 45,15,1215,405 +Node 1: + TableColGroup(table)(1) 0x80010004 45,15,840,405, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 12 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +Node 2: + TableColGroup(table)(1) 0x80010004 45,15,1215,405, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 12 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +frame state mismatch: 0x30010406 vs. 0x30010004 +Node 1: + TableCol(table)(1) 0x30010406 0,0,0,0, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 11 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +Node 2: + TableCol(table)(1) 0x30010004 870,0,345,405, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 11 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +frame bbox mismatch: 0,0,0,0 vs. 870,0,345,405 +Node 1: + TableCol(table)(1) 0x30010406 0,0,0,0, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 11 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +Node 2: + TableCol(table)(1) 0x30010004 870,0,345,405, |null attr|-16777216|left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null left: 1[0x1]enum top: 1[0x1]enum right: 1[0x1]enum bottom: 1[0x1]enum left: Null top: Null right: Null bottom: Null left: Null top: Null right: Null bottom: Null 1[0x1]enum 0|100 100 |left: Auto top: Auto right: Auto bottom: Auto Auto 0[0x0]tw Null Auto 0[0x0]tw Null 0 Auto |0 0 0 Normal Normal 0[0x0]tw Normal |0 11 0 0 0 0 0 0 0 0 0 0 |0 0 4 -1 1 |0 0 0 Null +regression test s:\mozilla\layout\html\tests\table\dom\verify\appendCells1.rgd failed ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCellsRebuild1.html: done loading (390 msec) +044regression test s:\mozilla\layout\html\tests\table\dom\verify\appendCellsRebuild1.rgd passed ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCol1.html: done loading (280 msec) +regression test s:\mozilla\layout\html\tests\table\dom\verify\appendCol1.rgd passed ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendCol2.html: done loading (220 msec) +regression test s:\mozilla\layout\html\tests\table\dom\verify\appendCol2.rgd passed ++++ file:///s|/mozilla/layout/html/tests/table/dom/appendColGroup1.html: done loading (220 msec) +regression test s:\mozilla\layout\html\tests\table\dom\verify\appendColGroup1.rgd passed +</pre> +<p> +The first regression test has failed and it is marked so. + + +<h2>Adding new regression tests</h2> +<p> +Once you have checked in the code: +<ul> +<li> please add your testcase for the bug to the regression tests. +<li>A testcase should only contain local files. +<li>Place the images in <code>table/images</code> (don't forget <code> cvs commit -kb </code>) +<li>and the testfile in the <code>table/bugs</code> directory. +<li>Update the <code>file_list<b>x</b>.txt</code> in order to include your file. +</ul> +<p>I would like to thank Chris Karnaze for his guidance and fantasai for his language support. +<div style="text-align:right"><i><regression.html> <Last updated: +2002-06-16 <a href="mailto:bernd.mielke@snafu.de">Bernd Mielke</a></i></div> + +</body> +</html> diff --git a/layout/doc/table_reflow_slides.html b/layout/doc/table_reflow_slides.html new file mode 100644 index 000000000..e76a10768 --- /dev/null +++ b/layout/doc/table_reflow_slides.html @@ -0,0 +1,888 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!-- vim:sw=2:et:ts=2:tw=72: +--> +<!DOCTYPE html public "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en-US"> +<head> + <title>Table Reflow Tech Talk, 2002-08-05</title> + <style type="text/css"> + + html, body { + height: 100%; + overflow: visible; + } + + body { + font-size: 1.4em; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: bold; + background: white; + color: black; + } + + h1, h2, p { + margin: 0; + } + + h1 { + font: inherit; + font-size: 1.5em; + /* text-align: center; */ + margin-bottom: 0.8em; + border-bottom: 0.1em solid #006; + color: #006; + } + + h2 { + font: inherit; + font-size: 1.2em; + text-align: left; + margin: 0.15em 0; + } + + ul { + padding: 0 0 0 1.4em; + margin: 0; + } + + li { margin: 0; + margin-top: 0.5em; + padding: 0; + font-size: 1.0em;} + + div.slide { + position: relative; + min-height: 100%; + } + + div.nav { + /* + position: absolute; + top: 4px; + right: 4px; + */ + float: right; + margin: 4px; + } + + div.nav :link, div.nav :visited, div.nav span { + text-decoration: none; + background: #006; + color: white; + padding: 0 0.4em 0.2em 0.4em; + line-height: 1.4em; + } + + div.nav :link:hover, div.nav :visited:hover { + background: #00f; + } + + table { + margin: auto; + } + + table.box { + border-collapse: collapse; + border: 2px solid black; + box-sizing: border-box; + width:98%; + height:96%; + } + + row { + border: 2px solid black; + } + row.title { + border: hidden; + } + + table td { + /*text-align: center;*/ + empty-cells: hide; + } + + table td.box { + height:100%; + border: 2px solid black; + } + + table td.title { + border-top: hidden; + border-right: hidden; + border-left: hidden; + font-size: .5em; + } + + table td.title2 { + border-bottom: hidden; + border-right: hidden; + border-left: hidden; + font-size: .5em; + } + + table.tree tr:not(.arrows) td { + font-family: monospace; + border: 0.1em solid; + font-size: .7em; + text-align:center; + } + + table td.left-arrow { + text-align: right; + } + + table td.right-arrow { + text-align: left; + } + + table td.center-arrow { + text-align: center; + } + + span.html { + color:purple; + } + + table td.space { + width: 5%; + } + + table td.frame { + width: 22%; + } + + span.comment { + color: red; + } + + </style> +</head> +<body> + +<div class="slide" id="s0"> + <div class="nav"> + <a href="#s28"><</a> + <a href="#s1">></a> + </div> + <table style="margin: auto"><tr><td> + <center> + <h1>Table Reflow Internals<br>Tech Talk</h1> + <p>Aug 5, 2002</p> + <p style="margin-top: 0.5em">Chris Karnaze</a></p> + </center> + </td></tr></table> + +</div> + +<div class="slide" id="s1"> + <div class="nav"> + <a href="#s0"><</a> + <a href="#s2">></a> + </div> + <h1>Overview</h1> + <ul> + <li>Review of reflow</li> + <li>Table frames</li> + <li>Table reflow</li> + <li>Intro to paginated reflow</li> + <li>Table paginated reflow</li> + </ul> +</div> + +<div class="slide" id="s2"> + <div class="nav"> + <a href="#s1"><</a> + <a href="#s3">></a> + </div> + <h1>Review of Reflow</h1> + <ul> + <li>Reflow process starts when + <ul> + <li>An html document starts loading (the frame tree contains only viewport, scroll(s), canvas, html, body).</li> + <li>The initial chunk of an xml doc is loaded.</li> + <li>The initial chunk of an html doc (or a subsequent chunk of an xml doc) is loaded. The container posts a + dirty reflow command with itself as the target. </li> + <li>Content is inserted, appended, or deleted through the DOM. The container posts a dirty reflow command + with itself as the target.</li> + <li>Style changes through the DOM - javascript, browser change font (CTRL+/-), a preference changes, etc.</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s3"> + <div class="nav"> + <a href="#s2"><</a> + <a href="#s4">></a> + </div> + <h1>Review of Reflow</h1> + <ul> + <li>Reflow starts with pres shell + <ul> + <li>Which reflows the reflow root (usually the view port frame),</li> + <li>Which reflows it children, etc.</li> + </ul> + </li> + <li>Ususally it starts when the pres shell processes its queue of reflow commands.</li> + <li>The reflower + <ul> + <li>Positions reflowee (if it can) before actually reflowing in case views are involved + (e.g. absolutely positioned elements) </li> + <li>Reflows reflowee and passes a reflow state (in) and a reflow metrics (in/out)</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s4"> + <div class="nav"> + <a href="#s3"><</a> + <a href="#s5">></a> + </div> + <h1>Review of Reflow</h1> + <ul> + <li>The reflow state: + <ul> + <li>Is a node in a tree structurally equivalent to the frame tree of reflow participants</li> + <li>contains: + <ul> + <li>reflow type,</li> + <li>avail size,</li> + <li>various computed values,</li> + <li>resolved style structs</li> + <li>possible request for preferred size and more.</li> + </ul> + </li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s5"> + <div class="nav"> + <a href="#s4"><</a> + <a href="#s6">></a> + </div> + <h1>Review of Reflow</h1> + <ul> + </li> + <li>the reflow metrics contains: + <ul class=nested> + <li>max element size (if requested) - the minimum size it can be</li> + <li>preferred size (if requested) - the size it would like to be given no size constraints.</li> + <li>desired size - the size it would like to be given the avail size. This + is equivalent to preferred size if the avail size is not constrained.</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s6"> + <div class="nav"> + <a href="#s5"><</a> + <a href="#s7">></a> + </div> + <h1>Review of Reflow</h1> + <ul> + <li>The reflowee sets various sizes in the reflow metrics after (possibly) reflowing some or all of its children + which reflows it children, etc.</li> + <li>The reflowee returns a reflow status which indicates + <ul class=nested> + <li>if it is complete, and thus not have to continue (split)</li> + <li>breaking status (in the case of some inline frames)</li> + <li>if there is truncation (it can't fit in the space and can't split). This is just a convience mechanism.</li> + </ul> + </li> + +</div> + +<div class="slide" id="s7"> + <div class="nav"> + <a href="#s6"><</a> + <a href="#s8">></a> + </div> + + <h1>Kinds of reflows</h1> + <ul> + <li>Initial - reflowee's first reflow must be of this type (reflower's responsibility).</li> + <li>Resize - reflowee gets a change in available space only. Similar to initial, except it can reoccur.</li> + <li>Incremental - has a reflow path (tree) where each node has a command with a target frame, <br>reflow command types are:</li> + <ul class=nested> + <li>dirty - something changed inside a target (e.g. it gains, loses children)</li> + <li>style changed - a target changed stylisticly (recall, size is a style property)</li> + <li>content changed - a target's content changed (e.g. a text run)</li> + <li>user defined - currently only used for fixed positioned frames </li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s8"> + <div class="nav"> + <a href="#s7"><</a> + <a href="#s9">></a> + </div> + <h1>Kinds of reflows</h1> + <ul> + <li>Incremental reflow (continued) + <ul class=nested> + <li>reflower not allowed to change available size of reflowee</li> + <li>reflow commands get coalesced to streamline processing</li> + </ul> + </li> + <li>Style change + <ul class=nested> + <li>a target changed stylistic if there is a target, otherwise every frame may need to respond</li> + <li>parent of target usually turns it into an incremental reflow with a style changed command type</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s9"> + <div class="nav"> + <a href="#s8"><</a> + <a href="#s10">></a> + </div> + <h1>Table Frames</h1> + <BR> + <table class="tree" width=90%> + <tr><td class=frame><td class=space style="width:2%"><td class=frame><td class=space style="width:2%"> + <td class=frame><td class=space><td class=frame></tr> + <tr><td><td><td class=frame><td> + <td>nsTableOuter Frame<td><td></tr> + <tr class="arrows"><td><td><td><td class=left-arrow>↙<td><td class=right-arrow>↘</tr> + <tr><td><td><td>nsTable<BR>Frame<td><td><td><td>nsTableCaption<BR>Frame</tr> + <tr class="arrows"><td><td class=left-arrow>↙<td><td class=right-arrow>↘<td><td><td class=center-arrow>↓</tr> + <tr><td>nsTableCol<BR>GroupFrame<td><td><TD><td>nsTableRow<BR>GroupFrame<td><td>nsBlockFrame</tr> + <tr class="arrows"><td class=center-arrow>↓<td><td><td><td class=center-arrow>↓</tr> + <tr><td>nsTableCol<BR>Frame<td><TD><TD><td>nsTableRow<BR>Frame</tr> + <tr class="arrows"><td><td><td><td><td class=center-arrow>↓</tr> + <tr><td><td><td><TD><td>nsTableCell<BR>Frame</tr> + <tr class="arrows"><td><td><td><td><td class=center-arrow>↓</tr> + <tr><td><td><td><TD><td>nsBlock<BR>Frame</tr> + </table> +</div> + +<div class="slide" id="s10"> + <div class="nav"> + <a href="#s9"><</a> + <a href="#s11">></a> + </div> + <h1>Table Reflow</h1> + <ul> + <li>table wrapper reflows table and caption (if present)</li> + <li>Table reflows row groups in multiple passes</li> + <ul class=nested> + <li>Pass 1 - unconstrained width, height and requests max elem width.</li> + <li>The table figures out the column widths (balances) given the style width constraints + on the table, col groups, cols, cells the preferred and max element sizes of the cells + (from the pass 1 reflow), and considers colspans</li> + <li>Pass 2 - cell widths are constrained by the column widths (heights are only + constrained in paginated mode).</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s11"> + <div class="nav"> + <a href="#s10"><</a> + <a href="#s12">></a> + </div> + <h1>Table Reflow</h1> + <ul> + <li>Table reflows row groups (continued)</li> + <ul class=nested> + <li>The row group figures out the row heights given the its style height constraints + its rows and cells and the actual heights of its rows and cells from the pass 2 reflow</li> + <li>If the table has a style height, it allocates extra height to its row groups, rows and cells.</li> + </ul> + </li> + <li>In each pass, row groups reflow rows which reflow cells which reflow cell blocks</li> + </ul> +</div> + +<div class="slide" id="s12"> + <div class="nav"> + <a href="#s11"><</a> + <a href="#s13">></a> + </div> + <h1>Table Reflow Example</h1> + <table width=100%> + <tr> + <td width=100%> + <pre style="font-size:.6em;"> +tblW 030176CC r=0 a=8940,UC c=0,0 cnt=429 + tbl 030178C4 r=0 a=8940,UC c=4470,UC cnt=430 + rowG 03017A7C r=0 a=UC,UC c=UC,UC cnt=431 + row 03017C08 r=0 a=UC,UC c=UC,UC cnt=432 + cell 03017DA8 r=0 a=UC,UC c=UC,UC cnt=433 + block 03017E08 r=0 a=UC,UC c=UC,UC cnt=434 + block 03017E08 d=870,300 me=480 + cell 03017DA8 d=930,360 me=540 + cell 0301A8CC r=0 a=UC,UC c=UC,UC cnt=436 + block 0301A92C r=0 a=UC,UC c=UC,UC cnt=437 + block 0301A92C d=1335,300 me=465 + cell 0301A8CC d=1395,360 me=525 + row 03017C08 d=UC,360 + rowG 03017A7C d=UC,360 + rowG 03017A7C r=2 a=4470,UC c=4470,UC cnt=442 + row 03017C08 r=2 a=4470,UC c=4470,UC cnt=443 + cell 03017DA8 r=2 a=1755,UC c=1695,UC cnt=444 + block 03017E08 r=2 a=1695,UC c=1695,UC cnt=445 + block 03017E08 d=1695,300 + cell 03017DA8 d=1755,360 + cell 0301A8CC r=2 a=2625,UC c=2565,UC cnt=446 + block 0301A92C r=2 a=2565,UC c=2565,UC cnt=447 + block 0301A92C d=2565,300 + cell 0301A8CC d=2625,360 + row 03017C08 d=4470,360 + rowG 03017A7C d=4470,360 + tbl 030178C4 d=4500,450 + tblW 030176CC d=4500,450 + + <a href="frame_reflow_debug.html">frame reflow debugging</a> gives instructions + for turning this on. + </pre> + </td> + <td> + <pre style="font-size:.7em;"> +<<span class=html>table</span> width=300> + <<span class=html>tr</span>> + <<span class=html>td</span>>foo<<span class=html>/td</span>> + <<span class=html>td</span>>bar zap<<span class=html>/td</span>> + <<span class=html>/tr</span>> +<<span class=html>/table</span>> + </pre> + <BR> + <BR> + <pre style="font-size:.7em;"> +Key: + + r = reflow reason, + 0 (initial), + 2 (resize) + a = avail w, h + c = computed w, h + d = desired w, h + me = max elem w + <pre> + </td> + </tr> + </table> +</div> + +<div class="slide" id="s13"> + <div class="nav"> + <a href="#s12"><</a> + <a href="#s14">></a> + </div> + <h1>Table reflow optimizations</h1> + <ul> + <li>If the table is already balanced, pass 1 constrains the width (like a normal pass 2) based on the current + column widths. The pass 2 will get skipped if the table doesn't need to rebalance. <!--<span class="comment">please clarify when can this happen</span>--></li> + <li>Nested table reflowed with an unconstrained width (i.e. an ancestor is doing a pass 1 reflow) + will only do a pass 1 reflow on its children</li> + <li>table wrapper caches last avail width and avoids reflowing children if resize reflow is the same as previous</li> + <li>Table caches max element, preferred widths in case they are requested and it isn't rebalanced</li> + <li>Cell caches prior avail width. if this doesn't change, the row may not have to reflow the cell</li> + </ul> + +</div> + +<div class="slide" id="s14"> + <div class="nav"> + <a href="#s13"><</a> + <a href="#s15">></a> + </div> + <h1>Table incremental reflow</h1> + <ul> + <li>table wrapper is a target when a caption is added or removed (dirty) or the table or caption margin + changes (style changed).</li> + <li>Caption is a target when it changes stylistically (style changed).</li> + <li>Table, row group, row, col group, col is a target when a child is added or removed (dirty) or it changes + stylistically (style changed). <!--<span class="comment">please show how the column style change is propagated + into the cell reflows as the cells are reflowed by their parent rows and not cols</span>--></li> + <li>In the dirty cases, a target posted the reflow command in AppendFrames, InsertFrames, or DeleteFrame.</li> + </ul> +</div> + +<div class="slide" id="s15"> + <div class="nav"> + <a href="#s14"><</a> + <a href="#s16">></a> + </div> + <h1>Table incremental reflow</h1> + <ul> + <li>In the style change cases where a target is between the table and the cell, the table is told to rebalance.</li> + <li>When a target is the cell or below and the cell changes size, the row tells the table so it can decide if + it needs to rebalance</li> + <li>When a target is inside the cell's block, the cell + requests max element, preferred sizes of its block in case they change</li> + <li>After the table reflows the row group(s) containing the targets, if it rebalances, it then does a pass 2 reflow.</li> + </ul> +</div> + +<div class="slide" id="s16"> + <div class="nav"> + <a href="#s15"><</a> + <a href="#s17">></a> + </div> + <h1>Special height reflow</h1> + <ul> + <li>When there is a % height frame inside a cell without a computed height</li> + <ul class=nested> + <li>the frame will never get a chance to size based on the final cell height</li> + <li>in paginated mode when there is a height on the table, the table doesn't allocate + extra height to rows until after it does a pass 2 reflow and then it is too late</li> + </ul> + </li> + <li>This can be fixed by doing a special 3rd pass reflow</li> + </ul> + </div> +</div> + +<div class="slide" id="s17"> + <div class="nav"> + <a href="#s16"><</a> + <a href="#s18">></a> + </div> + <h1>Special Reflow Example</h1> + <table width=100% style="text-align:left;"> + <tr> + <td> + <pre style="font-size:.7em; text-align:left;"> +<<span class=html>table</span> border=2 width=300> + <<span class=html>tr</span>> + <<span class=html>td</span>> + This cell's width is + constrained by the + table and image widths. + Its exact height is + hard to determine. + <<span class=html>/td</span>> + <<span class=html>td</span>> + <<span class=html>img</span> src=raptor.jpg + width=200 height=100%> + <<span class=html>/td</span>> + <<span class=html>/tr</span>> +<<span class=html>/table</span>> + </pre> + </td> + <td> + <table border=2 width=300> + <tr> + <td style="font-size:.7em;">This cell's width is constrained + by the table and image widths. <BR><BR>Its height + is hard to determine.<BR><BR> The image needs to be as high as the cell. + <td> + <!-- need ?raw=1 for lxr to cough up the image data, not a pretty page --> + <img src="raptor.jpg?raw=1" + width=200 height=100%> + </td> + </tr> + </table> + + </tr> + </table> +</div> + + +<div class="slide" id="s18"> + <div class="nav"> + <a href="#s17"><</a> + <a href="#s19">></a> + </div> + <h1>Special height reflow</h1> + <ul> + <li>The reflow state holds an observer and initiator</li> + <li>Observer</li> + <ul class=nested> + <li>is the table cell used as the height basis</li> + <li>set by frame without computed height in DidReflow</li> + <li>gives its block a computed height during 3rd pass</li> + <li>doesn't change height during 3rd pass</li> + </ul> + </li> + <li>Initiator</li> + <ul class=nested> + <li>is the table containing the observer</li> + <li>starts the 3rd pass reflow and sets a bit in the reflow state</li> + <li>gives its block a computed height during 3rd pass</li> + <li>could also be inside a cell which is an observer</li> + </ul> + </li> +</div> + +<div class="slide" id="s19"> + <div class="nav"> + <a href="#s18"><</a> + <a href="#s20">></a> + </div> + <h1>Special height reflow</h1> + <ul> + <li>Optimizations</li> + <ul class=nested> + <li>only frames needing 3rd pass actually get it</li> + <li>frames gettting a 3rd pass only get it once</li> + </ul> + </li> +</div> + +<div class="slide" id="s20"> + <div class="nav"> + <a href="#s19"><</a> + <a href="#s21">></a> + </div> + <h1>Intro to paginated reflow</h1> + <ul> + <li>When a reflowee's available height is constrained, it may not fit and need to either + split/continue on the next page, or start on the next page.</li> + <ul class=nested> + <li>If it can continue, it returns an incomplete status.</li> + <li>If it can't continue it returns a complete status.</li> + </ul> + </li> + <li>A continuation may also need to be continued</li> + <li>Continuations are linked together by prevInFlow and nextInFlow pointers </li> + </ul> +</div> + +<div class="slide" id="s21"> + <div class="nav"> + <a href="#s20"><</a> + <a href="#s22">></a> + </div> + <h1>Pagination Illustration</h1> + <table class=box style="height:500px"> + <tr><td class="title">nsSimplePageSequence</td></tr> + <tr> + <td class=box> + <table class=box style="height:40%;"> + <tr><td class=title>nsPageFrame</td></tr> + <tr> + <td class=box> + <table class=box style="height:100%;"> + <tr><td class=title>nsPageContentFrame</td></tr> + <tr> + <td class=box style="border-bottom: hidden"> + <table class=box style="height:100%; border-bottom:hidden"> + <tr><td class=title>areaFrame (html)</td></tr> + <tr> + <td class=box> + <table class=box style="height:100%; border-bottom:hidden"> + <tr><td class=title>blockFrame (body)</td></tr> + <tr> + <td class=box> + <table class=box style="height:100%; border-bottom:hidden"> + <tr><td class=title>nsTableWrapperFrame</td></tr> + <tr> + <td class=box></td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </tr> + </table> + </td> + </tr> + </table> + <BR> + <table class=box style="height:40%;"> + <tr> + <td class=box> + <table class=box style="height:100%;"> + <tr> + <td class=box style="border-top: hidden"> + <table class=box style="height:100%; border-top:hidden"> + <tr> + <td class=box> + <table class=box style="height:100%; border-top:hidden"> + <tr> + <td class=box> + <table class=box style="height:100%; border-top:hidden"> + <tr> + <td class=box></td> + </tr> + <tr><td class=title2>nsTableWrapperFrame</td></tr> + </table> + </td> + </tr> + <tr><td class=title2>blockFrame (body)</td></tr> + </table> + </td> + </tr> + <tr><td class=title2>areaFrame (html)</td></tr> + </table> + </tr> + <tr><td class=title2>nsPageContentFrame continued</td></tr> + </table> + </td> + </tr> + <tr><td class=title2>nsPageFrame continued</td></tr> + </table> + </td> + </tr> + </table> +</div> + +<div class="slide" id="s22"> + <div class="nav"> + <a href="#s21"><</a> + <a href="#s23">></a> + </div> + <h1>Intro to paginated reflow</h1> + <ul> + <li>The page sequence starts with one page and reflows it. If the page is incomplete then the page sequence + creates a continuation for the page and sets it as the page's next sibling (it is also the page's + nextInFlow).</li> + <li>The page was incomplete because the page content was incomplete because the doc root was incomplete</li> + <li>The doc root was incomplete because it contained lines that didn't fit (or if it was mapped to a table, + because the table didn't fit) becacause a line contained something that didn't fit, etc.</li> + </ul> +</div> + +<div class="slide" id="s23"> + <div class="nav"> + <a href="#s22"><</a> + <a href="#s24">></a> + </div> + <h1>Intro to paginated reflow</h1> + <ul> + <li>If the reflowee is incomplete, the reflower has the responsiblity to: + <ul> + <li>Create a continuation for the reflowee</li> + <li>Ensure that the continuation gets put in the frame hierarchy at the right place + and gets reflowed at the right time.</li> + <li>Typically, a reflower accomplishes this by putting the continuation (c) on an overflow + list which the reflower owns. When the reflower's continuation gets reflowed, it takes c + and its siblings as children and reflows them.</li> + </ul> + </li> + <li>If the reflowee is complete, truncated (it didn't fit), not at the top of page, + the reflower should put the reflowee on its overflow list and return an incomplete status.</li> + </ul> +</div> + +<div class="slide" id="s24"> + <div class="nav"> + <a href="#s23"><</a> + <a href="#s25">></a> + </div> + <h1>Intro to paginated reflow</h1> + <ul> + <li>Special assumptions + <ul> + <li>There are only initial and (possibly) resize reflows. Incremental + and style change reflows are not allowed.</li> + <li>Multiple resize reflows may be necessary (e.g. a child is truncated and gets reflowed on a + subsequent page) but they should not change the available width from the last time.</li> + <li>Multiple resize reflows may require special handling if a frame split previously. It may need + to "pull up" children from a continuation.</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s25"> + <div class="nav"> + <a href="#s24"><</a> + <a href="#s26">></a> + </div> + <h1>Table paginated reflow</h1> + <ul> + <li>The block containing the table wrapper reflows it. If it is incomplete, the block will + <ul> + <li>create a continuation for the table wrapper (which also creates a continuation for the table).</li> + <li>put the continuation on a new line and place that line on its overflow lines property.</li> + </ul> + </li> + <li>The table wrapper reflows the table and just returns the status of the table.</li> + <li>The table does a pass 1 reflow and balances. If it is incomplete,</li> + <ul> + <li>it will become the first-in-flow</li> + <li>it will be the only frame among its continuations to ever balance or calc the cell map, and it only + does this once</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s26"> + <div class="nav"> + <a href="#s25"><</a> + <a href="#s27">></a> + </div> + <h1>Table paginated reflow</h1> + <ul> + <li>The table does a pass 2 reflow constraining both avail heights and widths. If a row group is incomplete, the table + <ul> + <li>creates a continuation for the row group</li> + <li>puts the continuation in its overflow frames property</li> + </ul> + </li> + <li>What follows only applies during the pass 2 reflow.</li> + <li>The row group</li> + <ul> + <li>reflows all of its rows with unconstrained heights and calculates the row heights,</li> + <li>figures out which row falls on a page boundary and reflows it with a constrained height. If there + will be a pass 3 reflow then this should (bug) happen at that time instead.</li> + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s27"> + <div class="nav"> + <a href="#s26"><</a> + <a href="#s28">></a> + </div> + <h1>Table paginated reflow</h1> + <ul> + <li>The row group (continued)</li> + <ul> + <li>creates a continuation for the incomplete row (which also creates continuations for all of its cells + and all of the cell blocks)</li> + <li>puts the continuation in its overflow frames property. If the row was truncated and not top of page, + the row is put in the overflow frames property. + </ul> + </li> + </ul> +</div> + +<div class="slide" id="s28"> + <div class="nav"> + <a href="#s27"><</a> + <a href="#s0">></a> + </div> + <h1>Table paginated reflow</h1> + <ul> + <li>The row and cells (getting the constrained height reflow) just reflow their children with a constrained height. + They don't need an overflow list for continued children because the continuations were created when the + row group created the row's continutation.</li> + <li>A cell is incomplete because its block is incomplete. The block uses the overflow lines mechanism + (mentioned above) for its continued children</li> + </li> + <li>There are two splitting scenarios for a table + <ul> + <li>An incomplete cells block causes the cell, row, row group, table, table wrapper to + be incomplete</li> + <li>A truncated row or a row that started too far down the page causes the row group, + table, table wrapper to be incomplete.</li> + </ul> + </li> + </ul> +</div> + + +</body> +</html> |