зеркало из https://github.com/mozilla/pjs.git
Fix bug 416073: invalidate more things as needed during table reflow to prevent glitches. r+sr=roc
This commit is contained in:
Родитель
7d5dd48b52
Коммит
d6526d103e
|
@ -2486,3 +2486,21 @@ nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
|
|||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutUtils::GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
|
||||
nsRect* aHStrip, nsRect* aVStrip) {
|
||||
NS_ASSERTION(aR1.TopLeft() == aR2.TopLeft(),
|
||||
"expected rects at the same position");
|
||||
nsRect unionRect(aR1.x, aR1.y, PR_MAX(aR1.width, aR2.width),
|
||||
PR_MAX(aR1.height, aR2.height));
|
||||
nscoord VStripStart = PR_MIN(aR1.width, aR2.width);
|
||||
nscoord HStripStart = PR_MIN(aR1.height, aR2.height);
|
||||
*aVStrip = unionRect;
|
||||
aVStrip->x += VStripStart;
|
||||
aVStrip->width -= VStripStart;
|
||||
*aHStrip = unionRect;
|
||||
aHStrip->y += HStripStart;
|
||||
aHStrip->height -= HStripStart;
|
||||
}
|
||||
|
||||
|
|
|
@ -754,6 +754,15 @@ public:
|
|||
const nsStyleText* aStyleText,
|
||||
const nsStyleFont* aStyleFont);
|
||||
|
||||
/**
|
||||
* Takes two rectangles whose origins must be the same, and computes
|
||||
* the difference between their union and their intersection as two
|
||||
* rectangles. (This difference is a superset of the difference
|
||||
* between the two rectangles.)
|
||||
*/
|
||||
static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
|
||||
nsRect* aHStrip, nsRect* aVStrip);
|
||||
|
||||
/**
|
||||
* Indicates if the nsIFrame::GetUsedXXX assertions in nsFrame.cpp should
|
||||
* disabled.
|
||||
|
|
|
@ -2234,28 +2234,6 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two rectangles whose origins must be the same, and computes
|
||||
* the difference between their union and their intersection as two
|
||||
* rectangles. (This difference is a superset of the difference
|
||||
* between the two rectangles.)
|
||||
*/
|
||||
static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
|
||||
nsRect* aHStrip, nsRect* aVStrip) {
|
||||
NS_ASSERTION(aR1.TopLeft() == aR2.TopLeft(),
|
||||
"expected rects at the same position");
|
||||
nsRect unionRect(aR1.x, aR1.y, PR_MAX(aR1.width, aR2.width),
|
||||
PR_MAX(aR1.height, aR2.height));
|
||||
nscoord VStripStart = PR_MIN(aR1.width, aR2.width);
|
||||
nscoord HStripStart = PR_MIN(aR1.height, aR2.height);
|
||||
*aVStrip = unionRect;
|
||||
aVStrip->x += VStripStart;
|
||||
aVStrip->width -= VStripStart;
|
||||
*aHStrip = unionRect;
|
||||
aHStrip->y += HStripStart;
|
||||
aHStrip->height -= HStripStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reflow a line. The line will either contain a single block frame
|
||||
* or contain 1 or more inline frames. aKeepReflowGoing indicates
|
||||
|
@ -2305,10 +2283,11 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||
} else {
|
||||
nsRect combinedAreaHStrip, combinedAreaVStrip;
|
||||
nsRect boundsHStrip, boundsVStrip;
|
||||
GetRectDifferenceStrips(oldBounds, newBounds,
|
||||
nsLayoutUtils::GetRectDifferenceStrips(oldBounds, newBounds,
|
||||
&boundsHStrip, &boundsVStrip);
|
||||
GetRectDifferenceStrips(oldCombinedArea, lineCombinedArea,
|
||||
&combinedAreaHStrip, &combinedAreaVStrip);
|
||||
nsLayoutUtils::GetRectDifferenceStrips(oldCombinedArea, lineCombinedArea,
|
||||
&combinedAreaHStrip,
|
||||
&combinedAreaVStrip);
|
||||
|
||||
#ifdef NOISY_BLOCK_INVALIDATE
|
||||
printf("%p invalidate boundsVStrip (%d, %d, %d, %d)\n",
|
||||
|
|
|
@ -743,6 +743,11 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|||
aKidFrame->WillReflow(aPresContext);
|
||||
|
||||
if (0 == (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
||||
if ((aFlags & NS_FRAME_INVALIDATE_ON_MOVE) &&
|
||||
!(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
aKidFrame->GetPosition() != nsPoint(aX, aY)) {
|
||||
aKidFrame->InvalidateOverflowRect();
|
||||
}
|
||||
aKidFrame->SetPosition(nsPoint(aX, aY));
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
#define NS_FRAME_NO_MOVE_FRAME (0x0002 | NS_FRAME_NO_MOVE_VIEW)
|
||||
#define NS_FRAME_NO_SIZE_VIEW 0x0004
|
||||
#define NS_FRAME_NO_VISIBILITY 0x0008
|
||||
// Only applies to ReflowChild: if true, invalidate the child if it's
|
||||
// being moved
|
||||
#define NS_FRAME_INVALIDATE_ON_MOVE 0x0010
|
||||
|
||||
class nsOverflowContinuationTracker;
|
||||
|
||||
|
|
|
@ -3600,6 +3600,21 @@ nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
|||
InvalidateInternal(aDamageRect, aX + mRect.x, aY + mRect.y, this, aImmediate);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2)
|
||||
{
|
||||
nsRect sizeHStrip, sizeVStrip;
|
||||
nsLayoutUtils::GetRectDifferenceStrips(aR1, aR2, &sizeHStrip, &sizeVStrip);
|
||||
Invalidate(sizeVStrip);
|
||||
Invalidate(sizeHStrip);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateOverflowRect()
|
||||
{
|
||||
Invalidate(GetOverflowRect());
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateRoot(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, PRBool aImmediate)
|
||||
|
|
|
@ -1655,6 +1655,21 @@ public:
|
|||
nscoord aOffsetX, nscoord aOffsetY,
|
||||
nsIFrame* aForChild, PRBool aImmediate);
|
||||
|
||||
/**
|
||||
* Take two rectangles in the coordinate system of this frame which
|
||||
* have the same origin and invalidate the difference between them.
|
||||
* This is a helper method to be used when a frame is being resized.
|
||||
*
|
||||
* @param aR1 the first rectangle
|
||||
* @param aR2 the second rectangle
|
||||
*/
|
||||
void InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2);
|
||||
|
||||
/**
|
||||
* Invalidate the overflow rect of this frame
|
||||
*/
|
||||
void InvalidateOverflowRect();
|
||||
|
||||
/**
|
||||
* Computes a rect that encompasses everything that might be painted by
|
||||
* this frame. This includes this frame, all its descendent frames, this
|
||||
|
|
|
@ -593,6 +593,11 @@ void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
|
|||
// if the content is larger than the cell height align from top
|
||||
kidYTop = PR_MAX(0, kidYTop);
|
||||
|
||||
if (kidYTop != kidRect.y) {
|
||||
// Invalidate at the old position first
|
||||
firstKid->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
firstKid->SetPosition(nsPoint(kidRect.x, kidYTop));
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
desiredSize.width = mRect.width;
|
||||
|
@ -604,6 +609,9 @@ void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
|
|||
// Make sure any child views are correctly positioned. We know the inner table
|
||||
// cell won't have a view
|
||||
nsContainerFrame::PositionChildViews(firstKid);
|
||||
|
||||
// Invalidate new overflow rect
|
||||
firstKid->InvalidateOverflowRect();
|
||||
}
|
||||
if (HasView()) {
|
||||
nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
|
||||
|
@ -861,15 +869,19 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
nsPoint kidOrigin(leftInset, topInset);
|
||||
nsRect origRect = firstKid->GetRect();
|
||||
PRBool firstReflow = (firstKid->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
ReflowChild(firstKid, aPresContext, kidSize, kidReflowState,
|
||||
kidOrigin.x, kidOrigin.y, 0, aStatus);
|
||||
kidOrigin.x, kidOrigin.y, NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
|
||||
if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
|
||||
// Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
|
||||
//XXX should paginate overflow as overflow, but not in this patch (bug 379349)
|
||||
NS_FRAME_SET_INCOMPLETE(aStatus);
|
||||
printf("Set table cell incomplete %p\n", this);
|
||||
}
|
||||
|
||||
// XXXbz is this invalidate actually needed, really?
|
||||
if (GetStateBits() & NS_FRAME_IS_DIRTY) {
|
||||
Invalidate(GetOverflowRect(), PR_FALSE);
|
||||
}
|
||||
|
@ -886,6 +898,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
|||
FinishReflowChild(firstKid, aPresContext, &kidReflowState, kidSize,
|
||||
kidOrigin.x, kidOrigin.y, 0);
|
||||
|
||||
nsTableFrame::InvalidateFrame(firstKid, origRect, firstReflow);
|
||||
|
||||
// first, compute the height which can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
|
||||
|
|
|
@ -1957,6 +1957,11 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
// Fulfill the promise InvalidateFrame makes.
|
||||
Invalidate(aDesiredSize.mOverflowArea);
|
||||
}
|
||||
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
|
@ -2578,13 +2583,18 @@ nsTableFrame::InitChildReflowState(nsHTMLReflowState& aReflowState)
|
|||
// aKidRect is relative to the upper-left origin of our frame
|
||||
void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nsHTMLReflowMetrics& aKidDesiredSize)
|
||||
nsHTMLReflowMetrics& aKidDesiredSize,
|
||||
const nsRect& aOriginalKidRect)
|
||||
{
|
||||
PRBool isFirstReflow =
|
||||
(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
// Place and size the child
|
||||
FinishReflowChild(aKidFrame, PresContext(), nsnull, aKidDesiredSize,
|
||||
aReflowState.x, aReflowState.y, 0);
|
||||
|
||||
InvalidateFrame(aKidFrame, aOriginalKidRect, isFirstReflow);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += aKidDesiredSize.height;
|
||||
|
||||
|
@ -2936,7 +2946,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||
reorder = PR_TRUE;
|
||||
|
||||
rv = ReflowChild(kidFrame, presContext, desiredSize, kidReflowState,
|
||||
aReflowState.x, aReflowState.y, 0, aStatus);
|
||||
aReflowState.x, aReflowState.y,
|
||||
NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
|
||||
|
||||
if (reorder) {
|
||||
// reorder row groups the reflow may have changed the nextinflows
|
||||
|
@ -2957,7 +2968,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||
if (childX+1 < rowGroups.Length()) {
|
||||
nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
|
||||
if (nextRowGroupFrame) {
|
||||
PlaceChild(aReflowState, kidFrame, desiredSize);
|
||||
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect);
|
||||
aStatus = NS_FRAME_NOT_COMPLETE;
|
||||
PushChildren(rowGroups, childX + 1);
|
||||
aLastChildReflowed = kidFrame;
|
||||
|
@ -2988,7 +2999,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||
}
|
||||
|
||||
// Place the child
|
||||
PlaceChild(aReflowState, kidFrame, desiredSize);
|
||||
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect);
|
||||
|
||||
// Remember where we just were in case we end up pushing children
|
||||
prevKidFrame = kidFrame;
|
||||
|
@ -3036,10 +3047,14 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||
-1, -1, PR_FALSE);
|
||||
InitChildReflowState(footerReflowState);
|
||||
aReflowState.y += cellSpacingY;
|
||||
|
||||
nsRect origTfootRect = tfoot->GetRect();
|
||||
|
||||
nsReflowStatus footerStatus;
|
||||
rv = ReflowChild(tfoot, presContext, desiredSize, footerReflowState,
|
||||
aReflowState.x, aReflowState.y, 0, footerStatus);
|
||||
PlaceChild(aReflowState, tfoot, desiredSize);
|
||||
aReflowState.x, aReflowState.y,
|
||||
NS_FRAME_INVALIDATE_ON_MOVE, footerStatus);
|
||||
PlaceChild(aReflowState, tfoot, desiredSize, origTfootRect);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3048,11 +3063,13 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
|||
aReflowState.y += cellSpacingY;
|
||||
nsRect kidRect = kidFrame->GetRect();
|
||||
if (kidRect.y != aReflowState.y) {
|
||||
Invalidate(kidRect); // invalidate the old position
|
||||
// invalidate the old position
|
||||
kidFrame->InvalidateOverflowRect();
|
||||
kidRect.y = aReflowState.y;
|
||||
kidFrame->SetRect(kidRect); // move to the new position
|
||||
RePositionViews(kidFrame);
|
||||
Invalidate(kidRect); // invalidate the new position
|
||||
// invalidate the new position
|
||||
kidFrame->InvalidateOverflowRect();
|
||||
}
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
|
@ -3226,7 +3243,9 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
nscoord pctHeight = rowFrame->GetHeight(pctBasis);
|
||||
nscoord amountForRow = PR_MIN(aAmount - amountUsed, pctHeight - rowRect.height);
|
||||
if (amountForRow > 0) {
|
||||
nsRect oldRowRect = rowRect;
|
||||
rowRect.height += amountForRow;
|
||||
// XXXbz we don't need to change rowRect.y to be yOriginRow?
|
||||
rowFrame->SetRect(rowRect);
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
|
@ -3234,12 +3253,17 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
amountUsedByRG += amountForRow;
|
||||
//rowFrame->DidResize();
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
|
||||
rgFrame->InvalidateRectDifference(oldRowRect, rowRect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
if (amountUsed > 0 && yOriginRow != rowRect.y &&
|
||||
!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
|
@ -3247,15 +3271,27 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
if (rgRect.y != yOriginRG) {
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
nsRect origRgRect = rgRect;
|
||||
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
|
||||
rgFrame->SetRect(rgRect);
|
||||
|
||||
nsTableFrame::InvalidateFrame(rgFrame, origRgRect, PR_FALSE);
|
||||
}
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
else if (amountUsed > 0 && yOriginRG != rgFrame->GetPosition().y) {
|
||||
NS_ASSERTION(rgFrame->GetPosition().x == 0, "Unexpected position");
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
rgFrame->SetPosition(nsPoint(0, yOriginRG));
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(rgFrame);
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
@ -3360,9 +3396,16 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
nscoord amountForRow = (rowFrame == lastEligibleRow)
|
||||
? aAmount - amountUsed : NSToCoordRound(((float)(heightToDistribute)) * ratio);
|
||||
amountForRow = PR_MIN(amountForRow, aAmount - amountUsed);
|
||||
|
||||
if (yOriginRow != rowRect.y) {
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
// update the row height
|
||||
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width, rowRect.height + amountForRow);
|
||||
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width,
|
||||
rowRect.height + amountForRow);
|
||||
rowFrame->SetRect(newRowRect);
|
||||
|
||||
yOriginRow += newRowRect.height + cellSpacingY;
|
||||
yEndRG += newRowRect.height + cellSpacingY;
|
||||
|
||||
|
@ -3371,11 +3414,15 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
NS_ASSERTION((amountUsed <= aAmount), "invalid row allocation");
|
||||
//rowFrame->DidResize();
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
|
||||
nsTableFrame::InvalidateFrame(rowFrame, rowRect, PR_FALSE);
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
if (amountUsed > 0 && yOriginRow != rowRect.y) {
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
|
@ -3383,17 +3430,25 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
|||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
rgFrame->SetRect(rgRect);
|
||||
if (rgRect.y != yOriginRG) {
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
rgFrame->SetRect(nsRect(rgRect.x, yOriginRG, rgRect.width,
|
||||
rgRect.height + amountUsedByRG));
|
||||
|
||||
nsTableFrame::InvalidateFrame(rgFrame, rgRect, PR_FALSE);
|
||||
}
|
||||
// Make sure child views are properly positioned
|
||||
// XXX what happens if childFrame is a scroll frame and this gets skipped? see also below
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
else if (amountUsed > 0 && yOriginRG != rgFrame->GetPosition().y) {
|
||||
NS_ASSERTION(rgFrame->GetPosition().x == 0, "Unexpected position");
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
rgFrame->SetPosition(nsPoint(0, yOriginRG));
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(rgFrame);
|
||||
rgFrame->InvalidateOverflowRect();
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
@ -6718,6 +6773,27 @@ nsTableFrame::GetProperty(nsIFrame* aFrame,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsTableFrame::InvalidateFrame(nsIFrame* aFrame, const nsRect& aOrigRect,
|
||||
PRBool aIsFirstReflow)
|
||||
{
|
||||
nsIFrame* parent = aFrame->GetParent();
|
||||
NS_ASSERTION(parent, "What happened here?");
|
||||
|
||||
if (parent->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
// Don't bother; we'll invalidate the parent's overflow rect when
|
||||
// we finish reflowing it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aIsFirstReflow || aOrigRect.TopLeft() != aFrame->GetPosition()) {
|
||||
aFrame->InvalidateOverflowRect();
|
||||
} else {
|
||||
parent->InvalidateRectDifference(aOrigRect, aFrame->GetRect());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MAX_SIZE 128
|
||||
#define MIN_INDENT 30
|
||||
|
|
|
@ -480,6 +480,20 @@ public:
|
|||
PRBool HasCellSpanningPctCol() const;
|
||||
void SetHasCellSpanningPctCol(PRBool aValue);
|
||||
|
||||
/**
|
||||
* To be called on a frame by its parent after setting its size/position and
|
||||
* calling DidReflow (possibly via FinishReflowChild()). This can also be
|
||||
* used for child frames which are not being reflown but did have their size
|
||||
* or position changed.
|
||||
*
|
||||
* @param aFrame The frame to invalidate
|
||||
* @param aOrigRect The original rect of aFrame (before the change).
|
||||
* @param aIsFirstReflow True if the size/position change is due to the
|
||||
* first reflow of aFrame.
|
||||
*/
|
||||
static void InvalidateFrame(nsIFrame* aFrame, const nsRect& aOrigRect,
|
||||
PRBool aIsFirstReflow);
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
|
@ -567,7 +581,8 @@ protected:
|
|||
|
||||
void PlaceChild(nsTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nsHTMLReflowMetrics& aKidDesiredSize);
|
||||
nsHTMLReflowMetrics& aKidDesiredSize,
|
||||
const nsRect& aOriginalKidRect);
|
||||
|
||||
nsIFrame* GetFirstBodyRowGroupFrame();
|
||||
PRBool MoveOverflowToChildList(nsPresContext* aPresContext);
|
||||
|
|
|
@ -353,16 +353,24 @@ nsTableRowFrame::DidResize()
|
|||
nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
|
||||
|
||||
// resize the cell's height
|
||||
//if (cellFrameSize.height!=cellHeight)
|
||||
nsRect cellRect = cellFrame->GetRect();
|
||||
if (cellRect.height != cellHeight)
|
||||
{
|
||||
cellFrame->SetSize(nsSize(cellFrame->GetSize().width, cellHeight));
|
||||
// realign cell content based on the new height
|
||||
cellFrame->SetSize(nsSize(cellRect.width, cellHeight));
|
||||
nsTableFrame::InvalidateFrame(cellFrame, cellRect, PR_FALSE);
|
||||
}
|
||||
|
||||
// realign cell content based on the new height. We might be able to
|
||||
// skip this if the height didn't change... maybe. Hard to tell.
|
||||
cellFrame->VerticallyAlignChild(mMaxCellAscent);
|
||||
|
||||
// Always store the overflow, even if the height didn't change, since
|
||||
// we'll lose part of our overflow area otherwise.
|
||||
ConsiderChildOverflow(desiredSize.mOverflowArea, cellFrame);
|
||||
|
||||
// Note that if the cell's *content* needs to change in response
|
||||
// to this height, it will get a special height reflow.
|
||||
}
|
||||
}
|
||||
// Get the next child
|
||||
childFrame = iter.Next();
|
||||
}
|
||||
|
@ -855,6 +863,10 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
prevColIndex = (iter.IsLeftToRight()) ? cellColIndex + (cellColSpan - 1) : cellColIndex;
|
||||
|
||||
// Reflow the child frame
|
||||
nsRect kidRect = kidFrame->GetRect();
|
||||
PRBool firstReflow =
|
||||
(kidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
if (doReflowChild) {
|
||||
// Calculate the available width for the table cell using the known column widths
|
||||
nscoord availColWidth, availCellWidth;
|
||||
|
@ -889,7 +901,7 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
|
||||
nsReflowStatus status;
|
||||
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
|
||||
x, 0, 0, status);
|
||||
x, 0, NS_FRAME_INVALIDATE_ON_MOVE, status);
|
||||
|
||||
// allow the table to determine if/how the table needs to be rebalanced
|
||||
// If any of the cells are not complete, then we're not complete
|
||||
|
@ -898,6 +910,10 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (x != kidRect.x) {
|
||||
kidFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
desiredSize.width = cellDesiredSize.width;
|
||||
desiredSize.height = cellDesiredSize.height;
|
||||
nsRect *overflowArea =
|
||||
|
@ -950,16 +966,19 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
|
||||
FinishReflowChild(kidFrame, aPresContext, nsnull, desiredSize, x, 0, 0);
|
||||
|
||||
nsTableFrame::InvalidateFrame(kidFrame, kidRect, firstReflow);
|
||||
|
||||
x += desiredSize.width;
|
||||
}
|
||||
else {
|
||||
nsRect kidRect = kidFrame->GetRect();
|
||||
if (kidRect.x != x) {
|
||||
Invalidate(kidRect); // invalidate the old position
|
||||
kidRect.x = x;
|
||||
kidFrame->SetRect(kidRect); // move to the new position
|
||||
// Invalidate the old position
|
||||
kidFrame->InvalidateOverflowRect();
|
||||
// move to the new position
|
||||
kidFrame->SetPosition(nsPoint(x, kidRect.y));
|
||||
nsTableFrame::RePositionViews(kidFrame);
|
||||
Invalidate(kidRect); // invalidate the new position
|
||||
// invalidate the new position
|
||||
kidFrame->InvalidateOverflowRect();
|
||||
}
|
||||
// we need to account for the cell's width even if it isn't reflowed
|
||||
x += kidRect.width;
|
||||
|
@ -1066,9 +1085,9 @@ nsTableRowFrame::ReflowCellFrame(nsPresContext* aPresContext,
|
|||
ABORT1(NS_ERROR_NULL_POINTER);
|
||||
|
||||
// Reflow the cell frame with the specified height. Use the existing width
|
||||
nsSize cellSize = aCellFrame->GetSize();
|
||||
nsRect cellRect = aCellFrame->GetRect();
|
||||
|
||||
nsSize availSize(cellSize.width, aAvailableHeight);
|
||||
nsSize availSize(cellRect.width, aAvailableHeight);
|
||||
PRBool borderCollapse = ((nsTableFrame*)tableFrame->GetFirstInFlow())->IsBorderCollapse();
|
||||
nsTableCellReflowState cellReflowState(aPresContext, aReflowState,
|
||||
aCellFrame, availSize, PR_FALSE);
|
||||
|
@ -1083,7 +1102,11 @@ nsTableRowFrame::ReflowCellFrame(nsPresContext* aPresContext,
|
|||
if (fullyComplete) {
|
||||
desiredSize.height = aAvailableHeight;
|
||||
}
|
||||
aCellFrame->SetSize(nsSize(cellSize.width, desiredSize.height));
|
||||
aCellFrame->SetSize(nsSize(cellRect.width, desiredSize.height));
|
||||
|
||||
nsTableFrame::InvalidateFrame(aCellFrame, cellRect,
|
||||
(aCellFrame->GetStateBits() &
|
||||
NS_FRAME_FIRST_REFLOW) != 0);
|
||||
|
||||
// XXX What happens if this cell has 'vertical-align: baseline' ?
|
||||
// XXX Why is it assumed that the cell's ascent hasn't changed ?
|
||||
|
@ -1110,7 +1133,14 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
|||
tableFrame->SetNeedToCollapse(PR_TRUE);
|
||||
}
|
||||
|
||||
if (aRowOffset != 0) {
|
||||
// We're moving, so invalidate our old position
|
||||
InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
nsRect rowRect = GetRect();
|
||||
nsRect oldRect = rowRect;
|
||||
|
||||
rowRect.y -= aRowOffset;
|
||||
rowRect.width = aWidth;
|
||||
nsRect overflowArea(0, 0, 0, 0);
|
||||
|
@ -1124,6 +1154,13 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
|||
shift = rowRect.height + cellSpacingY;
|
||||
while (cellFrame) {
|
||||
nsRect cRect = cellFrame->GetRect();
|
||||
// If aRowOffset != 0, there's no point in invalidating the cells, since
|
||||
// we've already invalidated our overflow area. Note that we _do_ still
|
||||
// need to invalidate if our row is not moving, because the cell might
|
||||
// span out of this row, so invalidating our row rect won't do enough.
|
||||
if (aRowOffset == 0) {
|
||||
Invalidate(cRect);
|
||||
}
|
||||
cRect.height = 0;
|
||||
cellFrame->SetRect(cRect);
|
||||
cellFrame = cellFrame->GetNextCell();
|
||||
|
@ -1161,7 +1198,7 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
|||
*tableFrame, cellSpacingX, iter.IsLeftToRight(),
|
||||
PR_TRUE);
|
||||
}
|
||||
nsRect cRect(x, 0, 0,rowRect.height);
|
||||
nsRect cRect(x, 0, 0, rowRect.height);
|
||||
|
||||
// remember the rightmost (ltr) or leftmost (rtl) column this cell
|
||||
// spans into
|
||||
|
@ -1216,23 +1253,40 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
|||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
|
||||
nsRect oldCellRect = cellFrame->GetRect();
|
||||
|
||||
if (aRowOffset == 0 && cRect.TopLeft() != oldCellRect.TopLeft()) {
|
||||
// We're moving the cell. Invalidate the old overflow area
|
||||
cellFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
cellFrame->SetRect(cRect);
|
||||
|
||||
// XXXbz This looks completely bogus in the cases when we didn't
|
||||
// collapse the cell!
|
||||
nsRect cellOverflow = nsRect(0, 0, cRect.width, cRect.height);
|
||||
cellFrame->FinishAndStoreOverflow(&cellOverflow, nsSize(cRect.width,
|
||||
cRect.height));
|
||||
nsTableFrame::RePositionViews(cellFrame);
|
||||
ConsiderChildOverflow(overflowArea, cellFrame);
|
||||
|
||||
if (aRowOffset == 0) {
|
||||
nsTableFrame::InvalidateFrame(cellFrame, oldCellRect, PR_FALSE);
|
||||
}
|
||||
}
|
||||
kidFrame = iter.Next(); // Get the next child
|
||||
}
|
||||
}
|
||||
|
||||
SetRect(rowRect);
|
||||
overflowArea.UnionRect(nsRect(0,0,rowRect.width, rowRect.height),
|
||||
overflowArea);
|
||||
FinishAndStoreOverflow(&overflowArea, nsSize(rowRect.width,
|
||||
rowRect.height));
|
||||
|
||||
nsTableFrame::RePositionViews(this);
|
||||
nsTableFrame::InvalidateFrame(this, oldRect, PR_FALSE);
|
||||
return shift;
|
||||
}
|
||||
|
||||
|
|
|
@ -294,10 +294,17 @@ void
|
|||
nsTableRowGroupFrame::PlaceChild(nsPresContext* aPresContext,
|
||||
nsRowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsRect& aOriginalKidRect)
|
||||
{
|
||||
PRBool isFirstReflow =
|
||||
(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
// Place and size the child
|
||||
FinishReflowChild(aKidFrame, aPresContext, nsnull, aDesiredSize, 0, aReflowState.y, 0);
|
||||
FinishReflowChild(aKidFrame, aPresContext, nsnull, aDesiredSize, 0,
|
||||
aReflowState.y, 0);
|
||||
|
||||
nsTableFrame::InvalidateFrame(aKidFrame, aOriginalKidRect, isFirstReflow);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += aDesiredSize.height;
|
||||
|
@ -384,7 +391,7 @@ nsTableRowGroupFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
(aReflowState.reflowState.mFlags.mSpecialHeightReflow &&
|
||||
(isPaginated || (kidFrame->GetStateBits() &
|
||||
NS_FRAME_CONTAINS_RELATIVE_HEIGHT)))) {
|
||||
nsSize oldKidSize = kidFrame->GetSize();
|
||||
nsRect oldKidRect = kidFrame->GetRect();
|
||||
|
||||
// XXXldb We used to only pass aDesiredSize.mFlags through for the
|
||||
// incremental reflow codepath.
|
||||
|
@ -410,10 +417,12 @@ nsTableRowGroupFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
|
||||
0, aReflowState.y, 0, aStatus);
|
||||
0, aReflowState.y, NS_FRAME_INVALIDATE_ON_MOVE,
|
||||
aStatus);
|
||||
|
||||
// Place the child
|
||||
PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize);
|
||||
PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize,
|
||||
oldKidRect);
|
||||
aReflowState.y += cellSpacingY;
|
||||
|
||||
if (!reflowAllKids) {
|
||||
|
@ -436,7 +445,7 @@ nsTableRowGroupFrame::ReflowChildren(nsPresContext* aPresContext,
|
|||
Invalidate(dirtyRect);
|
||||
}
|
||||
}
|
||||
else if (oldKidSize.height != desiredSize.height)
|
||||
else if (oldKidRect.height != desiredSize.height)
|
||||
needToCalcRowHeights = PR_TRUE;
|
||||
} else {
|
||||
needToCalcRowHeights = PR_TRUE;
|
||||
|
@ -798,13 +807,19 @@ nsTableRowGroupFrame::CalculateRowHeights(nsPresContext* aPresContext,
|
|||
nscoord rowHeight = (rowInfo[rowIndex].height > 0) ? rowInfo[rowIndex].height : 0;
|
||||
|
||||
if (movedFrame || (rowHeight != rowBounds.height)) {
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.y = yOrigin;
|
||||
rowBounds.height = rowHeight;
|
||||
rowFrame->SetRect(rowBounds);
|
||||
// Resize/move the row to its final size and position
|
||||
if (movedFrame) {
|
||||
rowFrame->InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
rowFrame->SetRect(nsRect(rowBounds.x, yOrigin, rowBounds.width,
|
||||
rowHeight));
|
||||
|
||||
nsTableFrame::InvalidateFrame(rowFrame, rowBounds, PR_FALSE);
|
||||
}
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
// XXXbz we don't need to update our overflow area?
|
||||
}
|
||||
yOrigin += rowHeight + cellSpacingY;
|
||||
}
|
||||
|
@ -845,6 +860,8 @@ nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
|
|||
}
|
||||
|
||||
nsRect groupRect = GetRect();
|
||||
nsRect oldGroupRect = groupRect;
|
||||
|
||||
groupRect.height -= yGroupOffset;
|
||||
if (didCollapse) {
|
||||
// add back the cellspacing between rowgroups
|
||||
|
@ -853,12 +870,19 @@ nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
|
|||
|
||||
groupRect.y -= aYTotalOffset;
|
||||
groupRect.width = aWidth;
|
||||
|
||||
if (aYTotalOffset != 0) {
|
||||
InvalidateOverflowRect();
|
||||
}
|
||||
|
||||
SetRect(groupRect);
|
||||
overflowArea.UnionRect(nsRect(0, 0, groupRect.width, groupRect.height),
|
||||
overflowArea);
|
||||
FinishAndStoreOverflow(&overflowArea, nsSize(groupRect.width,
|
||||
groupRect.height));
|
||||
nsTableFrame::RePositionViews(this);
|
||||
nsTableFrame::InvalidateFrame(this, oldGroupRect, PR_FALSE);
|
||||
|
||||
return yGroupOffset;
|
||||
}
|
||||
|
||||
|
@ -880,8 +904,10 @@ nsTableRowGroupFrame::SlideChild(nsRowGroupReflowState& aReflowState,
|
|||
nsPoint newPosition = oldPosition;
|
||||
newPosition.y = aReflowState.y;
|
||||
if (oldPosition.y != newPosition.y) {
|
||||
aKidFrame->InvalidateOverflowRect();
|
||||
aKidFrame->SetPosition(newPosition);
|
||||
nsTableFrame::RePositionViews(aKidFrame);
|
||||
aKidFrame->InvalidateOverflowRect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,6 +1105,9 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
|
|||
rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page
|
||||
nsHTMLReflowMetrics rowMetrics;
|
||||
|
||||
// Get the old size before we reflow.
|
||||
nsRect oldRowRect = rowFrame->GetRect();
|
||||
|
||||
// Reflow the cell with the constrained height. A cell with rowspan >1 will get this
|
||||
// reflow later during SplitSpanningCells.
|
||||
rv = ReflowChild(rowFrame, aPresContext, rowMetrics, rowReflowState,
|
||||
|
@ -1088,6 +1117,8 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
|
|||
rowFrame->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
|
||||
rowFrame->DidResize();
|
||||
|
||||
nsTableFrame::InvalidateFrame(rowFrame, oldRowRect, PR_FALSE);
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// The row frame is incomplete and all of the rowspan 1 cells' block frames split
|
||||
if ((rowMetrics.height <= rowReflowState.availableHeight) || isTopOfPage) {
|
||||
|
|
|
@ -313,7 +313,8 @@ protected:
|
|||
void PlaceChild(nsPresContext* aPresContext,
|
||||
nsRowGroupReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsRect& aOriginalKidRect);
|
||||
|
||||
void CalculateRowHeights(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
|
|
Загрузка…
Ссылка в новой задаче