--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2481,8 +2481,26 @@ nsLayoutUtils::GetTextRunFlagsForStyle(n
}
break;
default:
break;
}
#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;
+}
+
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -750,16 +750,25 @@ public:
* -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
* and prefs indicate we should be optimizing for speed over quality
*/
static PRUint32 GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
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.
*/
#ifdef DEBUG
static PRBool sDisableGetUsedXAssertions;
#endif
};
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -2230,38 +2230,16 @@ nsBlockFrame::DeleteLine(nsBlockReflowSt
// Mark the previous margin of the next line dirty since we need to
// recompute its top position.
if (aLine != aLineEnd)
aLine->MarkPreviousMarginDirty();
}
}
/**
- * 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
* whether or not the caller should continue to reflow more lines.
*/
nsresult
nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
line_iterator aLine,
PRBool* aKeepReflowGoing)
@@ -2300,20 +2278,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowSt
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
#endif
Invalidate(dirtyRect);
} else {
nsRect combinedAreaHStrip, combinedAreaVStrip;
nsRect boundsHStrip, boundsVStrip;
- GetRectDifferenceStrips(oldBounds, newBounds,
- &boundsHStrip, &boundsVStrip);
- GetRectDifferenceStrips(oldCombinedArea, lineCombinedArea,
- &combinedAreaHStrip, &combinedAreaVStrip);
+ nsLayoutUtils::GetRectDifferenceStrips(oldBounds, newBounds,
+ &boundsHStrip, &boundsVStrip);
+ nsLayoutUtils::GetRectDifferenceStrips(oldCombinedArea, lineCombinedArea,
+ &combinedAreaHStrip,
+ &combinedAreaVStrip);
#ifdef NOISY_BLOCK_INVALIDATE
printf("%p invalidate boundsVStrip (%d, %d, %d, %d)\n",
this, boundsVStrip.x, boundsVStrip.y, boundsVStrip.width, boundsVStrip.height);
printf("%p invalidate boundsHStrip (%d, %d, %d, %d)\n",
this, boundsHStrip.x, boundsHStrip.y, boundsHStrip.width, boundsHStrip.height);
printf("%p invalidate combinedAreaVStrip (%d, %d, %d, %d)\n",
this, combinedAreaVStrip.x, combinedAreaVStrip.y, combinedAreaVStrip.width, combinedAreaVStrip.height);
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -738,16 +738,21 @@ nsContainerFrame::ReflowChild(nsIFrame*
nsresult result;
// Send the WillReflow() notification, and position the child frame
// and its view if requested
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));
}
if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
PositionFrameView(aKidFrame);
}
// Reflow the child frame
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -55,16 +55,19 @@
// for frames that support overflow containers
// Option flags for ReflowChild() and FinishReflowChild()
// member functions
#define NS_FRAME_NO_MOVE_VIEW 0x0001
#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;
/**
* Implementation of a container frame.
*/
class nsContainerFrame : public nsSplittableFrame
{
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3596,16 +3596,31 @@ void
nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
nsIFrame* aForChild, PRBool aImmediate)
{
GetParent()->
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)
{
PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
nsIView* view = GetView();
NS_ASSERTION(view, "This can only be called on frames with views");
view->GetViewManager()->UpdateView(view, aDamageRect + nsPoint(aX, aY), flags);
}
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1651,16 +1651,31 @@ public:
* In case it's true, pending notifications will be flushed which
* could cause frames to be deleted (including |this|).
*/
virtual void InvalidateInternal(const nsRect& aDamageRect,
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
* frame's outline, and descentant frames' outline, but does not include
* areas clipped out by the CSS "overflow" and "clip" properties.
*
* @return the rect relative to this frame's origin
*/
nsRect GetOverflowRect() const;
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -588,27 +588,35 @@ void nsTableCellFrame::VerticallyAlignCh
default:
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
// Align the middle of the child frame with the middle of the content area,
kidYTop = (height - childHeight - bottomInset + topInset) / 2;
}
// 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;
desiredSize.height = mRect.height;
GetSelfOverflow(desiredSize.mOverflowArea);
ConsiderChildOverflow(desiredSize.mOverflowArea, firstKid);
FinishAndStoreOverflow(&desiredSize);
if (kidYTop != kidRect.y) {
// 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,
GetView(),
&desiredSize.mOverflowArea, 0);
}
}
@@ -856,40 +864,46 @@ NS_METHOD nsTableCellFrame::Reflow(nsPre
(GetFirstInFlow()->GetStateBits() & NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
// We need to force the kid to have mVResize set if we've had a
// special reflow in the past, since the non-special reflow needs to
// resize back to what it was without the special height reflow.
kidReflowState.mFlags.mVResize = PR_TRUE;
}
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);
}
#ifdef NS_DEBUG
DebugCheckChildSize(firstKid, kidSize, availSize);
#endif
// 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
// see testcase "emptyCells.html"
SetContentEmpty(0 == kidSize.height);
// Place the child
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;
if (NS_UNCONSTRAINEDSIZE != cellHeight) {
cellHeight += topInset + bottomInset;
}
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1952,16 +1952,21 @@ NS_METHOD nsTableFrame::Reflow(nsPresCon
if (!reflowedChildren) {
// use the old overflow area
nsRect* oldOverflowArea = GetOverflowAreaProperty();
if (oldOverflowArea) {
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, *oldOverflowArea);
}
}
+ 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;
}
nsresult
nsTableFrame::ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
@@ -2573,23 +2578,28 @@ nsTableFrame::InitChildReflowState(nsHTM
aReflowState.mFlags.mHResize = PR_TRUE;
}
}
// Position and size aKidFrame and update our reflow state. The origin of
// 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;
// If our height is constrained, then update the available height
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
aReflowState.availSize.height -= aKidDesiredSize.height;
}
}
@@ -2929,19 +2939,20 @@ nsTableFrame::ReflowChildren(nsTableRefl
aReflowState.availSize.height -= cellSpacingY;
}
// record the presence of a next in flow, it might get destroyed so we
// need to reorder the row group array
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
PRBool reorder = PR_FALSE;
if (kidFrame->GetNextInFlow())
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
numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
childX = rowGroups.IndexOf(kidFrame);
if (childX == RowGroupArray::NoIndex) {
// XXXbz can this happen?
childX = numRowGroups;
@@ -2952,17 +2963,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight) &&
kidReflowState.availableHeight < desiredSize.height) {
// if we are on top of the page place with dataloss
if (kidReflowState.mFlags.mIsTopOfPage) {
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;
break;
}
}
}
else { // we are not on top, push this rowgroup onto the next page
@@ -2983,17 +2994,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
nsIFrame* nextKid =
(childX + 1 < numRowGroups) ? rowGroups[childX + 1] : nsnull;
pageBreak = PageBreakAfter(*kidFrame, nextKid);
}
// 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;
// Special handling for incomplete children
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
kidNextInFlow = kidFrame->GetNextInFlow();
if (!kidNextInFlow) {
@@ -3031,33 +3042,39 @@ nsTableFrame::ReflowChildren(nsTableRefl
if (allowRepeatedFooter) {
kidAvailSize.height = footerHeight;
nsHTMLReflowState footerReflowState(presContext,
aReflowState.reflowState,
tfoot, kidAvailSize,
-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;
}
}
else { // it isn't being reflowed
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;
// If our height is constrained then update the available height.
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
aReflowState.availSize.height -= cellSpacingY + kidRect.height;
}
}
@@ -3221,46 +3238,65 @@ nsTableFrame::DistributeHeightToRows(con
if (!rgFrame->HasStyleHeight()) {
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
while (rowFrame) {
nsRect rowRect = rowFrame->GetRect();
if ((amountUsed < aAmount) && rowFrame->HasPctHeight()) {
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;
amountUsed += amountForRow;
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;
}
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;
}
if (amountUsed >= aAmount) {
ResizeCells(*this);
return;
}
@@ -3355,50 +3391,69 @@ nsTableFrame::DistributeHeightToRows(con
// all rows get the same additional space
ratio = 1.0f / float(divisor);
}
// give rows their additional space, except for the last row which
// gets the remainder
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;
amountUsed += amountForRow;
amountUsedByRG += amountForRow;
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;
}
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;
}
ResizeCells(*this);
}
PRBool
@@ -6713,16 +6768,37 @@ nsTableFrame::GetProperty(nsIFrame*
if (value) {
propTable->SetProperty(aFrame, aPropertyName, value, dtorFunc, nsnull);
}
return value;
}
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
static
void DumpTableFramesRecur(nsIFrame* aFrame,
PRUint32 aIndent)
{
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -475,16 +475,30 @@ public:
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
PRBool HasPctCol() const;
void SetHasPctCol(PRBool aValue);
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.
* @see NewFrame
*/
nsTableFrame(nsStyleContext* aContext);
/** destructor, responsible for mColumnLayoutData */
@@ -562,17 +576,18 @@ protected:
// The following is a helper for CalcDesiredHeight
void DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
nscoord aAmount);
void PlaceChild(nsTableReflowState& aReflowState,
nsIFrame* aKidFrame,
- nsHTMLReflowMetrics& aKidDesiredSize);
+ nsHTMLReflowMetrics& aKidDesiredSize,
+ const nsRect& aOriginalKidRect);
nsIFrame* GetFirstBodyRowGroupFrame();
PRBool MoveOverflowToChildList(nsPresContext* aPresContext);
/**
* Push all our child frames from the aFrames array, in order, starting from the
* frame at aPushFrom to the end of the array. The frames are put on our overflow
* list or moved directly to our next-in-flow if one exists.
*/
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -348,25 +348,33 @@ nsTableRowFrame::DidResize()
desiredSize.height);
while (childFrame) {
if (IS_TABLE_CELL(childFrame->GetType())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)childFrame;
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->VerticallyAlignChild(mMaxCellAscent);
- 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.
+ 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();
}
FinishAndStoreOverflow(&desiredSize);
if (HasView()) {
nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this, GetView(), &desiredSize.mOverflowArea, 0);
}
@@ -850,16 +858,20 @@ nsTableRowFrame::ReflowChildren(nsPresCo
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
cellSpacingX, iter.IsLeftToRight(), PR_FALSE);
}
// remember the rightmost (ltr) or leftmost (rtl) column this cell spans into
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;
CalcAvailWidth(aTableFrame, *cellFrame, cellSpacingX,
availColWidth, availCellWidth);
nsHTMLReflowMetrics desiredSize;
@@ -884,25 +896,29 @@ nsTableRowFrame::ReflowChildren(nsPresCo
// Reflow the child
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, kidAvailSize, PR_FALSE);
InitChildReflowState(*aPresContext, kidAvailSize, borderCollapse,
kidReflowState);
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
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
aStatus = NS_FRAME_NOT_COMPLETE;
}
}
else {
+ if (x != kidRect.x) {
+ kidFrame->InvalidateOverflowRect();
+ }
+
desiredSize.width = cellDesiredSize.width;
desiredSize.height = cellDesiredSize.height;
nsRect *overflowArea =
cellFrame->GetOverflowAreaProperty();
if (overflowArea)
desiredSize.mOverflowArea = *overflowArea;
else
desiredSize.mOverflowArea.SetRect(0, 0, cellDesiredSize.width,
@@ -944,27 +960,30 @@ nsTableRowFrame::ReflowChildren(nsPresCo
}
// Place the child
if (NS_UNCONSTRAINEDSIZE != availColWidth) {
desiredSize.width = PR_MAX(availCellWidth, availColWidth);
}
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;
if (kidFrame->GetNextInFlow()) {
aStatus = NS_FRAME_NOT_COMPLETE;
}
}
@@ -1061,35 +1080,39 @@ nsTableRowFrame::ReflowCellFrame(nsPresC
nscoord aAvailableHeight,
nsReflowStatus& aStatus)
{
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
if (!tableFrame)
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);
InitChildReflowState(*aPresContext, availSize, borderCollapse, cellReflowState);
cellReflowState.mFlags.mIsTopOfPage = aIsTopOfPage;
nsHTMLReflowMetrics desiredSize;
ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
PRBool fullyComplete = NS_FRAME_IS_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus);
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 ?
if (fullyComplete) {
aCellFrame->VerticallyAlignChild(mMaxCellAscent);
}
aCellFrame->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
return desiredSize.height;
@@ -1105,30 +1128,44 @@ nsTableRowFrame::CollapseRowIfNecessary(
PRBool collapseRow = (NS_STYLE_VISIBILITY_COLLAPSE == rowVis->mVisible);
nsTableFrame* tableFrame = static_cast<nsTableFrame*>(nsTableFrame::GetTableFrame(this)->GetFirstInFlow());
if (!tableFrame)
return 0;
if (collapseRow) {
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);
nscoord shift = 0;
nscoord cellSpacingX = tableFrame->GetCellSpacingX();
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
if (aCollapseGroup || collapseRow) {
nsTableCellFrame* cellFrame = GetFirstCell();
aDidCollapse = PR_TRUE;
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();
}
rowRect.height = 0;
}
else { // row is not collapsed
nsTableIterator iter(*this);
@@ -1156,17 +1193,17 @@ nsTableRowFrame::CollapseRowIfNecessary(
// the space
if ((iter.IsLeftToRight() && (prevColIndex != (cellColIndex - 1))) ||
(!iter.IsLeftToRight() &&
(prevColIndex != cellColIndex + cellColSpan))) {
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan,
*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
prevColIndex = (iter.IsLeftToRight()) ?
cellColIndex + (cellColSpan - 1) : cellColIndex;
PRInt32 startIndex = (iter.IsLeftToRight()) ?
cellColIndex : cellColIndex + (cellColSpan - 1);
PRInt32 actualColSpan = cellColSpan;
@@ -1211,33 +1248,50 @@ nsTableRowFrame::CollapseRowIfNecessary(
PRBool collapseNextRow = (NS_STYLE_VISIBILITY_COLLAPSE ==
nextRowVis->mVisible);
if (!collapseNextRow) {
nsRect nextRect = rowFrame->GetRect();
cRect.height += nextRect.height + cellSpacingY;
}
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;
}
/**
* These 3 functions are called by the row group frame's SplitRowGroup() code when
* it creates a continuing cell frame and wants to insert it into the row's child list
*/
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -289,20 +289,27 @@ nsTableRowGroupFrame::GetSkipSides() con
}
// Position and size aKidFrame and update our reflow state. The origin of
// aKidRect is relative to the upper-left origin of our frame
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;
// If our height is constrained then update the available height
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
aReflowState.availSize.height -= aDesiredSize.height;
}
@@ -379,17 +386,17 @@ nsTableRowGroupFrame::ReflowChildren(nsP
haveRow = PR_TRUE;
// Reflow the row frame
if (reflowAllKids ||
NS_SUBTREE_DIRTY(kidFrame) ||
(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.
nsHTMLReflowMetrics desiredSize(aDesiredSize.mFlags);
desiredSize.width = desiredSize.height = 0;
// Reflow the child into the available space, giving it as much height as
// it wants. We'll deal with splitting later after we've computed the row
@@ -405,20 +412,22 @@ nsTableRowGroupFrame::ReflowChildren(nsP
kidReflowState.mFlags.mHResize = PR_TRUE;
// If this isn't the first row, then we can't be at the top of the page
if (kidFrame != GetFirstFrame()) {
kidReflowState.mFlags.mIsTopOfPage = PR_FALSE;
}
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) {
if (IsSimpleRowFrame(aReflowState.tableFrame, kidFrame)) {
// Inform the row of its new height.
((nsTableRowFrame*)kidFrame)->DidResize();
// the overflow area may have changed inflate the overflow area
if (aReflowState.tableFrame->IsAutoHeight()) {
@@ -431,17 +440,17 @@ nsTableRowGroupFrame::ReflowChildren(nsP
// Invalidate the area we're offseting. Note that we only
// repaint within our existing frame bounds.
if (kidRect.YMost() < mRect.height) {
nsRect dirtyRect(0, kidRect.YMost(),
mRect.width, mRect.height - kidRect.YMost());
Invalidate(dirtyRect);
}
}
- else if (oldKidSize.height != desiredSize.height)
+ else if (oldKidRect.height != desiredSize.height)
needToCalcRowHeights = PR_TRUE;
} else {
needToCalcRowHeights = PR_TRUE;
}
}
if (isPaginated && aPageBreakBeforeEnd && !*aPageBreakBeforeEnd) {
nsTableRowFrame* nextRow = ((nsTableRowFrame*)kidFrame)->GetNextRow();
@@ -793,23 +802,29 @@ nsTableRowGroupFrame::CalculateRowHeight
// update the rows with their (potentially) new heights
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
nsRect rowBounds = rowFrame->GetRect();
PRBool movedFrame = (rowBounds.y != yOrigin);
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;
}
if (isPaginated && styleHeightAllocation) {
// since the row group has a style height, cache the row heights, so next in flows can honor them
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
@@ -840,30 +855,39 @@ nsTableRowGroupFrame::CollapseRowGroupIf
yGroupOffset += rowFrame->CollapseRowIfNecessary(yGroupOffset,
aWidth, collapseGroup,
didCollapse);
ConsiderChildOverflow(overflowArea, rowFrame);
rowFrame = rowFrame->GetNextRow();
}
nsRect groupRect = GetRect();
+ nsRect oldGroupRect = groupRect;
+
groupRect.height -= yGroupOffset;
if (didCollapse) {
// add back the cellspacing between rowgroups
groupRect.height += tableFrame->GetCellSpacingY();
}
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;
}
// Move a child that was skipped during an incremental reflow.
// This function is not used for paginated mode so we don't need to deal
// with continuing frames, and it's only called if aKidFrame has no
// cells that span into it and no cells that span across it. That way
// we don't have to deal with rowspans
@@ -875,18 +899,20 @@ nsTableRowGroupFrame::SlideChild(nsRowGr
NS_PRECONDITION(NS_UNCONSTRAINEDSIZE == aReflowState.reflowState.availableHeight,
"we're not in galley mode");
// Move the frame if we need to
nsPoint oldPosition = aKidFrame->GetPosition();
nsPoint newPosition = oldPosition;
newPosition.y = aReflowState.y;
if (oldPosition.y != newPosition.y) {
+ aKidFrame->InvalidateOverflowRect();
aKidFrame->SetPosition(newPosition);
nsTableFrame::RePositionViews(aKidFrame);
+ aKidFrame->InvalidateOverflowRect();
}
}
// Create a continuing frame, add it to the child list, and then push it
// and the frames that follow
void
nsTableRowGroupFrame::CreateContinuingRowFrame(nsPresContext& aPresContext,
nsIFrame& aRowFrame,
@@ -1074,25 +1100,30 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
nsHTMLReflowState rowReflowState(aPresContext, aReflowState,
rowFrame, availSize,
-1, -1, PR_FALSE);
InitChildReflowState(*aPresContext, borderCollapse, rowReflowState);
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,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
if (NS_FAILED(rv)) return rv;
rowFrame->SetSize(nsSize(rowMetrics.width, rowMetrics.height));
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) {
// The row stays on this page because either it split ok or we're on the top of page.
// If top of page and the height exceeded the avail height, then there will be data loss
NS_ASSERTION(rowMetrics.height <= rowReflowState.availableHeight,
"data loss - incomplete row needed more height than available, on top of page");
CreateContinuingRowFrame(*aPresContext, *rowFrame, (nsIFrame**)&contRow);
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -308,17 +308,18 @@ protected:
nsHTMLReflowState& aReflowState);
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
void PlaceChild(nsPresContext* aPresContext,
nsRowGroupReflowState& aReflowState,
nsIFrame* aKidFrame,
- nsHTMLReflowMetrics& aDesiredSize);
+ nsHTMLReflowMetrics& aDesiredSize,
+ const nsRect& aOriginalKidRect);
void CalculateRowHeights(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState);
void DidResizeRows(nsHTMLReflowMetrics& aDesiredSize);
void SlideChild(nsRowGroupReflowState& aReflowState,