From 76dc813a2c572a2e31f23a6b2fd428d8c3653061 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Mon, 4 Jan 1999 04:54:33 +0000 Subject: [PATCH] Changed nsISpaceManager interface to conform to XP-COM conventions on return values --- layout/base/public/nsISpaceManager.h | 94 +++++----- layout/base/src/nsSpaceManager.cpp | 225 ++++++++++++++++------- layout/base/src/nsSpaceManager.h | 34 ++-- layout/base/tests/TestSpaceManager.cpp | 136 ++++++++++---- layout/generic/nsAreaFrame.cpp | 3 +- layout/generic/nsBlockBandData.cpp | 2 +- layout/generic/nsSpaceManager.cpp | 225 ++++++++++++++++------- layout/generic/nsSpaceManager.h | 34 ++-- layout/html/base/src/nsAreaFrame.cpp | 3 +- layout/html/base/src/nsBlockBandData.cpp | 2 +- 10 files changed, 495 insertions(+), 263 deletions(-) diff --git a/layout/base/public/nsISpaceManager.h b/layout/base/public/nsISpaceManager.h index 0aa92f03701..eb994e9ed31 100644 --- a/layout/base/public/nsISpaceManager.h +++ b/layout/base/public/nsISpaceManager.h @@ -53,7 +53,7 @@ struct nsBandTrapezoid { }; // Get the height of the trapezoid - nscoord GetHeight() {return yBottom - yTop;} + nscoord GetHeight() const {return yBottom - yTop;} // Get the bouding rect of the trapezoid void GetRect(nsRect& aRect) const; @@ -67,9 +67,9 @@ struct nsBandTrapezoid { * @see #GetBandData() */ struct nsBandData { - PRInt32 count; // 'out' parameter. Actual number of trapezoids in the band data - PRInt32 size; // 'in' parameter. The size of the array - nsBandTrapezoid* trapezoids; // 'out' parameter. Array of length 'size' + PRInt32 count; // [out] actual number of trapezoids in the band data + PRInt32 size; // [in] the size of the array (number of trapezoids) + nsBandTrapezoid* trapezoids; // [out] array of length 'size' }; /** @@ -84,27 +84,26 @@ public: * 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 additional interfaces such - * as nsIAnchoredItems + * You can use QueryInterface() on this frame to get any additional interfaces */ - virtual nsIFrame* GetFrame() const = 0; + NS_IMETHOD GetFrame(nsIFrame*& aFrame) const = 0; /** * Translate the current origin by the specified (dx, dy). This creates a new * local coordinate space relative to the current coordinate space. */ - virtual void Translate(nscoord aDx, nscoord aDy) = 0; + NS_IMETHOD Translate(nscoord aDx, nscoord aDy) = 0; /** * Returns the current translation from local coordinate space to world * coordinate space. This represents the accumulated calls to Translate(). */ - virtual void GetTranslation(nscoord& aX, nscoord& aY) const = 0; + NS_IMETHOD GetTranslation(nscoord& aX, nscoord& aY) const = 0; /** * Returns the y-most of the bottommost band, or 0 if there are no bands. */ - virtual nscoord YMost() const = 0; + NS_IMETHOD YMost(nscoord& aYMost) const = 0; /** * Returns a band starting at the specified y-offset. The band data indicates @@ -113,74 +112,77 @@ public: * The band data that is returned is in the coordinate space of the local * coordinate system. * - * The local coordinate space origin together with the max size describe a - * rectangle that's used to clip the underlying band of available space. + * 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 out parameter used to return the list of - * trapezoids that describe the available space and the unavailable - * space. - * @returns the number of trapezoids in the band data. If the band data is - * not large enough, returns the negative of the number of - * trapezoids needed + * @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 */ - virtual PRInt32 GetBandData(nscoord aYOffset, - const nsSize& aMaxSize, - nsBandData& aBandData) const = 0; + NS_IMETHOD GetBandData(nscoord aYOffset, + const nsSize& aMaxSize, + nsBandData& aBandData) const = 0; /** * Add a rectangular region of unavailable space. The space is relative to * the local coordinate system. * - * The region is tagged with a frame, which is used to identify the region. - * The frame must not be NULL + * The region is tagged with a frame. When translated to world coordinates + * the origin of the rect MUST be within the defined coordinate space, i.e. + * the x-offset and y-offset must be >= 0 * - * Returns PR_TRUE if successful and PR_FALSE otherwise, e.g. there is already - * a region tagged with aFrame - * - * When translated to world coordinates the origin MUST be within the defined - * coordinate space, i.e. the x-offset and y-offset must be >= 0 + * @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 + * NS_ERROR_INVALID_ARG if the rect translated to world coordinates + * is not within the defined coordinate space */ - virtual PRBool AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace) = 0; + NS_IMETHOD AddRectRegion(nsIFrame* aFrame, + const nsRect& aUnavailableSpace) = 0; /** - * 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 + * 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 PR_TRUE if successful and PR_FALSE otherwise, e.g. there is no region - * tagged with aFrame, or the new offset when translated to world coordinates is - * outside the defined coordinate space + * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region + * tagged with aFrame, and NS_ERROR_FAILURE if the new offset when translated + * to world coordinates is outside the defined coordinate space */ enum AffectedEdge {LeftEdge, RightEdge}; - virtual PRBool ResizeRectRegion(nsIFrame* aFrame, - nscoord aDeltaWidth, - nscoord aDeltaHeight, - AffectedEdge aEdge = RightEdge) = 0; + NS_IMETHOD ResizeRectRegion(nsIFrame* aFrame, + nscoord aDeltaWidth, + nscoord aDeltaHeight, + AffectedEdge aEdge = RightEdge) = 0; /** * Offset the region associated with aFrame by the specified amount. * - * Returns PR_TRUE if successful and PR_FALSE otherwise, e.g. there is no region - * tagged with aFrame, or the new offset when translated to world coordinates - * is outside the defined coordinate space + * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region + * tagged with aFrame, and NS_ERROR_FAILURE if the new offset when translated + * to world coordinates is outside the defined coordinate space */ - virtual PRBool OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy) = 0; + NS_IMETHOD OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy) = 0; /** * Remove the region associated with aFrane. * - * Returns PR_TRUE if successful and PR_FALSE otherwise, e.g. there is no region + * Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region * tagged with aFrame */ - virtual PRBool RemoveRegion(nsIFrame* aFrame) = 0; + NS_IMETHOD RemoveRegion(nsIFrame* aFrame) = 0; /** * Clears the list of regions representing the unavailable space. */ - virtual void ClearRegions() = 0; + NS_IMETHOD ClearRegions() = 0; }; void inline nsBandTrapezoid::GetRect(nsRect& aRect) const diff --git a/layout/base/src/nsSpaceManager.cpp b/layout/base/src/nsSpaceManager.cpp index 04edb3927bb..44e560746cd 100644 --- a/layout/base/src/nsSpaceManager.cpp +++ b/layout/base/src/nsSpaceManager.cpp @@ -50,7 +50,8 @@ nsSpaceManager::BandList::BandList() numFrames = 0; } -void nsSpaceManager::BandList::Clear() +void +nsSpaceManager::BandList::Clear() { if (!IsEmpty()) { BandRect* bandRect = Head(); @@ -66,7 +67,6 @@ void nsSpaceManager::BandList::Clear() } } - ///////////////////////////////////////////////////////////////////////////// // nsSpaceManager @@ -78,7 +78,8 @@ nsSpaceManager::nsSpaceManager(nsIFrame* aFrame) mFrameInfoMap = nsnull; } -void nsSpaceManager::ClearFrameInfo() +void +nsSpaceManager::ClearFrameInfo() { if (nsnull != mFrameInfoMap) { PL_HashTableEnumerateEntries(mFrameInfoMap, NS_RemoveFrameInfoEntries, 0); @@ -95,36 +96,41 @@ nsSpaceManager::~nsSpaceManager() NS_IMPL_ISUPPORTS(nsSpaceManager, kISpaceManagerIID); -nsIFrame* nsSpaceManager::GetFrame() const +NS_IMETHODIMP +nsSpaceManager::GetFrame(nsIFrame*& aFrame) const { - return mFrame; + aFrame = mFrame; + return NS_OK; } -void nsSpaceManager::Translate(nscoord aDx, nscoord aDy) +NS_IMETHODIMP +nsSpaceManager::Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; + return NS_OK; } -void nsSpaceManager::GetTranslation(nscoord& aX, nscoord& aY) const +NS_IMETHODIMP +nsSpaceManager::GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; + return NS_OK; } -nscoord nsSpaceManager::YMost() const +NS_IMETHODIMP +nsSpaceManager::YMost(nscoord& aYMost) const { - nscoord yMost; - if (mBandList.IsEmpty()) { - yMost = 0; + aYMost = 0; } else { BandRect* lastRect = mBandList.Tail(); - yMost = lastRect->bottom; + aYMost = lastRect->bottom; } - return yMost; + return NS_OK; } /** @@ -136,10 +142,11 @@ nscoord nsSpaceManager::YMost() const * @param aMaxSize the size to use to constrain the band data * @param aAvailableBand */ -PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, - nscoord aY, - const nsSize& aMaxSize, - nsBandData& aBandData) const +nsresult +nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, + nscoord aY, + const nsSize& aMaxSize, + nsBandData& aBandData) const { nscoord topOfBand = aBand->top; nscoord localY = aY - mY; @@ -171,6 +178,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, if (aBand->left > left) { // The rect is to the right of our current left coordinate, so we've // found some available space + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count += 2 * aBand->Length() + 2; // estimate the number needed + return NS_ERROR_FAILURE; + } trapezoid->state = nsBandTrapezoid::Available; trapezoid->frame = nsnull; @@ -184,6 +196,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, } // The rect represents unavailable space, so add another trapezoid + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count += 2 * aBand->Length() + 1; // estimate the number needed + return NS_ERROR_FAILURE; + } if (1 == aBand->numFrames) { trapezoid->state = nsBandTrapezoid::Occupied; trapezoid->frame = aBand->frame; @@ -218,6 +235,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, // No more rects left in the band. If we haven't yet reached the right edge, // then all the remaining space is available if (left < rightEdge) { + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count++; + return NS_ERROR_FAILURE; + } trapezoid->state = nsBandTrapezoid::Available; trapezoid->frame = nsnull; @@ -227,19 +249,25 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, aBandData.count++; } - return aBandData.count; + return NS_OK; } -PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, - const nsSize& aMaxSize, - nsBandData& aBandData) const +NS_IMETHODIMP +nsSpaceManager::GetBandData(nscoord aYOffset, + const nsSize& aMaxSize, + nsBandData& aBandData) const { + NS_PRECONDITION(aBandData.size >= 1, "bad band data"); + nsresult result = NS_OK; + // Convert the y-offset to world coordinates nscoord y = mY + aYOffset; // If there are no unavailable rects or the offset is below the bottommost // band, then all the space is available - if (y >= YMost()) { + nscoord yMost; + YMost(yMost); + if (y >= yMost) { // All the requested space is available aBandData.count = 1; aBandData.trapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, aMaxSize.height); @@ -273,7 +301,7 @@ PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, } NS_POSTCONDITION(aBandData.count > 0, "unexpected band data count"); - return aBandData.count; + return result; } /** @@ -282,7 +310,8 @@ PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, * @param aBandRect A rect within the band * @returns The start of the next band, or nsnull of this is the last band. */ -nsSpaceManager::BandRect* nsSpaceManager::GetNextBand(const BandRect* aBandRect) const +nsSpaceManager::BandRect* +nsSpaceManager::GetNextBand(const BandRect* aBandRect) const { nscoord topOfBand = aBandRect->top; @@ -308,7 +337,8 @@ nsSpaceManager::BandRect* nsSpaceManager::GetNextBand(const BandRect* aBandRect) * @param aBottom where to split the band. This becomes the bottom of the top * part */ -void nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) +void +nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) { NS_PRECONDITION(aBottom < aBandRect->bottom, "bad height"); nscoord topOfBand = aBandRect->top; @@ -330,7 +360,8 @@ void nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) } } -PRBool nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) +PRBool +nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) { PRBool result; nscoord topOfBand = aBand->top; @@ -384,7 +415,8 @@ PRBool nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) * * If the two bands are joined, the previous band is the the band that's deleted */ -PRBool nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) +PRBool +nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) { if (CanJoinBands(aBand, aPrevBand)) { BandRect* startOfNextBand = aBand; @@ -415,8 +447,8 @@ PRBool nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) * @param aBand the first rect in the band * @param aBandRect the band rect to add to the band */ -void nsSpaceManager::AddRectToBand(BandRect* aBand, - BandRect* aBandRect) +void +nsSpaceManager::AddRectToBand(BandRect* aBand, BandRect* aBandRect) { NS_PRECONDITION((aBand->top == aBandRect->top) && (aBand->bottom == aBandRect->bottom), "bad band"); @@ -580,11 +612,14 @@ void nsSpaceManager::AddRectToBand(BandRect* aBand, // | R | // +-----+ // -void nsSpaceManager::InsertBandRect(BandRect* aBandRect) +void +nsSpaceManager::InsertBandRect(BandRect* aBandRect) { // If there are no existing bands or this rect is below the bottommost // band, then add a new band - if (aBandRect->top >= YMost()) { + nscoord yMost; + YMost(yMost); + if (aBandRect->top >= yMost) { mBandList.Append(aBandRect); return; } @@ -673,7 +708,8 @@ void nsSpaceManager::InsertBandRect(BandRect* aBandRect) } } -PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace) +NS_IMETHODIMP +nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace) { NS_PRECONDITION(nsnull != aFrame, "null frame"); @@ -682,7 +718,7 @@ PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailabl if (nsnull != frameInfo) { NS_WARNING("aFrame is already associated with a region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } // Convert the frame to world coordinates @@ -692,39 +728,47 @@ PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailabl // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset for rect region"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } // Create a frame info structure frameInfo = CreateFrameInfo(aFrame, rect); + if (nsnull == frameInfo) { + return NS_ERROR_OUT_OF_MEMORY; + } // Is the rect empty? if (aUnavailableSpace.IsEmpty()) { // The rect doesn't consume any space, so don't add any band data - return PR_TRUE; + return NS_OK; } // Allocate a band rect BandRect* bandRect = new BandRect(rect.x, rect.y, rect.XMost(), rect.YMost(), aFrame); + if (nsnull == bandRect) { + return NS_ERROR_OUT_OF_MEMORY; + } // Insert the band rect InsertBandRect(bandRect); - return PR_TRUE; + return NS_OK; } -PRBool nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, - nscoord aDeltaWidth, - nscoord aDeltaHeight, - AffectedEdge aEdge) +NS_IMETHODIMP +nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, + nscoord aDeltaWidth, + nscoord aDeltaHeight, + AffectedEdge aEdge) { // Get the frame info associated with with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } + // Compute new rect nsRect rect(frameInfo->rect); rect.SizeBy(aDeltaWidth, aDeltaHeight); if (aEdge == LeftEdge) { @@ -734,51 +778,55 @@ PRBool nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset when resizing rect region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } - // For the time being just remove it and add it back in + // For the time being just remove it and add it back in. Because + // AddRectRegion() operates relative to the local coordinate space, + // translate from world coordinates to the local coordinate space + rect.MoveBy(-mX, -mY); RemoveRegion(aFrame); return AddRectRegion(aFrame, rect); } -PRBool nsSpaceManager::OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy) +NS_IMETHODIMP +nsSpaceManager::OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy) { // Get the frame info associated with with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } - // Compute new rect for the region; note that we have to translate - // from the global coordinate system (frameInfo->rect) to our - // current local coordinate system before adding the rect region - // again (since AddRectRegion operates relative to the current - // translation). + // Compute new rect nsRect rect(frameInfo->rect); - rect.MoveBy(-mX + aDx, -mY + aDy); + rect.MoveBy(aDx, aDy); // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset when offseting rect region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } - // For the time being just remove it and add it back in + // For the time being just remove it and add it back in. Because + // AddRectRegion() operates relative to the local coordinate space, + // translate from world coordinates to the local coordinate space + rect.MoveBy(-mX, -mY); RemoveRegion(aFrame); return AddRectRegion(aFrame, rect); } -PRBool nsSpaceManager::RemoveRegion(nsIFrame* aFrame) +NS_IMETHODIMP +nsSpaceManager::RemoveRegion(nsIFrame* aFrame) { // Get the frame info associated with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } if (!frameInfo->rect.IsEmpty()) { @@ -871,16 +919,19 @@ PRBool nsSpaceManager::RemoveRegion(nsIFrame* aFrame) } DestroyFrameInfo(frameInfo); - return PR_TRUE; + return NS_OK; } -void nsSpaceManager::ClearRegions() +NS_IMETHODIMP +nsSpaceManager::ClearRegions() { ClearFrameInfo(); mBandList.Clear(); + return NS_OK; } -nsSpaceManager::FrameInfo* nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) +nsSpaceManager::FrameInfo* +nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) { FrameInfo* result = nsnull; @@ -891,21 +942,26 @@ nsSpaceManager::FrameInfo* nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) return result; } -nsSpaceManager::FrameInfo* nsSpaceManager::CreateFrameInfo(nsIFrame* aFrame, - const nsRect& aRect) +nsSpaceManager::FrameInfo* +nsSpaceManager::CreateFrameInfo(nsIFrame* aFrame, const nsRect& aRect) { if (nsnull == mFrameInfoMap) { mFrameInfoMap = PL_NewHashTable(17, NS_HashNumber, PL_CompareValues, PL_CompareValues, nsnull, nsnull); + if (nsnull == mFrameInfoMap) { + return nsnull; + } } FrameInfo* frameInfo = new FrameInfo(aFrame, aRect); - - PL_HashTableAdd(mFrameInfoMap, (const void*)aFrame, frameInfo); + if (nsnull != frameInfo) { + PL_HashTableAdd(mFrameInfoMap, (const void*)aFrame, frameInfo); + } return frameInfo; } -void nsSpaceManager::DestroyFrameInfo(FrameInfo* aFrameInfo) +void +nsSpaceManager::DestroyFrameInfo(FrameInfo* aFrameInfo) { PL_HashTableRemove(mFrameInfoMap, (const void*)aFrameInfo->frame); delete aFrameInfo; @@ -958,7 +1014,8 @@ nsSpaceManager::BandRect::~BandRect() } } -nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitVertically(nscoord aBottom) +nsSpaceManager::BandRect* +nsSpaceManager::BandRect::SplitVertically(nscoord aBottom) { NS_PRECONDITION((aBottom > top) && (aBottom < bottom), "bad argument"); @@ -973,11 +1030,11 @@ nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitVertically(nscoord aBot // This band rect becomes the top part, so adjust the bottom edge bottom = aBottom; - return bottomBandRect; } -nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitHorizontally(nscoord aRight) +nsSpaceManager::BandRect* +nsSpaceManager::BandRect::SplitHorizontally(nscoord aRight) { NS_PRECONDITION((aRight > left) && (aRight < right), "bad argument"); @@ -992,11 +1049,11 @@ nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitHorizontally(nscoord aR // This band rect becomes the left part, so adjust the right edge right = aRight; - return rightBandRect; } -PRBool nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const +PRBool +nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const { PRBool result; @@ -1019,7 +1076,8 @@ PRBool nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const return result; } -void nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) +void +nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) { if (1 == numFrames) { nsIFrame* f = frame; @@ -1032,7 +1090,8 @@ void nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) NS_POSTCONDITION(frames->Count() == numFrames, "bad frame count"); } -void nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) +void +nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) { NS_PRECONDITION(numFrames > 1, "only one frame"); frames->RemoveElement((void*)aFrame); @@ -1046,7 +1105,8 @@ void nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) } } -PRBool nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) const +PRBool +nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) const { PRBool result; @@ -1073,3 +1133,26 @@ PRBool nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) con return result; } + +/** + * Internal helper function that counts the number of rects in this band + * including the current band rect + */ +PRInt32 +nsSpaceManager::BandRect::Length() const +{ + nscoord topOfBand = top; + PRInt32 len = 1; + BandRect* bandRect = Next(); + + // Because there's a header cell we know we'll either find the next band + // (which has a different y-offset) or the header cell which has an invalid + // y-offset + while (bandRect->top == top) { + len++; + bandRect = bandRect->Next(); + } + + return len; +} + diff --git a/layout/base/src/nsSpaceManager.h b/layout/base/src/nsSpaceManager.h index d09eece1719..676c2ededbb 100644 --- a/layout/base/src/nsSpaceManager.h +++ b/layout/base/src/nsSpaceManager.h @@ -35,25 +35,26 @@ public: NS_DECL_ISUPPORTS // nsISpaceManager - virtual nsIFrame* GetFrame() const; + NS_IMETHOD GetFrame(nsIFrame*& aFrame) const; - virtual void Translate(nscoord aDx, nscoord aDy); - virtual void GetTranslation(nscoord& aX, nscoord& aY) const; - virtual nscoord YMost() const; + NS_IMETHOD Translate(nscoord aDx, nscoord aDy); + NS_IMETHOD GetTranslation(nscoord& aX, nscoord& aY) const; + NS_IMETHOD YMost(nscoord& aYMost) const; - virtual PRInt32 GetBandData(nscoord aYOffset, - const nsSize& aMaxSize, - nsBandData& aBandData) const; + NS_IMETHOD GetBandData(nscoord aYOffset, + const nsSize& aMaxSize, + nsBandData& aBandData) const; - virtual PRBool AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace); - virtual PRBool ResizeRectRegion(nsIFrame* aFrame, - nscoord aDeltaWidth, - nscoord aDeltaHeight, - AffectedEdge aEdge); - virtual PRBool OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy); - virtual PRBool RemoveRegion(nsIFrame* aFrame); + NS_IMETHOD AddRectRegion(nsIFrame* aFrame, + const nsRect& aUnavailableSpace); + NS_IMETHOD ResizeRectRegion(nsIFrame* aFrame, + nscoord aDeltaWidth, + nscoord aDeltaHeight, + AffectedEdge aEdge); + NS_IMETHOD OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy); + NS_IMETHOD RemoveRegion(nsIFrame* aFrame); - virtual void ClearRegions(); + NS_IMETHOD ClearRegions(); protected: // Structure that maintains information about the region associated @@ -109,6 +110,7 @@ protected: void AddFrame(const nsIFrame*); void RemoveFrame(const nsIFrame*); PRBool HasSameFrameList(const BandRect* aBandRect) const; + PRInt32 Length() const; }; // Circular linked list of band rects @@ -147,7 +149,7 @@ protected: void AddRectToBand(BandRect* aBand, BandRect* aBandRect); void InsertBandRect(BandRect* aBandRect); - PRInt32 GetBandAvailableSpace(const BandRect* aBand, + nsresult GetBandAvailableSpace(const BandRect* aBand, nscoord aY, const nsSize& aMaxSize, nsBandData& aAvailableSpace) const; diff --git a/layout/base/tests/TestSpaceManager.cpp b/layout/base/tests/TestSpaceManager.cpp index 94331a0bd74..cbf76e58a9d 100644 --- a/layout/base/tests/TestSpaceManager.cpp +++ b/layout/base/tests/TestSpaceManager.cpp @@ -31,6 +31,7 @@ public: PRBool TestRemoveRegion(); PRBool TestOffsetRegion(); PRBool TestResizeRectRegion(); + PRBool TestGetBandData(); protected: struct BandInfo { @@ -92,8 +93,8 @@ void MySpaceManager::GetBandsInfo(BandsInfo& aBandsInfo) // 4. adding a new band below the bottommost band PRBool MySpaceManager::TestAddBand() { - PRBool status; BandsInfo bandsInfo; + nsresult status; // Clear any existing regions ClearRegions(); @@ -103,8 +104,8 @@ PRBool MySpaceManager::TestAddBand() // #1. Add a rect region. Verify the return status, and that a band rect is // added status = AddRectRegion((nsIFrame*)0x01, nsRect(10, 100, 100, 100)); - if (PR_FALSE == status) { - printf("TestAddBand: add returned false (#1)\n"); + if (NS_FAILED(status)) { + printf("TestAddBand: add failed (#1)\n"); return PR_FALSE; } GetBandsInfo(bandsInfo); @@ -120,7 +121,7 @@ PRBool MySpaceManager::TestAddBand() ///////////////////////////////////////////////////////////////////////////// // #2. Add another band rect completely above the first band rect status = AddRectRegion((nsIFrame*)0x02, nsRect(10, 10, 100, 20)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 2) { printf("TestAddBand: wrong number of bands (#2): %i\n", bandsInfo.numBands); @@ -135,7 +136,7 @@ PRBool MySpaceManager::TestAddBand() ///////////////////////////////////////////////////////////////////////////// // #3. Now insert a new band between the two existing bands status = AddRectRegion((nsIFrame*)0x03, nsRect(10, 40, 100, 30)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 3) { printf("TestAddBand: wrong number of bands (#3): %i\n", bandsInfo.numBands); @@ -151,7 +152,7 @@ PRBool MySpaceManager::TestAddBand() ///////////////////////////////////////////////////////////////////////////// // #4. Append a new bottommost band status = AddRectRegion((nsIFrame*)0x04, nsRect(10, 210, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 4) { printf("TestAddBand: wrong number of bands (#4): %i\n", bandsInfo.numBands); @@ -177,8 +178,8 @@ PRBool MySpaceManager::TestAddBand() // 3. Adding a rect that contains an existing band PRBool MySpaceManager::TestAddBandOverlap() { - PRBool status; BandsInfo bandsInfo; + nsresult status; // Clear any existing regions ClearRegions(); @@ -186,12 +187,12 @@ PRBool MySpaceManager::TestAddBandOverlap() // Add a new band status = AddRectRegion((nsIFrame*)0x01, nsRect(100, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); ///////////////////////////////////////////////////////////////////////////// // #1. Add a rect region that's above and partially overlaps an existing band status = AddRectRegion((nsIFrame*)0x02, nsRect(10, 50, 50, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 3) { printf("TestAddBandOverlap: wrong number of bands (#1): %i\n", bandsInfo.numBands); @@ -213,7 +214,7 @@ PRBool MySpaceManager::TestAddBandOverlap() ///////////////////////////////////////////////////////////////////////////// // #2. Add a rect region that's contained by the first band status = AddRectRegion((nsIFrame*)0x03, nsRect(200, 60, 50, 10)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 5) { printf("TestAddBandOverlap: wrong number of bands (#2): %i\n", bandsInfo.numBands); @@ -239,7 +240,7 @@ PRBool MySpaceManager::TestAddBandOverlap() ///////////////////////////////////////////////////////////////////////////// // #3. Add a rect that overlaps and is below an existing band status = AddRectRegion((nsIFrame*)0x04, nsRect(200, 175, 50, 50)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 7) { printf("TestAddBandOverlap: wrong number of bands (#3): %i\n", bandsInfo.numBands); @@ -270,11 +271,11 @@ PRBool MySpaceManager::TestAddBandOverlap() // #4. Now test adding a rect that contains an existing band ClearRegions(); status = AddRectRegion((nsIFrame*)0x01, nsRect(100, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); // Now add a rect that contains the existing band vertically status = AddRectRegion((nsIFrame*)0x02, nsRect(200, 50, 100, 200)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 3) { @@ -308,22 +309,22 @@ PRBool MySpaceManager::TestAddBandOverlap() // 6. Add a new rect that completely contains an existing rect PRBool MySpaceManager::TestAddRectToBand() { - PRBool status; BandsInfo bandsInfo; BandRect* bandRect; - + nsresult status; + // Clear any existing regions ClearRegions(); NS_ASSERTION(mBandList.IsEmpty(), "clear regions failed"); // Add a new band status = AddRectRegion((nsIFrame*)0x01, nsRect(100, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); ///////////////////////////////////////////////////////////////////////////// // #1. Add a rect region that's to the left of the existing rect status = AddRectRegion((nsIFrame*)0x02, nsRect(10, 100, 50, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 1) { printf("TestAddRectToBand: wrong number of bands (#1): %i\n", bandsInfo.numBands); @@ -347,7 +348,7 @@ PRBool MySpaceManager::TestAddRectToBand() ///////////////////////////////////////////////////////////////////////////// // #2. Add a rect region that's to the right of the rightmost rect status = AddRectRegion((nsIFrame*)0x03, nsRect(250, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); NS_ASSERTION(bandsInfo.numBands == 1, "wrong number of bands"); if (bandsInfo.bands[0].numRects != 3) { @@ -374,7 +375,7 @@ PRBool MySpaceManager::TestAddRectToBand() // #3. Add a rect region that's to the left of an existing rect and that // overlaps the rect status = AddRectRegion((nsIFrame*)0x04, nsRect(80, 100, 40, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); NS_ASSERTION(bandsInfo.numBands == 1, "wrong number of bands"); if (bandsInfo.bands[0].numRects != 5) { @@ -414,7 +415,7 @@ PRBool MySpaceManager::TestAddRectToBand() // #4. Add a rect region that's to the right of an existing rect and that // overlaps the rect status = AddRectRegion((nsIFrame*)0x05, nsRect(50, 100, 20, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); NS_ASSERTION(bandsInfo.numBands == 1, "wrong number of bands"); if (bandsInfo.bands[0].numRects != 7) { @@ -450,7 +451,7 @@ PRBool MySpaceManager::TestAddRectToBand() // #5. Add a new rect over top of an existing rect (existing rect contains // the new rect) status = AddRectRegion((nsIFrame*)0x06, nsRect(20, 100, 20, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); NS_ASSERTION(bandsInfo.numBands == 1, "wrong number of bands"); if (bandsInfo.bands[0].numRects != 9) { @@ -484,7 +485,7 @@ PRBool MySpaceManager::TestAddRectToBand() ///////////////////////////////////////////////////////////////////////////// // #6. Add a new rect that completely contains an existing rect status = AddRectRegion((nsIFrame*)0x07, nsRect(0, 100, 30, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); NS_ASSERTION(bandsInfo.numBands == 1, "wrong number of bands"); if (bandsInfo.bands[0].numRects != 11) { @@ -533,10 +534,10 @@ PRBool MySpaceManager::TestAddRectToBand() // 3. removing a band rect and making sure adjacent bands are combined PRBool MySpaceManager::TestRemoveRegion() { - PRBool status; BandsInfo bandsInfo; BandRect* bandRect; - + nsresult status; + // Clear any existing regions ClearRegions(); NS_ASSERTION(mBandList.IsEmpty(), "clear regions failed"); @@ -544,9 +545,9 @@ PRBool MySpaceManager::TestRemoveRegion() ///////////////////////////////////////////////////////////////////////////// // #1. A simple test of removing the one and only band rect status = AddRectRegion((nsIFrame*)0x01, nsRect(10, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); status = RemoveRegion((nsIFrame*)0x01); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.numBands != 0) { printf("TestRemoveRegion: wrong number of bands (#1): %i\n", bandsInfo.numBands); @@ -557,9 +558,9 @@ PRBool MySpaceManager::TestRemoveRegion() // #2. Test removing a rect that's shared. Make sure adjacent rects are // coalesced status = AddRectRegion((nsIFrame*)0x01, nsRect(10, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); status = AddRectRegion((nsIFrame*)0x02, nsRect(40, 100, 20, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); // Verify there are three rects in the band GetBandsInfo(bandsInfo); @@ -570,7 +571,7 @@ PRBool MySpaceManager::TestRemoveRegion() // Remove the region associated with the second frame status = RemoveRegion((nsIFrame*)0x02); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.bands[0].numRects != 1) { printf("TestRemoveRegion: failed to coalesce adjacent rects (#2)\n"); @@ -585,7 +586,7 @@ PRBool MySpaceManager::TestRemoveRegion() ///////////////////////////////////////////////////////////////////////////// // #3. Test removing a band rect and making sure adjacent bands are combined status = AddRectRegion((nsIFrame*)0x02, nsRect(10, 140, 20, 20)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); // Verify there are three bands and that each band has three rects GetBandsInfo(bandsInfo); @@ -608,7 +609,7 @@ PRBool MySpaceManager::TestRemoveRegion() // Remove the region associated with the second frame status = RemoveRegion((nsIFrame*)0x02); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); GetBandsInfo(bandsInfo); if (bandsInfo.bands[0].numRects != 1) { printf("TestRemoveRegion: failed to coalesce adjacent rects (#3)\n"); @@ -629,9 +630,9 @@ PRBool MySpaceManager::TestRemoveRegion() // 1. simple test of offseting the one and only band rect PRBool MySpaceManager::TestOffsetRegion() { - PRBool status; BandsInfo bandsInfo; BandRect* bandRect; + nsresult status; // Clear any existing regions ClearRegions(); @@ -640,9 +641,9 @@ PRBool MySpaceManager::TestOffsetRegion() ///////////////////////////////////////////////////////////////////////////// // #1. A simple test of offseting the one and only band rect status = AddRectRegion((nsIFrame*)0x01, nsRect(10, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); status = OffsetRegion((nsIFrame*)0x01, 50, 50); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); // Verify there is one band with one rect GetBandsInfo(bandsInfo); @@ -671,9 +672,9 @@ PRBool MySpaceManager::TestOffsetRegion() // 1. simple test of resizing the one and only band rect PRBool MySpaceManager::TestResizeRectRegion() { - PRBool status; BandsInfo bandsInfo; BandRect* bandRect; + nsresult status; // Clear any existing regions ClearRegions(); @@ -682,9 +683,9 @@ PRBool MySpaceManager::TestResizeRectRegion() ///////////////////////////////////////////////////////////////////////////// // #1. A simple test of resizing the right edge of the one and only band rect status = AddRectRegion((nsIFrame*)0x01, nsRect(10, 100, 100, 100)); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); status = ResizeRectRegion((nsIFrame*)0x01, 50, 50, nsISpaceManager::RightEdge); - NS_ASSERTION(PR_TRUE == status, "unexpected status"); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); // Verify there is one band with one rect GetBandsInfo(bandsInfo); @@ -708,6 +709,63 @@ PRBool MySpaceManager::TestResizeRectRegion() return PR_TRUE; } +// Test of getting the band data +PRBool MySpaceManager::TestGetBandData() +{ + BandsInfo bandsInfo; + BandRect* bandRect; + nsresult status; + + // Clear any existing regions + ClearRegions(); + NS_ASSERTION(mBandList.IsEmpty(), "clear regions failed"); + + // Make a band with three rects + status = AddRectRegion((nsIFrame*)0x01, nsRect(100, 100, 100, 100)); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); + + status = AddRectRegion((nsIFrame*)0x02, nsRect(300, 100, 100, 100)); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); + + status = AddRectRegion((nsIFrame*)0x03, nsRect(500, 100, 100, 100)); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); + + // Get the band data using a very large clip rect and a band data struct + // that's large enough + nsBandData bandData; + nsBandTrapezoid trapezoids[16]; + bandData.size = 16; + bandData.trapezoids = trapezoids; + status = GetBandData(100, nsSize(10000,10000), bandData); + NS_ASSERTION(NS_SUCCEEDED(status), "unexpected status"); + + // Verify that there are seven trapezoids + if (bandData.count != 7) { + printf("TestGetBandData: wrong trapezoid count (#1)\n"); + return PR_FALSE; + } + + // Get the band data using a very large clip rect and a band data struct + // that's too small + bandData.size = 3; + status = GetBandData(100, nsSize(10000,10000), bandData); + if (NS_SUCCEEDED(status)) { + printf("TestGetBandData: ignored band data count (#2)\n"); + return PR_FALSE; + } + + // Make sure the count has been updated to reflect the number of trapezoids + // required + if (bandData.count <= bandData.size) { + printf("TestGetBandData: bad band data count (#2)\n"); + return PR_FALSE; + } + + // XXX We need lots more tests here... + + return PR_TRUE; +} + /////////////////////////////////////////////////////////////////////////////// // @@ -751,11 +809,11 @@ int main(int argc, char** argv) return -1; } -#if 0 + // Test getting the band data if (!spaceMgr->TestGetBandData()) { return -1; } -#endif + NS_RELEASE(spaceMgr); return 0; } diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index e005d2ea268..ff5dc20a4d9 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -295,7 +295,8 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // Compute our desired size. Take into account any floaters when computing the // height - nscoord floaterYMost = mSpaceManager->YMost(); + nscoord floaterYMost; + mSpaceManager->YMost(floaterYMost); if (floaterYMost > 0) { // What we need to check for is if the bottom most floater extends below // the content area of the desired size diff --git a/layout/generic/nsBlockBandData.cpp b/layout/generic/nsBlockBandData.cpp index d7dc6893706..acf739e3a7c 100644 --- a/layout/generic/nsBlockBandData.cpp +++ b/layout/generic/nsBlockBandData.cpp @@ -230,7 +230,7 @@ nscoord nsBlockBandData::GetFrameYMost(nsIFrame* aFrame) { nsIFrame* spaceFrame; - spaceFrame = mSpaceManager->GetFrame(); + mSpaceManager->GetFrame(spaceFrame); nsRect r; nsPoint p; diff --git a/layout/generic/nsSpaceManager.cpp b/layout/generic/nsSpaceManager.cpp index 04edb3927bb..44e560746cd 100644 --- a/layout/generic/nsSpaceManager.cpp +++ b/layout/generic/nsSpaceManager.cpp @@ -50,7 +50,8 @@ nsSpaceManager::BandList::BandList() numFrames = 0; } -void nsSpaceManager::BandList::Clear() +void +nsSpaceManager::BandList::Clear() { if (!IsEmpty()) { BandRect* bandRect = Head(); @@ -66,7 +67,6 @@ void nsSpaceManager::BandList::Clear() } } - ///////////////////////////////////////////////////////////////////////////// // nsSpaceManager @@ -78,7 +78,8 @@ nsSpaceManager::nsSpaceManager(nsIFrame* aFrame) mFrameInfoMap = nsnull; } -void nsSpaceManager::ClearFrameInfo() +void +nsSpaceManager::ClearFrameInfo() { if (nsnull != mFrameInfoMap) { PL_HashTableEnumerateEntries(mFrameInfoMap, NS_RemoveFrameInfoEntries, 0); @@ -95,36 +96,41 @@ nsSpaceManager::~nsSpaceManager() NS_IMPL_ISUPPORTS(nsSpaceManager, kISpaceManagerIID); -nsIFrame* nsSpaceManager::GetFrame() const +NS_IMETHODIMP +nsSpaceManager::GetFrame(nsIFrame*& aFrame) const { - return mFrame; + aFrame = mFrame; + return NS_OK; } -void nsSpaceManager::Translate(nscoord aDx, nscoord aDy) +NS_IMETHODIMP +nsSpaceManager::Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; + return NS_OK; } -void nsSpaceManager::GetTranslation(nscoord& aX, nscoord& aY) const +NS_IMETHODIMP +nsSpaceManager::GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; + return NS_OK; } -nscoord nsSpaceManager::YMost() const +NS_IMETHODIMP +nsSpaceManager::YMost(nscoord& aYMost) const { - nscoord yMost; - if (mBandList.IsEmpty()) { - yMost = 0; + aYMost = 0; } else { BandRect* lastRect = mBandList.Tail(); - yMost = lastRect->bottom; + aYMost = lastRect->bottom; } - return yMost; + return NS_OK; } /** @@ -136,10 +142,11 @@ nscoord nsSpaceManager::YMost() const * @param aMaxSize the size to use to constrain the band data * @param aAvailableBand */ -PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, - nscoord aY, - const nsSize& aMaxSize, - nsBandData& aBandData) const +nsresult +nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, + nscoord aY, + const nsSize& aMaxSize, + nsBandData& aBandData) const { nscoord topOfBand = aBand->top; nscoord localY = aY - mY; @@ -171,6 +178,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, if (aBand->left > left) { // The rect is to the right of our current left coordinate, so we've // found some available space + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count += 2 * aBand->Length() + 2; // estimate the number needed + return NS_ERROR_FAILURE; + } trapezoid->state = nsBandTrapezoid::Available; trapezoid->frame = nsnull; @@ -184,6 +196,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, } // The rect represents unavailable space, so add another trapezoid + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count += 2 * aBand->Length() + 1; // estimate the number needed + return NS_ERROR_FAILURE; + } if (1 == aBand->numFrames) { trapezoid->state = nsBandTrapezoid::Occupied; trapezoid->frame = aBand->frame; @@ -218,6 +235,11 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, // No more rects left in the band. If we haven't yet reached the right edge, // then all the remaining space is available if (left < rightEdge) { + if (aBandData.count >= aBandData.size) { + // Not enough space in the array of trapezoids + aBandData.count++; + return NS_ERROR_FAILURE; + } trapezoid->state = nsBandTrapezoid::Available; trapezoid->frame = nsnull; @@ -227,19 +249,25 @@ PRInt32 nsSpaceManager::GetBandAvailableSpace(const BandRect* aBand, aBandData.count++; } - return aBandData.count; + return NS_OK; } -PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, - const nsSize& aMaxSize, - nsBandData& aBandData) const +NS_IMETHODIMP +nsSpaceManager::GetBandData(nscoord aYOffset, + const nsSize& aMaxSize, + nsBandData& aBandData) const { + NS_PRECONDITION(aBandData.size >= 1, "bad band data"); + nsresult result = NS_OK; + // Convert the y-offset to world coordinates nscoord y = mY + aYOffset; // If there are no unavailable rects or the offset is below the bottommost // band, then all the space is available - if (y >= YMost()) { + nscoord yMost; + YMost(yMost); + if (y >= yMost) { // All the requested space is available aBandData.count = 1; aBandData.trapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, aMaxSize.height); @@ -273,7 +301,7 @@ PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, } NS_POSTCONDITION(aBandData.count > 0, "unexpected band data count"); - return aBandData.count; + return result; } /** @@ -282,7 +310,8 @@ PRInt32 nsSpaceManager::GetBandData(nscoord aYOffset, * @param aBandRect A rect within the band * @returns The start of the next band, or nsnull of this is the last band. */ -nsSpaceManager::BandRect* nsSpaceManager::GetNextBand(const BandRect* aBandRect) const +nsSpaceManager::BandRect* +nsSpaceManager::GetNextBand(const BandRect* aBandRect) const { nscoord topOfBand = aBandRect->top; @@ -308,7 +337,8 @@ nsSpaceManager::BandRect* nsSpaceManager::GetNextBand(const BandRect* aBandRect) * @param aBottom where to split the band. This becomes the bottom of the top * part */ -void nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) +void +nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) { NS_PRECONDITION(aBottom < aBandRect->bottom, "bad height"); nscoord topOfBand = aBandRect->top; @@ -330,7 +360,8 @@ void nsSpaceManager::DivideBand(BandRect* aBandRect, nscoord aBottom) } } -PRBool nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) +PRBool +nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) { PRBool result; nscoord topOfBand = aBand->top; @@ -384,7 +415,8 @@ PRBool nsSpaceManager::CanJoinBands(BandRect* aBand, BandRect* aPrevBand) * * If the two bands are joined, the previous band is the the band that's deleted */ -PRBool nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) +PRBool +nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) { if (CanJoinBands(aBand, aPrevBand)) { BandRect* startOfNextBand = aBand; @@ -415,8 +447,8 @@ PRBool nsSpaceManager::JoinBands(BandRect* aBand, BandRect* aPrevBand) * @param aBand the first rect in the band * @param aBandRect the band rect to add to the band */ -void nsSpaceManager::AddRectToBand(BandRect* aBand, - BandRect* aBandRect) +void +nsSpaceManager::AddRectToBand(BandRect* aBand, BandRect* aBandRect) { NS_PRECONDITION((aBand->top == aBandRect->top) && (aBand->bottom == aBandRect->bottom), "bad band"); @@ -580,11 +612,14 @@ void nsSpaceManager::AddRectToBand(BandRect* aBand, // | R | // +-----+ // -void nsSpaceManager::InsertBandRect(BandRect* aBandRect) +void +nsSpaceManager::InsertBandRect(BandRect* aBandRect) { // If there are no existing bands or this rect is below the bottommost // band, then add a new band - if (aBandRect->top >= YMost()) { + nscoord yMost; + YMost(yMost); + if (aBandRect->top >= yMost) { mBandList.Append(aBandRect); return; } @@ -673,7 +708,8 @@ void nsSpaceManager::InsertBandRect(BandRect* aBandRect) } } -PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace) +NS_IMETHODIMP +nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace) { NS_PRECONDITION(nsnull != aFrame, "null frame"); @@ -682,7 +718,7 @@ PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailabl if (nsnull != frameInfo) { NS_WARNING("aFrame is already associated with a region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } // Convert the frame to world coordinates @@ -692,39 +728,47 @@ PRBool nsSpaceManager::AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailabl // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset for rect region"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } // Create a frame info structure frameInfo = CreateFrameInfo(aFrame, rect); + if (nsnull == frameInfo) { + return NS_ERROR_OUT_OF_MEMORY; + } // Is the rect empty? if (aUnavailableSpace.IsEmpty()) { // The rect doesn't consume any space, so don't add any band data - return PR_TRUE; + return NS_OK; } // Allocate a band rect BandRect* bandRect = new BandRect(rect.x, rect.y, rect.XMost(), rect.YMost(), aFrame); + if (nsnull == bandRect) { + return NS_ERROR_OUT_OF_MEMORY; + } // Insert the band rect InsertBandRect(bandRect); - return PR_TRUE; + return NS_OK; } -PRBool nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, - nscoord aDeltaWidth, - nscoord aDeltaHeight, - AffectedEdge aEdge) +NS_IMETHODIMP +nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, + nscoord aDeltaWidth, + nscoord aDeltaHeight, + AffectedEdge aEdge) { // Get the frame info associated with with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } + // Compute new rect nsRect rect(frameInfo->rect); rect.SizeBy(aDeltaWidth, aDeltaHeight); if (aEdge == LeftEdge) { @@ -734,51 +778,55 @@ PRBool nsSpaceManager::ResizeRectRegion(nsIFrame* aFrame, // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset when resizing rect region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } - // For the time being just remove it and add it back in + // For the time being just remove it and add it back in. Because + // AddRectRegion() operates relative to the local coordinate space, + // translate from world coordinates to the local coordinate space + rect.MoveBy(-mX, -mY); RemoveRegion(aFrame); return AddRectRegion(aFrame, rect); } -PRBool nsSpaceManager::OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy) +NS_IMETHODIMP +nsSpaceManager::OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy) { // Get the frame info associated with with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } - // Compute new rect for the region; note that we have to translate - // from the global coordinate system (frameInfo->rect) to our - // current local coordinate system before adding the rect region - // again (since AddRectRegion operates relative to the current - // translation). + // Compute new rect nsRect rect(frameInfo->rect); - rect.MoveBy(-mX + aDx, -mY + aDy); + rect.MoveBy(aDx, aDy); // Verify that the offset is within the defined coordinate space if ((rect.x < 0) || (rect.y < 0)) { NS_WARNING("invalid offset when offseting rect region"); - return PR_FALSE; + return NS_ERROR_FAILURE; } - // For the time being just remove it and add it back in + // For the time being just remove it and add it back in. Because + // AddRectRegion() operates relative to the local coordinate space, + // translate from world coordinates to the local coordinate space + rect.MoveBy(-mX, -mY); RemoveRegion(aFrame); return AddRectRegion(aFrame, rect); } -PRBool nsSpaceManager::RemoveRegion(nsIFrame* aFrame) +NS_IMETHODIMP +nsSpaceManager::RemoveRegion(nsIFrame* aFrame) { // Get the frame info associated with aFrame FrameInfo* frameInfo = GetFrameInfoFor(aFrame); if (nsnull == frameInfo) { NS_WARNING("no region associated with aFrame"); - return PR_FALSE; + return NS_ERROR_INVALID_ARG; } if (!frameInfo->rect.IsEmpty()) { @@ -871,16 +919,19 @@ PRBool nsSpaceManager::RemoveRegion(nsIFrame* aFrame) } DestroyFrameInfo(frameInfo); - return PR_TRUE; + return NS_OK; } -void nsSpaceManager::ClearRegions() +NS_IMETHODIMP +nsSpaceManager::ClearRegions() { ClearFrameInfo(); mBandList.Clear(); + return NS_OK; } -nsSpaceManager::FrameInfo* nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) +nsSpaceManager::FrameInfo* +nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) { FrameInfo* result = nsnull; @@ -891,21 +942,26 @@ nsSpaceManager::FrameInfo* nsSpaceManager::GetFrameInfoFor(nsIFrame* aFrame) return result; } -nsSpaceManager::FrameInfo* nsSpaceManager::CreateFrameInfo(nsIFrame* aFrame, - const nsRect& aRect) +nsSpaceManager::FrameInfo* +nsSpaceManager::CreateFrameInfo(nsIFrame* aFrame, const nsRect& aRect) { if (nsnull == mFrameInfoMap) { mFrameInfoMap = PL_NewHashTable(17, NS_HashNumber, PL_CompareValues, PL_CompareValues, nsnull, nsnull); + if (nsnull == mFrameInfoMap) { + return nsnull; + } } FrameInfo* frameInfo = new FrameInfo(aFrame, aRect); - - PL_HashTableAdd(mFrameInfoMap, (const void*)aFrame, frameInfo); + if (nsnull != frameInfo) { + PL_HashTableAdd(mFrameInfoMap, (const void*)aFrame, frameInfo); + } return frameInfo; } -void nsSpaceManager::DestroyFrameInfo(FrameInfo* aFrameInfo) +void +nsSpaceManager::DestroyFrameInfo(FrameInfo* aFrameInfo) { PL_HashTableRemove(mFrameInfoMap, (const void*)aFrameInfo->frame); delete aFrameInfo; @@ -958,7 +1014,8 @@ nsSpaceManager::BandRect::~BandRect() } } -nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitVertically(nscoord aBottom) +nsSpaceManager::BandRect* +nsSpaceManager::BandRect::SplitVertically(nscoord aBottom) { NS_PRECONDITION((aBottom > top) && (aBottom < bottom), "bad argument"); @@ -973,11 +1030,11 @@ nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitVertically(nscoord aBot // This band rect becomes the top part, so adjust the bottom edge bottom = aBottom; - return bottomBandRect; } -nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitHorizontally(nscoord aRight) +nsSpaceManager::BandRect* +nsSpaceManager::BandRect::SplitHorizontally(nscoord aRight) { NS_PRECONDITION((aRight > left) && (aRight < right), "bad argument"); @@ -992,11 +1049,11 @@ nsSpaceManager::BandRect* nsSpaceManager::BandRect::SplitHorizontally(nscoord aR // This band rect becomes the left part, so adjust the right edge right = aRight; - return rightBandRect; } -PRBool nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const +PRBool +nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const { PRBool result; @@ -1019,7 +1076,8 @@ PRBool nsSpaceManager::BandRect::IsOccupiedBy(const nsIFrame* aFrame) const return result; } -void nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) +void +nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) { if (1 == numFrames) { nsIFrame* f = frame; @@ -1032,7 +1090,8 @@ void nsSpaceManager::BandRect::AddFrame(const nsIFrame* aFrame) NS_POSTCONDITION(frames->Count() == numFrames, "bad frame count"); } -void nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) +void +nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) { NS_PRECONDITION(numFrames > 1, "only one frame"); frames->RemoveElement((void*)aFrame); @@ -1046,7 +1105,8 @@ void nsSpaceManager::BandRect::RemoveFrame(const nsIFrame* aFrame) } } -PRBool nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) const +PRBool +nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) const { PRBool result; @@ -1073,3 +1133,26 @@ PRBool nsSpaceManager::BandRect::HasSameFrameList(const BandRect* aBandRect) con return result; } + +/** + * Internal helper function that counts the number of rects in this band + * including the current band rect + */ +PRInt32 +nsSpaceManager::BandRect::Length() const +{ + nscoord topOfBand = top; + PRInt32 len = 1; + BandRect* bandRect = Next(); + + // Because there's a header cell we know we'll either find the next band + // (which has a different y-offset) or the header cell which has an invalid + // y-offset + while (bandRect->top == top) { + len++; + bandRect = bandRect->Next(); + } + + return len; +} + diff --git a/layout/generic/nsSpaceManager.h b/layout/generic/nsSpaceManager.h index d09eece1719..676c2ededbb 100644 --- a/layout/generic/nsSpaceManager.h +++ b/layout/generic/nsSpaceManager.h @@ -35,25 +35,26 @@ public: NS_DECL_ISUPPORTS // nsISpaceManager - virtual nsIFrame* GetFrame() const; + NS_IMETHOD GetFrame(nsIFrame*& aFrame) const; - virtual void Translate(nscoord aDx, nscoord aDy); - virtual void GetTranslation(nscoord& aX, nscoord& aY) const; - virtual nscoord YMost() const; + NS_IMETHOD Translate(nscoord aDx, nscoord aDy); + NS_IMETHOD GetTranslation(nscoord& aX, nscoord& aY) const; + NS_IMETHOD YMost(nscoord& aYMost) const; - virtual PRInt32 GetBandData(nscoord aYOffset, - const nsSize& aMaxSize, - nsBandData& aBandData) const; + NS_IMETHOD GetBandData(nscoord aYOffset, + const nsSize& aMaxSize, + nsBandData& aBandData) const; - virtual PRBool AddRectRegion(nsIFrame* aFrame, const nsRect& aUnavailableSpace); - virtual PRBool ResizeRectRegion(nsIFrame* aFrame, - nscoord aDeltaWidth, - nscoord aDeltaHeight, - AffectedEdge aEdge); - virtual PRBool OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy); - virtual PRBool RemoveRegion(nsIFrame* aFrame); + NS_IMETHOD AddRectRegion(nsIFrame* aFrame, + const nsRect& aUnavailableSpace); + NS_IMETHOD ResizeRectRegion(nsIFrame* aFrame, + nscoord aDeltaWidth, + nscoord aDeltaHeight, + AffectedEdge aEdge); + NS_IMETHOD OffsetRegion(nsIFrame* aFrame, nscoord aDx, nscoord aDy); + NS_IMETHOD RemoveRegion(nsIFrame* aFrame); - virtual void ClearRegions(); + NS_IMETHOD ClearRegions(); protected: // Structure that maintains information about the region associated @@ -109,6 +110,7 @@ protected: void AddFrame(const nsIFrame*); void RemoveFrame(const nsIFrame*); PRBool HasSameFrameList(const BandRect* aBandRect) const; + PRInt32 Length() const; }; // Circular linked list of band rects @@ -147,7 +149,7 @@ protected: void AddRectToBand(BandRect* aBand, BandRect* aBandRect); void InsertBandRect(BandRect* aBandRect); - PRInt32 GetBandAvailableSpace(const BandRect* aBand, + nsresult GetBandAvailableSpace(const BandRect* aBand, nscoord aY, const nsSize& aMaxSize, nsBandData& aAvailableSpace) const; diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index e005d2ea268..ff5dc20a4d9 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -295,7 +295,8 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // Compute our desired size. Take into account any floaters when computing the // height - nscoord floaterYMost = mSpaceManager->YMost(); + nscoord floaterYMost; + mSpaceManager->YMost(floaterYMost); if (floaterYMost > 0) { // What we need to check for is if the bottom most floater extends below // the content area of the desired size diff --git a/layout/html/base/src/nsBlockBandData.cpp b/layout/html/base/src/nsBlockBandData.cpp index d7dc6893706..acf739e3a7c 100644 --- a/layout/html/base/src/nsBlockBandData.cpp +++ b/layout/html/base/src/nsBlockBandData.cpp @@ -230,7 +230,7 @@ nscoord nsBlockBandData::GetFrameYMost(nsIFrame* aFrame) { nsIFrame* spaceFrame; - spaceFrame = mSpaceManager->GetFrame(); + mSpaceManager->GetFrame(spaceFrame); nsRect r; nsPoint p;