зеркало из https://github.com/mozilla/pjs.git
Changed space manager to return a list of available and unavailable trapezoids
This commit is contained in:
Родитель
fce71a412e
Коммит
f4c0f974bb
|
@ -37,6 +37,7 @@
|
|||
|
||||
static NS_DEFINE_IID(kIStyleSpacingSID, NS_STYLESPACING_SID);
|
||||
static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
|
||||
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
|
||||
|
||||
nsContainerFrame::nsContainerFrame(nsIContent* aContent,
|
||||
PRInt32 aIndexInParent,
|
||||
|
@ -451,29 +452,54 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
// nsBlockFrame since it already has band data, and it's probably the only
|
||||
// one who calls this routine anyway
|
||||
nsBandData bandData;
|
||||
nsBandTrapezoid trapezoids[7];
|
||||
nsBandTrapezoid* availSpace = trapezoids;
|
||||
nsBandTrapezoid trapezoids[12];
|
||||
nsBandTrapezoid* trapezoid = trapezoids;
|
||||
nsRect availBand;
|
||||
nsSize availSize = aMaxSize;
|
||||
|
||||
bandData.trapezoids = trapezoids;
|
||||
bandData.size = 7;
|
||||
bandData.size = 12;
|
||||
aSpaceManager->GetBandData(0, aMaxSize, bandData);
|
||||
|
||||
// If there's more than one trapezoid then figure out which one determines the
|
||||
// available reflow area
|
||||
if (bandData.count == 2) {
|
||||
nsRect r0, r1;
|
||||
if (bandData.count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
trapezoids[0].GetRect(r0);
|
||||
trapezoids[1].GetRect(r1);
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < bandData.count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &trapezoids[i];
|
||||
|
||||
// Either a left or right floater. Use whichever space is larger
|
||||
if (r1.width > r0.width) {
|
||||
availSpace = &trapezoids[1];
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (bandData.count == 3) {
|
||||
// Assume there are floaters on the left and right, and use the middle rect
|
||||
availSpace = &trapezoids[1];
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &trapezoids[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availBand);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availBand);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availBand.x = availBand.XMost();
|
||||
}
|
||||
availBand.width = 0;
|
||||
}
|
||||
|
||||
// Does the child frame want to do continuation-based runaround?
|
||||
|
@ -482,20 +508,17 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
aKidFrame->IsSplittable(isSplittable);
|
||||
if (isSplittable == frSplittableNonRectangular) {
|
||||
// Reduce the max height to the band height.
|
||||
availSize.height = availSpace->yBottom - availSpace->yTop;
|
||||
availSize.height = availBand.height;
|
||||
}
|
||||
|
||||
// Get the bounding rect of the available trapezoid
|
||||
nsRect rect;
|
||||
nsIStyleContext* kidSC;
|
||||
aKidFrame->GetStyleContext(aPresContext, kidSC);
|
||||
nsStyleSpacing* spacing = (nsStyleSpacing*)kidSC->GetData(kIStyleSpacingSID);
|
||||
nsStyleSpacing* spacing;
|
||||
|
||||
aKidFrame->GetStyleData(kIStyleSpacingSID, (nsStyleStruct*&)spacing);
|
||||
|
||||
availSpace->GetRect(rect);
|
||||
if (aMaxSize.width != NS_UNCONSTRAINEDSIZE) {
|
||||
if ((rect.x > 0) || (rect.XMost() < aMaxSize.width)) {
|
||||
if ((availBand.x > 0) || (availBand.XMost() < aMaxSize.width)) {
|
||||
// There are left/right floaters.
|
||||
availSize.width = rect.width;
|
||||
availSize.width = availBand.width;
|
||||
}
|
||||
|
||||
// Reduce the available width by the kid's left/right margin
|
||||
|
@ -505,7 +528,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
// Does the child frame support interface nsIRunaround?
|
||||
if (NS_OK == aKidFrame->QueryInterface(kIRunaroundIID, (void**)&reflowRunaround)) {
|
||||
// Yes, the child frame wants to interact directly with the space manager.
|
||||
nscoord tx = rect.x + spacing->mMargin.left;
|
||||
nscoord tx = availBand.x + spacing->mMargin.left;
|
||||
|
||||
// Translate the local coordinate space to the current left edge plus any
|
||||
// left margin the child wants
|
||||
|
@ -513,7 +536,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
|
||||
reflowRunaround->ResizeReflow(aPresContext, aSpaceManager, availSize,
|
||||
aDesiredRect, aMaxElementSize, status);
|
||||
aDesiredRect.x += rect.x;
|
||||
aDesiredRect.x += availBand.x;
|
||||
|
||||
// Translate back
|
||||
aSpaceManager->Translate(-tx, 0);
|
||||
|
@ -526,7 +549,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
aMaxElementSize, status);
|
||||
|
||||
// Return the desired rect
|
||||
aDesiredRect.x = rect.x;
|
||||
aDesiredRect.x = availBand.x;
|
||||
aDesiredRect.y = 0;
|
||||
aDesiredRect.width = desiredSize.width;
|
||||
aDesiredRect.height = desiredSize.height;
|
||||
|
@ -547,7 +570,6 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
}
|
||||
}
|
||||
|
||||
NS_RELEASE(kidSC);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ nscoord SpaceManager::YMost() const
|
|||
}
|
||||
|
||||
/**
|
||||
* Internal function that returns the available space within the band
|
||||
* Internal function that returns the list of available and unavailable space
|
||||
* within the band
|
||||
*
|
||||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
|
@ -70,25 +71,24 @@ nscoord SpaceManager::YMost() const
|
|||
* @param aMaxSize the size to use to constrain the band data
|
||||
* @param aAvailableBand
|
||||
*/
|
||||
PRInt32 SpaceManager::GetBandAvailableSpace(const nsRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const
|
||||
PRInt32 SpaceManager::GetBandAvailableSpace(const nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aBandData) const
|
||||
{
|
||||
PRInt32 numRects = LengthOfBand(aBand, aIndex);
|
||||
nscoord localY = aY - mY;
|
||||
nscoord height = PR_MIN(aBand->YMost() - aY, aMaxSize.height);
|
||||
nsBandTrapezoid* trapezoid = aAvailableSpace.trapezoids;
|
||||
nsBandTrapezoid* trapezoid = aBandData.trapezoids;
|
||||
nscoord rightEdge = mX + aMaxSize.width;
|
||||
|
||||
// Initialize the band data
|
||||
aAvailableSpace.count = 0;
|
||||
trapezoid->xTopLeft = mX;
|
||||
aBandData.count = 0;
|
||||
|
||||
// Skip any rectangles that are to the left of the local coordinate space
|
||||
while (numRects > 0) {
|
||||
if (aBand->XMost() >= mX) {
|
||||
if (aBand->XMost() > mX) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -97,60 +97,74 @@ PRInt32 SpaceManager::GetBandAvailableSpace(const nsRect* aBand,
|
|||
numRects--;
|
||||
}
|
||||
|
||||
// Process all the remaining rectangles that are within the clip width
|
||||
// This is used to track the current x-location within the band. This is in
|
||||
// world coordinates
|
||||
nscoord left = mX;
|
||||
|
||||
// Process the remaining rectangles that are within the clip width
|
||||
while ((numRects > 0) && (aBand->x < rightEdge)) {
|
||||
if (aBand->x > trapezoid->xTopLeft) {
|
||||
// We found some available space
|
||||
trapezoid->xTopRight = trapezoid->xBottomRight = aBand->x;
|
||||
|
||||
// Convert from world to local coordinates
|
||||
trapezoid->xTopLeft -= mX;
|
||||
trapezoid->xTopRight -= mX;
|
||||
trapezoid->xBottomLeft = trapezoid->xTopLeft;
|
||||
trapezoid->xBottomRight = trapezoid->xTopRight;
|
||||
|
||||
trapezoid->yTop = localY;
|
||||
trapezoid->yBottom = localY + height;
|
||||
// Compare the left edge of the occupied space with the current left
|
||||
// coordinate
|
||||
if (aBand->x > left) {
|
||||
// The rect is to the right of our current left coordinate, so we've
|
||||
// found some available space
|
||||
trapezoid->state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid->frame = nsnull;
|
||||
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the current left coordinate
|
||||
*trapezoid = nsRect(left - mX, localY, aBand->x - left, height);
|
||||
|
||||
// Move to the next output rect
|
||||
trapezoid++;
|
||||
aAvailableSpace.count++;
|
||||
aBandData.count++;
|
||||
}
|
||||
|
||||
trapezoid->xTopLeft = aBand->XMost();
|
||||
// The rect represents unavailable space, so add another trapezoid
|
||||
trapezoid->state = nsBandTrapezoid::smOccupied;
|
||||
trapezoid->frame = aBand->frame;
|
||||
|
||||
// Move to the next rect in the band
|
||||
nscoord x = aBand->x;
|
||||
// The first band can straddle the clip rect
|
||||
if (x < mX) {
|
||||
// Clip the left edge
|
||||
x = mX;
|
||||
}
|
||||
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the rects's left coordinate
|
||||
*trapezoid = nsRect(x - mX, localY, aBand->XMost() - x, height);
|
||||
|
||||
// Move to the next output rect
|
||||
trapezoid++;
|
||||
aBandData.count++;
|
||||
|
||||
// Adjust our current x-location within the band
|
||||
left = aBand->XMost();
|
||||
|
||||
// Move to the next rect within the band
|
||||
numRects--;
|
||||
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 (trapezoid->xTopLeft < rightEdge) {
|
||||
trapezoid->xTopRight = rightEdge;
|
||||
|
||||
// Convert from world to local coordinates
|
||||
trapezoid->xTopLeft -= mX;
|
||||
trapezoid->xTopRight -= mX;
|
||||
trapezoid->xBottomLeft = trapezoid->xTopLeft;
|
||||
trapezoid->xBottomRight = trapezoid->xTopRight;
|
||||
|
||||
trapezoid->yTop = localY;
|
||||
trapezoid->yBottom = localY + height;
|
||||
if (left < rightEdge) {
|
||||
trapezoid->state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid->frame = nsnull;
|
||||
|
||||
aAvailableSpace.count++;
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the current left coordinate
|
||||
*trapezoid = nsRect(left - mX, localY, rightEdge - left, height);
|
||||
aBandData.count++;
|
||||
}
|
||||
|
||||
return aAvailableSpace.count;
|
||||
return aBandData.count;
|
||||
}
|
||||
|
||||
PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const
|
||||
nsBandData& aBandData) const
|
||||
{
|
||||
// Convert the y-offset to world coordinates
|
||||
nscoord y = mY + aYOffset;
|
||||
|
@ -158,35 +172,29 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
// If there are no unavailable rects or the offset is below the bottommost
|
||||
// band then all the space is available
|
||||
if ((0 == mRectArray.mCount) || (y >= mRectArray.YMost())) {
|
||||
aAvailableSpace.count = 1;
|
||||
|
||||
nsBandTrapezoid& trapezoid = aAvailableSpace.trapezoids[0];
|
||||
|
||||
trapezoid.xTopLeft = trapezoid.xBottomLeft = 0;
|
||||
trapezoid.yTop = aYOffset;
|
||||
trapezoid.xTopRight = trapezoid.xBottomRight = aMaxSize.width;
|
||||
trapezoid.yBottom = aYOffset + aMaxSize.height;
|
||||
trapezoid.state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid.frame = nsnull;
|
||||
// All the requested space is available
|
||||
aBandData.count = 1;
|
||||
aBandData.trapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, aMaxSize.height);
|
||||
aBandData.trapezoids[0].state = nsBandTrapezoid::smAvailable;
|
||||
aBandData.trapezoids[0].frame = nsnull;
|
||||
} else {
|
||||
// Find the first band that contains the y-offset or is below the y-offset
|
||||
nsRect* band = mRectArray.mRects;
|
||||
nsBandRect* band = mRectArray.mRects;
|
||||
|
||||
for (PRInt32 i = 0; i < mRectArray.mCount; ) {
|
||||
if (band->y > y) {
|
||||
// The band is below the y-offset
|
||||
nsBandTrapezoid& trapezoid = aAvailableSpace.trapezoids[0];
|
||||
|
||||
trapezoid.xTopLeft = trapezoid.xBottomLeft = 0;
|
||||
trapezoid.yTop = aYOffset;
|
||||
trapezoid.xTopRight = trapezoid.xBottomRight = aMaxSize.width;
|
||||
trapezoid.yBottom = aYOffset + PR_MIN(band->y - y, aMaxSize.height);
|
||||
trapezoid.state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid.frame = nsnull;
|
||||
// The band is below the y-offset. The area between the y-offset and
|
||||
// the top of the band is available
|
||||
aBandData.count = 1;
|
||||
aBandData.trapezoids[0] =
|
||||
nsRect(0, aYOffset, aMaxSize.width, PR_MIN(band->y - y, aMaxSize.height));
|
||||
aBandData.trapezoids[0].state = nsBandTrapezoid::smAvailable;
|
||||
aBandData.trapezoids[0].frame = nsnull;
|
||||
break;
|
||||
} else if (y < band->YMost()) {
|
||||
// The band contains the y-offset
|
||||
return GetBandAvailableSpace(band, i, y, aMaxSize, aAvailableSpace);
|
||||
// The band contains the y-offset. Return a list of available and
|
||||
// unavailable rects within the band
|
||||
return GetBandAvailableSpace(band, i, y, aMaxSize, aBandData);
|
||||
} else {
|
||||
// Skip to the next band
|
||||
GetNextBand(band, i);
|
||||
|
@ -194,7 +202,7 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
}
|
||||
}
|
||||
|
||||
return aAvailableSpace.count;
|
||||
return aBandData.count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +215,7 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
* next band. If there is no next band then aRect is undefined
|
||||
* and aIndex is set to the number of rects in the rect array
|
||||
*/
|
||||
PRBool SpaceManager::GetNextBand(nsRect*& aRect, PRInt32& aIndex) const
|
||||
PRBool SpaceManager::GetNextBand(nsBandRect*& aRect, PRInt32& aIndex) const
|
||||
{
|
||||
nscoord topOfBand = aRect->y;
|
||||
|
||||
|
@ -231,7 +239,7 @@ PRBool SpaceManager::GetNextBand(nsRect*& aRect, PRInt32& aIndex) const
|
|||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
*/
|
||||
PRInt32 SpaceManager::LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const
|
||||
PRInt32 SpaceManager::LengthOfBand(const nsBandRect* aBand, PRInt32 aIndex) const
|
||||
{
|
||||
nscoord topOfBand = aBand->y;
|
||||
PRInt32 result = 1;
|
||||
|
@ -252,36 +260,48 @@ PRInt32 SpaceManager::LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const
|
|||
}
|
||||
|
||||
/**
|
||||
* Tries to coalesce horizontally overlapping rectangles within a band
|
||||
* Tries to coalesce adjoining rectangles within a band. Returns PR_TRUE if any
|
||||
* of the rects are coalesced and PR_FALSE otherwise
|
||||
*
|
||||
* @param aRect a rect in the band
|
||||
* @param aIndex aRect's index in the rect array
|
||||
* @param aRect the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
*/
|
||||
void SpaceManager::CoalesceBand(nsRect* aRect, PRInt32 aIndex)
|
||||
PRBool SpaceManager::CoalesceBand(nsBandRect* aBand, PRInt32 aIndex)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
while ((aIndex + 1) < mRectArray.mCount) {
|
||||
// Is there another rect in this band?
|
||||
nsRect* nextRect = aRect + 1;
|
||||
nsBandRect* nextRect = aBand + 1;
|
||||
|
||||
if (nextRect->y == aRect->y) {
|
||||
// Yes. Do the two rects overlap horizontally?
|
||||
if (aRect->XMost() > nextRect->x) {
|
||||
// Yes. Extend the right edge of aRect
|
||||
aRect->width = nextRect->XMost() - aRect->x;
|
||||
if (nextRect->y == aBand->y) {
|
||||
// The rects must not be overlapping
|
||||
NS_ASSERTION(nextRect->x >= aBand->XMost(), "overlapping rects");
|
||||
|
||||
// Are the two rects adjoining and have the same tagged frame?
|
||||
if ((aBand->XMost() == nextRect->x) && (aBand->frame == nextRect->frame)) {
|
||||
// Yes. Extend the right edge of the current rect
|
||||
aBand->width = nextRect->XMost() - aBand->x;
|
||||
|
||||
// Remove the next rect
|
||||
mRectArray.RemoveAt(aIndex + 1);
|
||||
aRect = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Continue through the loop trying to coalesce this rect
|
||||
result = PR_TRUE;
|
||||
|
||||
} else {
|
||||
// No. We're all done
|
||||
break;
|
||||
// No. Move to the next rect within the band
|
||||
aBand++;
|
||||
aIndex++;
|
||||
}
|
||||
} else {
|
||||
// The next rect is part of a different band, so we're all done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,7 +311,7 @@ void SpaceManager::CoalesceBand(nsRect* aRect, PRInt32 aIndex)
|
|||
* @param aIndex aBand's index in the rect array
|
||||
* @param aB1Height the height of the new band to create
|
||||
*/
|
||||
void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
||||
void SpaceManager::DivideBand(nsBandRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
||||
{
|
||||
NS_PRECONDITION(aB1Height < aBand->height, "bad height");
|
||||
|
||||
|
@ -305,7 +325,7 @@ void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
|||
// Insert a new bottom band
|
||||
nsRect r(aBand->x, aBand->y + aB1Height, aBand->width, aB2Height);
|
||||
|
||||
mRectArray.InsertAt(r, insertAt);
|
||||
mRectArray.InsertAt(r, insertAt, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Adjust the height of the top band
|
||||
|
@ -322,62 +342,127 @@ void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
|||
*
|
||||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
* @param aRect the rect to add to the band
|
||||
* @param aRect the rect to add to the band. It's in world coordinates
|
||||
* @returns PR_TRUE if successful and PR_FALSE if this is the last band
|
||||
*/
|
||||
void SpaceManager::AddRectToBand(nsRect* aBand,
|
||||
void SpaceManager::AddRectToBand(nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
const nsRect& aRect)
|
||||
const nsRect& aRect,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION((aBand->y == aRect.y) && (aBand->height == aRect.height), "bad band");
|
||||
|
||||
nscoord topOfBand = aBand->y;
|
||||
nsRect rect(aRect);
|
||||
|
||||
// Figure out where in the band to horizontally insert the rect. Try and
|
||||
// coalesce it with an existing rect if possible.
|
||||
// Figure out where in the band horizontally to insert the rect. Try and
|
||||
// coalesce it with an existing rect if possible. We can only do this if
|
||||
// they're tagged with the same frame
|
||||
do {
|
||||
// Compare the left edge of the new rect with the left edge of the existing
|
||||
// rect
|
||||
if (aRect.x <= aBand->x) {
|
||||
// The new rect's left edge is to the left of the existing rect's left
|
||||
// edge. Does the new rect overlap the existing rect?
|
||||
if (aRect.XMost() >= aBand->x) {
|
||||
// Yes. Extend the existing rect
|
||||
if (aRect.XMost() > aBand->XMost()) {
|
||||
aBand->x = aRect.x;
|
||||
aBand->width = aRect.width;
|
||||
|
||||
// We're extending the right edge of the existing rect which may
|
||||
// cause the rect to overlap the remaining rects in the band
|
||||
CoalesceBand(aBand, aIndex);
|
||||
} else {
|
||||
aBand->width = aBand->XMost() - aRect.x;
|
||||
aBand->x = aRect.x;
|
||||
}
|
||||
} else {
|
||||
// No, it's completely to the left of the existing rect. Insert a new
|
||||
// rect
|
||||
mRectArray.InsertAt(aRect, aIndex);
|
||||
if (rect.x < aBand->x) {
|
||||
// The new rect's left edge is to the left of the existing rect's left edge.
|
||||
// Could be any of these cases (N is new rect, E is existing rect):
|
||||
//
|
||||
// Case 1: left-of Case 2: overlaps Case 3: N.contains(E)
|
||||
// --------------- ---------------- ---------------------
|
||||
// +-----+ +-----+ +-----+ +---------+
|
||||
// | N | | E | | N | | N |
|
||||
// +-----+ +-----+ +-----+ +---------+
|
||||
// +-----+ +---+
|
||||
// | E | | E |
|
||||
// +-----+ +---+
|
||||
//
|
||||
// Do the two rectangles overlap?
|
||||
if (rect.XMost() <= aBand->x) {
|
||||
// No, the new rect is completely to the left of the existing rect
|
||||
// (case #1). Insert a new rect
|
||||
mRectArray.InsertAt(rect, aIndex, aFrame);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
} else if (aRect.x <= aBand->XMost()) {
|
||||
// The two rects are overlapping or adjoining. Extend the right edge of
|
||||
// the existing rect
|
||||
aBand->width = aRect.XMost() - aBand->x;
|
||||
// Yes, they overlap. Insert a new rect for the part that's to the left
|
||||
// of the existing rect
|
||||
nsRect r1(rect.x, rect.y, aBand->x - rect.x, rect.height);
|
||||
|
||||
// Since we extended the right edge of the existing rect it may now
|
||||
// overlap the remaining rects in the band
|
||||
CoalesceBand(aBand, aIndex);
|
||||
mRectArray.InsertAt(r1, aIndex, aFrame);
|
||||
aIndex++;
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Adjust rect to reflect the overlap
|
||||
rect.width = rect.XMost() - aBand->x;
|
||||
rect.x = aBand->x;
|
||||
|
||||
} else if (rect.x > aBand->x) {
|
||||
// The new rect's left edge is to the right of the existing rect's left
|
||||
// edge. Could be any one of these cases:
|
||||
//
|
||||
// Case 4: right-of Case 5: overlaps Case 6: E.Contains(N)
|
||||
// --------------- ---------------- ---------------------
|
||||
// +-----+ +-----+ +-----+ +------------+
|
||||
// | E | | N | | E | | E |
|
||||
// +-----+ +-----+ +-----+ +------------+
|
||||
// +-----+ +-----+
|
||||
// | N | | N |
|
||||
// +-----+ +-----+
|
||||
//
|
||||
if (rect.x >= aBand->XMost()) {
|
||||
// The new rect is to the right of the existing rect (case #4), so move
|
||||
// to the next rect in the band
|
||||
aBand++; aIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The rects overlap, so divide the existing rect into two rects: the
|
||||
// part to the left of the new rect, and the part that overlaps
|
||||
nsRect r1(rect.x, aBand->y, aBand->XMost() - rect.x, aBand->height);
|
||||
|
||||
// Modify the left half of the existing rect
|
||||
aBand->width = rect.x - aBand->x;
|
||||
|
||||
// Insert the new right half of the existing rect, and make it the current
|
||||
// rect
|
||||
aIndex++;
|
||||
mRectArray.InsertAt(r1, aIndex, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
}
|
||||
|
||||
// At this point the left edge of the new rect is the same as the left edge
|
||||
// of the existing rect
|
||||
NS_ASSERTION(rect.x == aBand->x, "unexpected rect");
|
||||
|
||||
// Compare which rect is wider, the new rect or the existing rect
|
||||
if (aBand->width > rect.width) {
|
||||
// The existing rect is wider (cases 2 and 6). Divide the existing rect
|
||||
// into two rects: the part that overlaps, and the part to the right of
|
||||
// the new rect
|
||||
nsRect r1(rect.XMost(), aBand->y, aBand->XMost() - rect.XMost(), aBand->height);
|
||||
|
||||
// Modify the left half of the existing rect
|
||||
aBand->width = r1.x - aBand->x;
|
||||
|
||||
// Insert the new right half of the existing rect
|
||||
mRectArray.InsertAt(r1, aIndex, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
}
|
||||
|
||||
// XXX Mark the existing rect as being shared by the two frames...
|
||||
|
||||
if (rect.width == aBand->width) {
|
||||
// We're all done
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to the next rect in the band
|
||||
// The new rect is wider than the existing rect (cases 3 and 5). Set rect
|
||||
// to be the overhang and move to the next rect within the band
|
||||
rect.width = rect.XMost() - aBand->XMost();
|
||||
rect.x = aBand->XMost();
|
||||
aBand++; aIndex++;
|
||||
} while ((aIndex < mRectArray.mCount) && (aBand->y == topOfBand));
|
||||
|
||||
// Insert a new rect
|
||||
mRectArray.InsertAt(aRect, aIndex);
|
||||
mRectArray.InsertAt(aRect, aIndex, aFrame);
|
||||
}
|
||||
|
||||
// When comparing a rect to a band there are seven cases to consider.
|
||||
|
@ -417,12 +502,12 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
// then add a new band
|
||||
if ((0 == mRectArray.mCount) || (rect.y >= mRectArray.YMost())) {
|
||||
// Append a new bottommost band
|
||||
mRectArray.Append(rect);
|
||||
mRectArray.Append(rect, aFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
// Examine each band looking for a band that intersects this rect
|
||||
nsRect* band = mRectArray.mRects;
|
||||
nsBandRect* band = mRectArray.mRects;
|
||||
|
||||
for (PRInt32 i = 0; i < mRectArray.mCount; ) {
|
||||
// Compare the top edge of this rect with the top edge of the band
|
||||
|
@ -432,7 +517,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
if (rect.YMost() <= band->y) {
|
||||
// Case #1. This rect is completely above the band, so insert a
|
||||
// new band
|
||||
mRectArray.InsertAt(rect, i);
|
||||
mRectArray.InsertAt(rect, i, aFrame);
|
||||
break; // we're all done
|
||||
}
|
||||
|
||||
|
@ -441,7 +526,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
nsRect r1(rect.x, rect.y, rect.width, band->y - rect.y);
|
||||
|
||||
// Insert r1 as a new band
|
||||
mRectArray.InsertAt(r1, i);
|
||||
mRectArray.InsertAt(r1, i, aFrame);
|
||||
i++;
|
||||
band = mRectArray.mRects + i; // memory may have changed...
|
||||
|
||||
|
@ -480,7 +565,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
|
||||
if (rect.height == band->height) {
|
||||
// Add the rect to the band
|
||||
AddRectToBand(band, i, rect);
|
||||
AddRectToBand(band, i, rect, aFrame);
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
@ -489,7 +574,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
nsRect r1(rect.x, rect.y, rect.width, band->YMost() - rect.y);
|
||||
|
||||
// Add r1 to the band
|
||||
AddRectToBand(band, i, r1);
|
||||
AddRectToBand(band, i, r1, aFrame);
|
||||
band = mRectArray.mRects + i; // memory may have changed...
|
||||
|
||||
// Modify rect to be the part below the band
|
||||
|
@ -499,7 +584,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
// Continue with the next band
|
||||
if (!GetNextBand(band, i)) {
|
||||
// Append a new bottommost band
|
||||
mRectArray.Append(rect);
|
||||
mRectArray.Append(rect, aFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -532,29 +617,40 @@ nscoord SpaceManager::RectArray::YMost() const
|
|||
return mRects[mCount - 1].YMost();
|
||||
}
|
||||
|
||||
void SpaceManager::RectArray::Append(const nsRect& aRect)
|
||||
void SpaceManager::RectArray::Append(const nsRect& aRect, nsIFrame* aFrame)
|
||||
{
|
||||
// Ensure there's enough capacity
|
||||
if (mCount >= mMax) {
|
||||
mMax += 8;
|
||||
mRects = (nsRect*)realloc(mRects, mMax * sizeof(nsRect));
|
||||
mRects = (nsBandRect*)realloc(mRects, mMax * sizeof(nsBandRect));
|
||||
}
|
||||
|
||||
mRects[mCount++] = aRect;
|
||||
mRects[mCount].x = aRect.x;
|
||||
mRects[mCount].y = aRect.y;
|
||||
mRects[mCount].width = aRect.width;
|
||||
mRects[mCount].height = aRect.height;
|
||||
mRects[mCount].frame = aFrame;
|
||||
mCount++;
|
||||
}
|
||||
|
||||
void SpaceManager::RectArray::InsertAt(const nsRect& aRect, PRInt32 aIndex)
|
||||
void SpaceManager::RectArray::InsertAt(const nsRect& aRect,
|
||||
PRInt32 aIndex,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION(aIndex <= mCount, "bad index"); // no holes in the array
|
||||
|
||||
// Ensure there's enough capacity
|
||||
if (mCount >= mMax) {
|
||||
mMax += 8;
|
||||
mRects = (nsRect*)realloc(mRects, mMax * sizeof(nsRect));
|
||||
mRects = (nsBandRect*)realloc(mRects, mMax * sizeof(nsBandRect));
|
||||
}
|
||||
|
||||
memmove(&mRects[aIndex + 1], &mRects[aIndex], (mCount - aIndex) * sizeof(nsRect));
|
||||
mRects[aIndex] = aRect;
|
||||
memmove(&mRects[aIndex + 1], &mRects[aIndex], (mCount - aIndex) * sizeof(nsBandRect));
|
||||
mRects[aIndex].x = aRect.x;
|
||||
mRects[aIndex].y = aRect.y;
|
||||
mRects[aIndex].width = aRect.width;
|
||||
mRects[aIndex].height = aRect.height;
|
||||
mRects[aIndex].frame = aFrame;
|
||||
mCount++;
|
||||
}
|
||||
|
||||
|
@ -564,7 +660,7 @@ void SpaceManager::RectArray::RemoveAt(PRInt32 aIndex)
|
|||
|
||||
mCount--;
|
||||
if (aIndex < mCount) {
|
||||
memmove(&mRects[aIndex], &mRects[aIndex + 1], (mCount - aIndex) * sizeof(nsRect));
|
||||
memmove(&mRects[aIndex], &mRects[aIndex + 1], (mCount - aIndex) * sizeof(nsBandRect));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,19 +38,23 @@ public:
|
|||
virtual nscoord YMost() const;
|
||||
virtual PRInt32 GetBandData(nscoord aYOffset,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
nsBandData& aBandData) const;
|
||||
virtual void AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFrame);
|
||||
virtual void ClearRegions();
|
||||
|
||||
protected:
|
||||
struct nsBandRect : nsRect {
|
||||
nsIFrame* frame;
|
||||
};
|
||||
|
||||
class RectArray {
|
||||
public:
|
||||
RectArray();
|
||||
~RectArray();
|
||||
|
||||
// Functions to add rects
|
||||
void Append(const nsRect& aRect);
|
||||
void InsertAt(const nsRect& aRect, PRInt32 aIndex);
|
||||
void Append(const nsRect& aRect, nsIFrame* aFrame);
|
||||
void InsertAt(const nsRect& aRect, PRInt32 aIndex, nsIFrame* aFrame);
|
||||
void RemoveAt(PRInt32 aIndex);
|
||||
|
||||
// Clear the list of rectangles
|
||||
|
@ -61,9 +65,9 @@ protected:
|
|||
|
||||
public:
|
||||
// Access to the underlying storage
|
||||
nsRect* mRects; // y-x banded array of rectangles of unavailable space
|
||||
PRInt32 mCount; // current number of rects
|
||||
PRInt32 mMax; // capacity of rect array
|
||||
nsBandRect* mRects; // y-x banded array of rectangles of unavailable space
|
||||
PRInt32 mCount; // current number of rects
|
||||
PRInt32 mMax; // capacity of rect array
|
||||
};
|
||||
|
||||
nsIFrame* const mFrame; // frame associated with the space manager
|
||||
|
@ -71,16 +75,17 @@ protected:
|
|||
RectArray mRectArray; // y-x banded array of rectangles of unavailable space
|
||||
|
||||
protected:
|
||||
PRBool GetNextBand(nsRect*& aRect, PRInt32& aIndex) const;
|
||||
PRInt32 LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const;
|
||||
void CoalesceBand(nsRect* aBand, PRInt32 aIndex);
|
||||
void DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height);
|
||||
void AddRectToBand(nsRect* aBand, PRInt32 aIndex, const nsRect& aRect);
|
||||
PRInt32 GetBandAvailableSpace(const nsRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
PRBool GetNextBand(nsBandRect*& aRect, PRInt32& aIndex) const;
|
||||
PRInt32 LengthOfBand(const nsBandRect* aBand, PRInt32 aIndex) const;
|
||||
PRBool CoalesceBand(nsBandRect* aBand, PRInt32 aIndex);
|
||||
void DivideBand(nsBandRect* aBand, PRInt32 aIndex, nscoord aB1Height);
|
||||
void AddRectToBand(nsBandRect* aBand, PRInt32 aIndex,
|
||||
const nsRect& aRect, nsIFrame* aFrame);
|
||||
PRInt32 GetBandAvailableSpace(const nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
|
||||
private:
|
||||
SpaceManager(const SpaceManager&); // no implementation
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
|
@ -62,7 +62,8 @@ nscoord SpaceManager::YMost() const
|
|||
}
|
||||
|
||||
/**
|
||||
* Internal function that returns the available space within the band
|
||||
* Internal function that returns the list of available and unavailable space
|
||||
* within the band
|
||||
*
|
||||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
|
@ -70,25 +71,24 @@ nscoord SpaceManager::YMost() const
|
|||
* @param aMaxSize the size to use to constrain the band data
|
||||
* @param aAvailableBand
|
||||
*/
|
||||
PRInt32 SpaceManager::GetBandAvailableSpace(const nsRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const
|
||||
PRInt32 SpaceManager::GetBandAvailableSpace(const nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aBandData) const
|
||||
{
|
||||
PRInt32 numRects = LengthOfBand(aBand, aIndex);
|
||||
nscoord localY = aY - mY;
|
||||
nscoord height = PR_MIN(aBand->YMost() - aY, aMaxSize.height);
|
||||
nsBandTrapezoid* trapezoid = aAvailableSpace.trapezoids;
|
||||
nsBandTrapezoid* trapezoid = aBandData.trapezoids;
|
||||
nscoord rightEdge = mX + aMaxSize.width;
|
||||
|
||||
// Initialize the band data
|
||||
aAvailableSpace.count = 0;
|
||||
trapezoid->xTopLeft = mX;
|
||||
aBandData.count = 0;
|
||||
|
||||
// Skip any rectangles that are to the left of the local coordinate space
|
||||
while (numRects > 0) {
|
||||
if (aBand->XMost() >= mX) {
|
||||
if (aBand->XMost() > mX) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -97,60 +97,74 @@ PRInt32 SpaceManager::GetBandAvailableSpace(const nsRect* aBand,
|
|||
numRects--;
|
||||
}
|
||||
|
||||
// Process all the remaining rectangles that are within the clip width
|
||||
// This is used to track the current x-location within the band. This is in
|
||||
// world coordinates
|
||||
nscoord left = mX;
|
||||
|
||||
// Process the remaining rectangles that are within the clip width
|
||||
while ((numRects > 0) && (aBand->x < rightEdge)) {
|
||||
if (aBand->x > trapezoid->xTopLeft) {
|
||||
// We found some available space
|
||||
trapezoid->xTopRight = trapezoid->xBottomRight = aBand->x;
|
||||
|
||||
// Convert from world to local coordinates
|
||||
trapezoid->xTopLeft -= mX;
|
||||
trapezoid->xTopRight -= mX;
|
||||
trapezoid->xBottomLeft = trapezoid->xTopLeft;
|
||||
trapezoid->xBottomRight = trapezoid->xTopRight;
|
||||
|
||||
trapezoid->yTop = localY;
|
||||
trapezoid->yBottom = localY + height;
|
||||
// Compare the left edge of the occupied space with the current left
|
||||
// coordinate
|
||||
if (aBand->x > left) {
|
||||
// The rect is to the right of our current left coordinate, so we've
|
||||
// found some available space
|
||||
trapezoid->state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid->frame = nsnull;
|
||||
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the current left coordinate
|
||||
*trapezoid = nsRect(left - mX, localY, aBand->x - left, height);
|
||||
|
||||
// Move to the next output rect
|
||||
trapezoid++;
|
||||
aAvailableSpace.count++;
|
||||
aBandData.count++;
|
||||
}
|
||||
|
||||
trapezoid->xTopLeft = aBand->XMost();
|
||||
// The rect represents unavailable space, so add another trapezoid
|
||||
trapezoid->state = nsBandTrapezoid::smOccupied;
|
||||
trapezoid->frame = aBand->frame;
|
||||
|
||||
// Move to the next rect in the band
|
||||
nscoord x = aBand->x;
|
||||
// The first band can straddle the clip rect
|
||||
if (x < mX) {
|
||||
// Clip the left edge
|
||||
x = mX;
|
||||
}
|
||||
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the rects's left coordinate
|
||||
*trapezoid = nsRect(x - mX, localY, aBand->XMost() - x, height);
|
||||
|
||||
// Move to the next output rect
|
||||
trapezoid++;
|
||||
aBandData.count++;
|
||||
|
||||
// Adjust our current x-location within the band
|
||||
left = aBand->XMost();
|
||||
|
||||
// Move to the next rect within the band
|
||||
numRects--;
|
||||
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 (trapezoid->xTopLeft < rightEdge) {
|
||||
trapezoid->xTopRight = rightEdge;
|
||||
|
||||
// Convert from world to local coordinates
|
||||
trapezoid->xTopLeft -= mX;
|
||||
trapezoid->xTopRight -= mX;
|
||||
trapezoid->xBottomLeft = trapezoid->xTopLeft;
|
||||
trapezoid->xBottomRight = trapezoid->xTopRight;
|
||||
|
||||
trapezoid->yTop = localY;
|
||||
trapezoid->yBottom = localY + height;
|
||||
if (left < rightEdge) {
|
||||
trapezoid->state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid->frame = nsnull;
|
||||
|
||||
aAvailableSpace.count++;
|
||||
// Assign the trapezoid a rectangular shape. The trapezoid must be in the
|
||||
// local coordinate space, so convert the current left coordinate
|
||||
*trapezoid = nsRect(left - mX, localY, rightEdge - left, height);
|
||||
aBandData.count++;
|
||||
}
|
||||
|
||||
return aAvailableSpace.count;
|
||||
return aBandData.count;
|
||||
}
|
||||
|
||||
PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const
|
||||
nsBandData& aBandData) const
|
||||
{
|
||||
// Convert the y-offset to world coordinates
|
||||
nscoord y = mY + aYOffset;
|
||||
|
@ -158,35 +172,29 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
// If there are no unavailable rects or the offset is below the bottommost
|
||||
// band then all the space is available
|
||||
if ((0 == mRectArray.mCount) || (y >= mRectArray.YMost())) {
|
||||
aAvailableSpace.count = 1;
|
||||
|
||||
nsBandTrapezoid& trapezoid = aAvailableSpace.trapezoids[0];
|
||||
|
||||
trapezoid.xTopLeft = trapezoid.xBottomLeft = 0;
|
||||
trapezoid.yTop = aYOffset;
|
||||
trapezoid.xTopRight = trapezoid.xBottomRight = aMaxSize.width;
|
||||
trapezoid.yBottom = aYOffset + aMaxSize.height;
|
||||
trapezoid.state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid.frame = nsnull;
|
||||
// All the requested space is available
|
||||
aBandData.count = 1;
|
||||
aBandData.trapezoids[0] = nsRect(0, aYOffset, aMaxSize.width, aMaxSize.height);
|
||||
aBandData.trapezoids[0].state = nsBandTrapezoid::smAvailable;
|
||||
aBandData.trapezoids[0].frame = nsnull;
|
||||
} else {
|
||||
// Find the first band that contains the y-offset or is below the y-offset
|
||||
nsRect* band = mRectArray.mRects;
|
||||
nsBandRect* band = mRectArray.mRects;
|
||||
|
||||
for (PRInt32 i = 0; i < mRectArray.mCount; ) {
|
||||
if (band->y > y) {
|
||||
// The band is below the y-offset
|
||||
nsBandTrapezoid& trapezoid = aAvailableSpace.trapezoids[0];
|
||||
|
||||
trapezoid.xTopLeft = trapezoid.xBottomLeft = 0;
|
||||
trapezoid.yTop = aYOffset;
|
||||
trapezoid.xTopRight = trapezoid.xBottomRight = aMaxSize.width;
|
||||
trapezoid.yBottom = aYOffset + PR_MIN(band->y - y, aMaxSize.height);
|
||||
trapezoid.state = nsBandTrapezoid::smAvailable;
|
||||
trapezoid.frame = nsnull;
|
||||
// The band is below the y-offset. The area between the y-offset and
|
||||
// the top of the band is available
|
||||
aBandData.count = 1;
|
||||
aBandData.trapezoids[0] =
|
||||
nsRect(0, aYOffset, aMaxSize.width, PR_MIN(band->y - y, aMaxSize.height));
|
||||
aBandData.trapezoids[0].state = nsBandTrapezoid::smAvailable;
|
||||
aBandData.trapezoids[0].frame = nsnull;
|
||||
break;
|
||||
} else if (y < band->YMost()) {
|
||||
// The band contains the y-offset
|
||||
return GetBandAvailableSpace(band, i, y, aMaxSize, aAvailableSpace);
|
||||
// The band contains the y-offset. Return a list of available and
|
||||
// unavailable rects within the band
|
||||
return GetBandAvailableSpace(band, i, y, aMaxSize, aBandData);
|
||||
} else {
|
||||
// Skip to the next band
|
||||
GetNextBand(band, i);
|
||||
|
@ -194,7 +202,7 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
}
|
||||
}
|
||||
|
||||
return aAvailableSpace.count;
|
||||
return aBandData.count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +215,7 @@ PRInt32 SpaceManager::GetBandData(nscoord aYOffset,
|
|||
* next band. If there is no next band then aRect is undefined
|
||||
* and aIndex is set to the number of rects in the rect array
|
||||
*/
|
||||
PRBool SpaceManager::GetNextBand(nsRect*& aRect, PRInt32& aIndex) const
|
||||
PRBool SpaceManager::GetNextBand(nsBandRect*& aRect, PRInt32& aIndex) const
|
||||
{
|
||||
nscoord topOfBand = aRect->y;
|
||||
|
||||
|
@ -231,7 +239,7 @@ PRBool SpaceManager::GetNextBand(nsRect*& aRect, PRInt32& aIndex) const
|
|||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
*/
|
||||
PRInt32 SpaceManager::LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const
|
||||
PRInt32 SpaceManager::LengthOfBand(const nsBandRect* aBand, PRInt32 aIndex) const
|
||||
{
|
||||
nscoord topOfBand = aBand->y;
|
||||
PRInt32 result = 1;
|
||||
|
@ -252,36 +260,48 @@ PRInt32 SpaceManager::LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const
|
|||
}
|
||||
|
||||
/**
|
||||
* Tries to coalesce horizontally overlapping rectangles within a band
|
||||
* Tries to coalesce adjoining rectangles within a band. Returns PR_TRUE if any
|
||||
* of the rects are coalesced and PR_FALSE otherwise
|
||||
*
|
||||
* @param aRect a rect in the band
|
||||
* @param aIndex aRect's index in the rect array
|
||||
* @param aRect the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
*/
|
||||
void SpaceManager::CoalesceBand(nsRect* aRect, PRInt32 aIndex)
|
||||
PRBool SpaceManager::CoalesceBand(nsBandRect* aBand, PRInt32 aIndex)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
while ((aIndex + 1) < mRectArray.mCount) {
|
||||
// Is there another rect in this band?
|
||||
nsRect* nextRect = aRect + 1;
|
||||
nsBandRect* nextRect = aBand + 1;
|
||||
|
||||
if (nextRect->y == aRect->y) {
|
||||
// Yes. Do the two rects overlap horizontally?
|
||||
if (aRect->XMost() > nextRect->x) {
|
||||
// Yes. Extend the right edge of aRect
|
||||
aRect->width = nextRect->XMost() - aRect->x;
|
||||
if (nextRect->y == aBand->y) {
|
||||
// The rects must not be overlapping
|
||||
NS_ASSERTION(nextRect->x >= aBand->XMost(), "overlapping rects");
|
||||
|
||||
// Are the two rects adjoining and have the same tagged frame?
|
||||
if ((aBand->XMost() == nextRect->x) && (aBand->frame == nextRect->frame)) {
|
||||
// Yes. Extend the right edge of the current rect
|
||||
aBand->width = nextRect->XMost() - aBand->x;
|
||||
|
||||
// Remove the next rect
|
||||
mRectArray.RemoveAt(aIndex + 1);
|
||||
aRect = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Continue through the loop trying to coalesce this rect
|
||||
result = PR_TRUE;
|
||||
|
||||
} else {
|
||||
// No. We're all done
|
||||
break;
|
||||
// No. Move to the next rect within the band
|
||||
aBand++;
|
||||
aIndex++;
|
||||
}
|
||||
} else {
|
||||
// The next rect is part of a different band, so we're all done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,7 +311,7 @@ void SpaceManager::CoalesceBand(nsRect* aRect, PRInt32 aIndex)
|
|||
* @param aIndex aBand's index in the rect array
|
||||
* @param aB1Height the height of the new band to create
|
||||
*/
|
||||
void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
||||
void SpaceManager::DivideBand(nsBandRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
||||
{
|
||||
NS_PRECONDITION(aB1Height < aBand->height, "bad height");
|
||||
|
||||
|
@ -305,7 +325,7 @@ void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
|||
// Insert a new bottom band
|
||||
nsRect r(aBand->x, aBand->y + aB1Height, aBand->width, aB2Height);
|
||||
|
||||
mRectArray.InsertAt(r, insertAt);
|
||||
mRectArray.InsertAt(r, insertAt, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Adjust the height of the top band
|
||||
|
@ -322,62 +342,127 @@ void SpaceManager::DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height)
|
|||
*
|
||||
* @param aBand the first rect in the band
|
||||
* @param aIndex aBand's index in the rect array
|
||||
* @param aRect the rect to add to the band
|
||||
* @param aRect the rect to add to the band. It's in world coordinates
|
||||
* @returns PR_TRUE if successful and PR_FALSE if this is the last band
|
||||
*/
|
||||
void SpaceManager::AddRectToBand(nsRect* aBand,
|
||||
void SpaceManager::AddRectToBand(nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
const nsRect& aRect)
|
||||
const nsRect& aRect,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION((aBand->y == aRect.y) && (aBand->height == aRect.height), "bad band");
|
||||
|
||||
nscoord topOfBand = aBand->y;
|
||||
nsRect rect(aRect);
|
||||
|
||||
// Figure out where in the band to horizontally insert the rect. Try and
|
||||
// coalesce it with an existing rect if possible.
|
||||
// Figure out where in the band horizontally to insert the rect. Try and
|
||||
// coalesce it with an existing rect if possible. We can only do this if
|
||||
// they're tagged with the same frame
|
||||
do {
|
||||
// Compare the left edge of the new rect with the left edge of the existing
|
||||
// rect
|
||||
if (aRect.x <= aBand->x) {
|
||||
// The new rect's left edge is to the left of the existing rect's left
|
||||
// edge. Does the new rect overlap the existing rect?
|
||||
if (aRect.XMost() >= aBand->x) {
|
||||
// Yes. Extend the existing rect
|
||||
if (aRect.XMost() > aBand->XMost()) {
|
||||
aBand->x = aRect.x;
|
||||
aBand->width = aRect.width;
|
||||
|
||||
// We're extending the right edge of the existing rect which may
|
||||
// cause the rect to overlap the remaining rects in the band
|
||||
CoalesceBand(aBand, aIndex);
|
||||
} else {
|
||||
aBand->width = aBand->XMost() - aRect.x;
|
||||
aBand->x = aRect.x;
|
||||
}
|
||||
} else {
|
||||
// No, it's completely to the left of the existing rect. Insert a new
|
||||
// rect
|
||||
mRectArray.InsertAt(aRect, aIndex);
|
||||
if (rect.x < aBand->x) {
|
||||
// The new rect's left edge is to the left of the existing rect's left edge.
|
||||
// Could be any of these cases (N is new rect, E is existing rect):
|
||||
//
|
||||
// Case 1: left-of Case 2: overlaps Case 3: N.contains(E)
|
||||
// --------------- ---------------- ---------------------
|
||||
// +-----+ +-----+ +-----+ +---------+
|
||||
// | N | | E | | N | | N |
|
||||
// +-----+ +-----+ +-----+ +---------+
|
||||
// +-----+ +---+
|
||||
// | E | | E |
|
||||
// +-----+ +---+
|
||||
//
|
||||
// Do the two rectangles overlap?
|
||||
if (rect.XMost() <= aBand->x) {
|
||||
// No, the new rect is completely to the left of the existing rect
|
||||
// (case #1). Insert a new rect
|
||||
mRectArray.InsertAt(rect, aIndex, aFrame);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
} else if (aRect.x <= aBand->XMost()) {
|
||||
// The two rects are overlapping or adjoining. Extend the right edge of
|
||||
// the existing rect
|
||||
aBand->width = aRect.XMost() - aBand->x;
|
||||
// Yes, they overlap. Insert a new rect for the part that's to the left
|
||||
// of the existing rect
|
||||
nsRect r1(rect.x, rect.y, aBand->x - rect.x, rect.height);
|
||||
|
||||
// Since we extended the right edge of the existing rect it may now
|
||||
// overlap the remaining rects in the band
|
||||
CoalesceBand(aBand, aIndex);
|
||||
mRectArray.InsertAt(r1, aIndex, aFrame);
|
||||
aIndex++;
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
|
||||
// Adjust rect to reflect the overlap
|
||||
rect.width = rect.XMost() - aBand->x;
|
||||
rect.x = aBand->x;
|
||||
|
||||
} else if (rect.x > aBand->x) {
|
||||
// The new rect's left edge is to the right of the existing rect's left
|
||||
// edge. Could be any one of these cases:
|
||||
//
|
||||
// Case 4: right-of Case 5: overlaps Case 6: E.Contains(N)
|
||||
// --------------- ---------------- ---------------------
|
||||
// +-----+ +-----+ +-----+ +------------+
|
||||
// | E | | N | | E | | E |
|
||||
// +-----+ +-----+ +-----+ +------------+
|
||||
// +-----+ +-----+
|
||||
// | N | | N |
|
||||
// +-----+ +-----+
|
||||
//
|
||||
if (rect.x >= aBand->XMost()) {
|
||||
// The new rect is to the right of the existing rect (case #4), so move
|
||||
// to the next rect in the band
|
||||
aBand++; aIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The rects overlap, so divide the existing rect into two rects: the
|
||||
// part to the left of the new rect, and the part that overlaps
|
||||
nsRect r1(rect.x, aBand->y, aBand->XMost() - rect.x, aBand->height);
|
||||
|
||||
// Modify the left half of the existing rect
|
||||
aBand->width = rect.x - aBand->x;
|
||||
|
||||
// Insert the new right half of the existing rect, and make it the current
|
||||
// rect
|
||||
aIndex++;
|
||||
mRectArray.InsertAt(r1, aIndex, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
}
|
||||
|
||||
// At this point the left edge of the new rect is the same as the left edge
|
||||
// of the existing rect
|
||||
NS_ASSERTION(rect.x == aBand->x, "unexpected rect");
|
||||
|
||||
// Compare which rect is wider, the new rect or the existing rect
|
||||
if (aBand->width > rect.width) {
|
||||
// The existing rect is wider (cases 2 and 6). Divide the existing rect
|
||||
// into two rects: the part that overlaps, and the part to the right of
|
||||
// the new rect
|
||||
nsRect r1(rect.XMost(), aBand->y, aBand->XMost() - rect.XMost(), aBand->height);
|
||||
|
||||
// Modify the left half of the existing rect
|
||||
aBand->width = r1.x - aBand->x;
|
||||
|
||||
// Insert the new right half of the existing rect
|
||||
mRectArray.InsertAt(r1, aIndex, aBand->frame);
|
||||
aBand = mRectArray.mRects + aIndex; // memory may have changed...
|
||||
}
|
||||
|
||||
// XXX Mark the existing rect as being shared by the two frames...
|
||||
|
||||
if (rect.width == aBand->width) {
|
||||
// We're all done
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to the next rect in the band
|
||||
// The new rect is wider than the existing rect (cases 3 and 5). Set rect
|
||||
// to be the overhang and move to the next rect within the band
|
||||
rect.width = rect.XMost() - aBand->XMost();
|
||||
rect.x = aBand->XMost();
|
||||
aBand++; aIndex++;
|
||||
} while ((aIndex < mRectArray.mCount) && (aBand->y == topOfBand));
|
||||
|
||||
// Insert a new rect
|
||||
mRectArray.InsertAt(aRect, aIndex);
|
||||
mRectArray.InsertAt(aRect, aIndex, aFrame);
|
||||
}
|
||||
|
||||
// When comparing a rect to a band there are seven cases to consider.
|
||||
|
@ -417,12 +502,12 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
// then add a new band
|
||||
if ((0 == mRectArray.mCount) || (rect.y >= mRectArray.YMost())) {
|
||||
// Append a new bottommost band
|
||||
mRectArray.Append(rect);
|
||||
mRectArray.Append(rect, aFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
// Examine each band looking for a band that intersects this rect
|
||||
nsRect* band = mRectArray.mRects;
|
||||
nsBandRect* band = mRectArray.mRects;
|
||||
|
||||
for (PRInt32 i = 0; i < mRectArray.mCount; ) {
|
||||
// Compare the top edge of this rect with the top edge of the band
|
||||
|
@ -432,7 +517,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
if (rect.YMost() <= band->y) {
|
||||
// Case #1. This rect is completely above the band, so insert a
|
||||
// new band
|
||||
mRectArray.InsertAt(rect, i);
|
||||
mRectArray.InsertAt(rect, i, aFrame);
|
||||
break; // we're all done
|
||||
}
|
||||
|
||||
|
@ -441,7 +526,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
nsRect r1(rect.x, rect.y, rect.width, band->y - rect.y);
|
||||
|
||||
// Insert r1 as a new band
|
||||
mRectArray.InsertAt(r1, i);
|
||||
mRectArray.InsertAt(r1, i, aFrame);
|
||||
i++;
|
||||
band = mRectArray.mRects + i; // memory may have changed...
|
||||
|
||||
|
@ -480,7 +565,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
|
||||
if (rect.height == band->height) {
|
||||
// Add the rect to the band
|
||||
AddRectToBand(band, i, rect);
|
||||
AddRectToBand(band, i, rect, aFrame);
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
@ -489,7 +574,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
nsRect r1(rect.x, rect.y, rect.width, band->YMost() - rect.y);
|
||||
|
||||
// Add r1 to the band
|
||||
AddRectToBand(band, i, r1);
|
||||
AddRectToBand(band, i, r1, aFrame);
|
||||
band = mRectArray.mRects + i; // memory may have changed...
|
||||
|
||||
// Modify rect to be the part below the band
|
||||
|
@ -499,7 +584,7 @@ void SpaceManager::AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFra
|
|||
// Continue with the next band
|
||||
if (!GetNextBand(band, i)) {
|
||||
// Append a new bottommost band
|
||||
mRectArray.Append(rect);
|
||||
mRectArray.Append(rect, aFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -532,29 +617,40 @@ nscoord SpaceManager::RectArray::YMost() const
|
|||
return mRects[mCount - 1].YMost();
|
||||
}
|
||||
|
||||
void SpaceManager::RectArray::Append(const nsRect& aRect)
|
||||
void SpaceManager::RectArray::Append(const nsRect& aRect, nsIFrame* aFrame)
|
||||
{
|
||||
// Ensure there's enough capacity
|
||||
if (mCount >= mMax) {
|
||||
mMax += 8;
|
||||
mRects = (nsRect*)realloc(mRects, mMax * sizeof(nsRect));
|
||||
mRects = (nsBandRect*)realloc(mRects, mMax * sizeof(nsBandRect));
|
||||
}
|
||||
|
||||
mRects[mCount++] = aRect;
|
||||
mRects[mCount].x = aRect.x;
|
||||
mRects[mCount].y = aRect.y;
|
||||
mRects[mCount].width = aRect.width;
|
||||
mRects[mCount].height = aRect.height;
|
||||
mRects[mCount].frame = aFrame;
|
||||
mCount++;
|
||||
}
|
||||
|
||||
void SpaceManager::RectArray::InsertAt(const nsRect& aRect, PRInt32 aIndex)
|
||||
void SpaceManager::RectArray::InsertAt(const nsRect& aRect,
|
||||
PRInt32 aIndex,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
NS_PRECONDITION(aIndex <= mCount, "bad index"); // no holes in the array
|
||||
|
||||
// Ensure there's enough capacity
|
||||
if (mCount >= mMax) {
|
||||
mMax += 8;
|
||||
mRects = (nsRect*)realloc(mRects, mMax * sizeof(nsRect));
|
||||
mRects = (nsBandRect*)realloc(mRects, mMax * sizeof(nsBandRect));
|
||||
}
|
||||
|
||||
memmove(&mRects[aIndex + 1], &mRects[aIndex], (mCount - aIndex) * sizeof(nsRect));
|
||||
mRects[aIndex] = aRect;
|
||||
memmove(&mRects[aIndex + 1], &mRects[aIndex], (mCount - aIndex) * sizeof(nsBandRect));
|
||||
mRects[aIndex].x = aRect.x;
|
||||
mRects[aIndex].y = aRect.y;
|
||||
mRects[aIndex].width = aRect.width;
|
||||
mRects[aIndex].height = aRect.height;
|
||||
mRects[aIndex].frame = aFrame;
|
||||
mCount++;
|
||||
}
|
||||
|
||||
|
@ -564,7 +660,7 @@ void SpaceManager::RectArray::RemoveAt(PRInt32 aIndex)
|
|||
|
||||
mCount--;
|
||||
if (aIndex < mCount) {
|
||||
memmove(&mRects[aIndex], &mRects[aIndex + 1], (mCount - aIndex) * sizeof(nsRect));
|
||||
memmove(&mRects[aIndex], &mRects[aIndex + 1], (mCount - aIndex) * sizeof(nsBandRect));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,19 +38,23 @@ public:
|
|||
virtual nscoord YMost() const;
|
||||
virtual PRInt32 GetBandData(nscoord aYOffset,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
nsBandData& aBandData) const;
|
||||
virtual void AddRectRegion(const nsRect& aUnavailableSpace, nsIFrame* aFrame);
|
||||
virtual void ClearRegions();
|
||||
|
||||
protected:
|
||||
struct nsBandRect : nsRect {
|
||||
nsIFrame* frame;
|
||||
};
|
||||
|
||||
class RectArray {
|
||||
public:
|
||||
RectArray();
|
||||
~RectArray();
|
||||
|
||||
// Functions to add rects
|
||||
void Append(const nsRect& aRect);
|
||||
void InsertAt(const nsRect& aRect, PRInt32 aIndex);
|
||||
void Append(const nsRect& aRect, nsIFrame* aFrame);
|
||||
void InsertAt(const nsRect& aRect, PRInt32 aIndex, nsIFrame* aFrame);
|
||||
void RemoveAt(PRInt32 aIndex);
|
||||
|
||||
// Clear the list of rectangles
|
||||
|
@ -61,9 +65,9 @@ protected:
|
|||
|
||||
public:
|
||||
// Access to the underlying storage
|
||||
nsRect* mRects; // y-x banded array of rectangles of unavailable space
|
||||
PRInt32 mCount; // current number of rects
|
||||
PRInt32 mMax; // capacity of rect array
|
||||
nsBandRect* mRects; // y-x banded array of rectangles of unavailable space
|
||||
PRInt32 mCount; // current number of rects
|
||||
PRInt32 mMax; // capacity of rect array
|
||||
};
|
||||
|
||||
nsIFrame* const mFrame; // frame associated with the space manager
|
||||
|
@ -71,16 +75,17 @@ protected:
|
|||
RectArray mRectArray; // y-x banded array of rectangles of unavailable space
|
||||
|
||||
protected:
|
||||
PRBool GetNextBand(nsRect*& aRect, PRInt32& aIndex) const;
|
||||
PRInt32 LengthOfBand(const nsRect* aBand, PRInt32 aIndex) const;
|
||||
void CoalesceBand(nsRect* aBand, PRInt32 aIndex);
|
||||
void DivideBand(nsRect* aBand, PRInt32 aIndex, nscoord aB1Height);
|
||||
void AddRectToBand(nsRect* aBand, PRInt32 aIndex, const nsRect& aRect);
|
||||
PRInt32 GetBandAvailableSpace(const nsRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
PRBool GetNextBand(nsBandRect*& aRect, PRInt32& aIndex) const;
|
||||
PRInt32 LengthOfBand(const nsBandRect* aBand, PRInt32 aIndex) const;
|
||||
PRBool CoalesceBand(nsBandRect* aBand, PRInt32 aIndex);
|
||||
void DivideBand(nsBandRect* aBand, PRInt32 aIndex, nscoord aB1Height);
|
||||
void AddRectToBand(nsBandRect* aBand, PRInt32 aIndex,
|
||||
const nsRect& aRect, nsIFrame* aFrame);
|
||||
PRInt32 GetBandAvailableSpace(const nsBandRect* aBand,
|
||||
PRInt32 aIndex,
|
||||
nscoord aY,
|
||||
const nsSize& aMaxSize,
|
||||
nsBandData& aAvailableSpace) const;
|
||||
|
||||
private:
|
||||
SpaceManager(const SpaceManager&); // no implementation
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
|
@ -59,11 +59,68 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
NS_DEF_PTR(nsIContent);
|
||||
|
||||
struct BlockBandData : public nsBandData {
|
||||
nsBandTrapezoid data[5];
|
||||
nsBandTrapezoid data[12];
|
||||
|
||||
BlockBandData() {size = 5; trapezoids = data;}
|
||||
// Bounding rect of available space between any left and right floaters
|
||||
nsRect availSpace;
|
||||
|
||||
// Constructor
|
||||
BlockBandData() {size = 12; trapezoids = data;}
|
||||
|
||||
// Computes the bounding rect of the available space, i.e. space between
|
||||
// any left and right floaters
|
||||
//
|
||||
// Uses the current trapezoid data, see nsISpaceManager::GetBandData().
|
||||
// Updates member data "availSpace"
|
||||
void ComputeAvailSpaceRect();
|
||||
};
|
||||
|
||||
void BlockBandData::ComputeAvailSpaceRect()
|
||||
{
|
||||
nsBandTrapezoid* trapezoid = data;
|
||||
|
||||
if (count > 1) {
|
||||
// If there's more than one trapezoid that means there are floaters
|
||||
PRInt32 i;
|
||||
|
||||
// Stop when we get to space occupied by a right floater
|
||||
for (i = 0; i < count; i++) {
|
||||
nsBandTrapezoid* trapezoid = &data[i];
|
||||
|
||||
if (trapezoid->state != nsBandTrapezoid::smAvailable) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
trapezoid = &data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (nsBandTrapezoid::smAvailable == trapezoid->state) {
|
||||
// The trapezoid is available
|
||||
trapezoid->GetRect(availSpace);
|
||||
} else {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
// The trapezoid is occupied. That means there's no available space
|
||||
trapezoid->GetRect(availSpace);
|
||||
|
||||
// XXX Handle the case of multiple frames
|
||||
trapezoid->frame->GetStyleData(kStyleDisplaySID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
availSpace.x = availSpace.XMost();
|
||||
}
|
||||
availSpace.width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Bugs
|
||||
// 1. right to left reflow can generate negative x coordinates.
|
||||
|
||||
|
@ -366,13 +423,13 @@ void nsBlockFrame::PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
|
|||
styleContext->GetData(kStyleDisplaySID);
|
||||
|
||||
floater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == sd->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == sd->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
@ -682,9 +739,9 @@ void nsBlockFrame::GetAvailSize(nsSize& aResult,
|
|||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (aIsInline) {
|
||||
if (NS_STYLE_DIRECTION_LTR == aState.styleDisplay->mDirection) {
|
||||
aResult.width = aState.currentBand->trapezoids[0].xTopRight - aState.x;
|
||||
aResult.width = aState.currentBand->availSpace.XMost() - aState.x;
|
||||
} else {
|
||||
aResult.width = aState.x - aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aResult.width = aState.x - aState.currentBand->availSpace.x;
|
||||
}
|
||||
} else {
|
||||
// It's a block. Don't adjust for the left/right margin here. That happens
|
||||
|
@ -767,31 +824,11 @@ void nsBlockFrame::GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY)
|
|||
aState.spaceManager->Translate(aState.borderPadding.left, 0);
|
||||
aState.spaceManager->GetBandData(aY, aState.availSize, *aState.currentBand);
|
||||
|
||||
// XXX This is hack code that needs to change when the space manager interface
|
||||
// changes to return both the available and unavailable space
|
||||
//
|
||||
// We'll get back anywhere between 1 and 3 rects depending on how many floaters
|
||||
// there are. Actually the way it currently works we could get back zero rects
|
||||
// if there are overlapping left and right floaters occupying all the space
|
||||
if (aState.currentBand->count > 1) {
|
||||
// If there are three rects then let's assume that there are floaters on the
|
||||
// left and right and that only the middle rect is available
|
||||
if (aState.currentBand->count == 3) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
} else {
|
||||
nsRect r0, r1;
|
||||
|
||||
// There are two rects. That means either a left or right floater. Just use
|
||||
// whichever space is larger.
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r1.width > r0.width) {
|
||||
aState.currentBand->trapezoids[0] = aState.currentBand->trapezoids[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the bounding rect of the available space, i.e. space between any
|
||||
// left and right floaters
|
||||
aState.currentBand->ComputeAvailSpaceRect();
|
||||
aState.spaceManager->Translate(-aState.borderPadding.left, 0);
|
||||
aState.x = aState.currentBand->trapezoids[0].xTopLeft;
|
||||
aState.x = aState.currentBand->availSpace.x;
|
||||
}
|
||||
|
||||
void nsBlockFrame::ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear)
|
||||
|
@ -807,39 +844,22 @@ getBand:
|
|||
// Get a band of available space
|
||||
aState.spaceManager->GetBandData(y, aState.availSize, *aState.currentBand);
|
||||
|
||||
if (aState.currentBand->count == 1) {
|
||||
nsRect rect;
|
||||
// Scan the trapezoids looking for left and right floaters
|
||||
nsBandTrapezoid* trapezoid = aState.currentBand->trapezoids;
|
||||
for (PRInt32 i = 0; i < aState.currentBand->count; i++) {
|
||||
// XXX Handle multiply occupied
|
||||
if (nsBandTrapezoid::smOccupied == trapezoid->state) {
|
||||
nsStyleDisplay* display;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(rect);
|
||||
if (rect.width != aState.availSize.width) {
|
||||
// Some of the space is taken up by floaters
|
||||
if (rect.x > 0) {
|
||||
trapezoid->frame->GetStyleData(kStylePositionSID, (nsStyleStruct*&)display);
|
||||
if (NS_STYLE_FLOAT_LEFT == display->mFloats) {
|
||||
isLeftFloater = PR_TRUE;
|
||||
}
|
||||
|
||||
if (rect.XMost() < aState.availSize.width) {
|
||||
} else if (NS_STYLE_FLOAT_RIGHT == display->mFloats) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aState.currentBand->count == 2) {
|
||||
nsRect r0, r1;
|
||||
|
||||
aState.currentBand->trapezoids[0].GetRect(r0);
|
||||
aState.currentBand->trapezoids[1].GetRect(r1);
|
||||
if (r0.width > r1.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
} else {
|
||||
isLeftFloater = PR_TRUE;
|
||||
|
||||
// There may also be a right floater
|
||||
if (r1.XMost() < aState.availSize.width) {
|
||||
isRightFloater = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be both left and right floaters
|
||||
isLeftFloater = PR_TRUE;
|
||||
isRightFloater = PR_TRUE;
|
||||
trapezoid++;
|
||||
}
|
||||
|
||||
if (isLeftFloater) {
|
||||
|
@ -1988,13 +2008,13 @@ void nsBlockFrame::PlaceFloater(nsIPresContext* aCX,
|
|||
nsRect region;
|
||||
|
||||
aFloater->GetRect(region);
|
||||
region.y = mCurrentState->currentBand->trapezoids[0].yTop;
|
||||
region.y = mCurrentState->currentBand->availSpace.y;
|
||||
|
||||
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopLeft;
|
||||
region.x = mCurrentState->currentBand->availSpace.x;
|
||||
} else {
|
||||
NS_ASSERTION(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats, "bad float type");
|
||||
region.x = mCurrentState->currentBand->trapezoids[0].xTopRight - region.width;
|
||||
region.x = mCurrentState->currentBand->availSpace.XMost() - region.width;
|
||||
}
|
||||
|
||||
// XXX Don't forget the floater's margins...
|
||||
|
|
Загрузка…
Ссылка в новой задаче