diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index c89680728077..3f7cb18712d3 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -783,7 +783,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } nsresult rv = NS_OK; - PRBool isStyleChange = PR_FALSE; nsIFrame* target; switch (aReflowState.reason) { @@ -813,7 +812,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, switch (type) { case eReflowType_StyleChanged: rv = PrepareStyleChangedReflow(state); - isStyleChange = PR_TRUE; break; case eReflowType_ReflowDirty: // Do nothing; the dirty lines will already have been marked. @@ -908,87 +906,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif - // If this is an incremental reflow and we changed size, then make sure our - // border is repainted if necessary - if ((eReflowReason_Incremental == aReflowState.reason || - eReflowReason_Dirty == aReflowState.reason)) { - if (isStyleChange) { - // This is only true if it's a style change reflow targeted at this - // frame (rather than an ancestor) (I think). That seems to be - // what's wanted here. - // Lots of things could have changed so damage our entire - // bounds -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 1 (%d, %d, %d, %d)\n", - this, 0, 0, mRect.width, mRect.height); -#endif - nsRect damageRect(0, 0, mRect.width, mRect.height); - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext,damageRect); - } - } else { - nsMargin border = aReflowState.mComputedBorderPadding - - aReflowState.mComputedPadding; - - // See if our width changed - if ((aMetrics.width != mRect.width) && (border.right > 0)) { - nsRect damageRect; - - if (aMetrics.width < mRect.width) { - // Our new width is smaller, so we need to make sure that - // we paint our border in its new position - damageRect.x = aMetrics.width - border.right; - damageRect.width = border.right; - damageRect.y = 0; - damageRect.height = aMetrics.height; - - } else { - // Our new width is larger, so we need to erase our border in its - // old position - damageRect.x = mRect.width - border.right; - damageRect.width = border.right; - damageRect.y = 0; - damageRect.height = mRect.height; - } -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 2 (%d, %d, %d, %d)\n", - this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); -#endif - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext, damageRect); - } - } - - // See if our height changed - if ((aMetrics.height != mRect.height) && (border.bottom > 0)) { - nsRect damageRect; - - if (aMetrics.height < mRect.height) { - // Our new height is smaller, so we need to make sure that - // we paint our border in its new position - damageRect.x = 0; - damageRect.width = aMetrics.width; - damageRect.y = aMetrics.height - border.bottom; - damageRect.height = border.bottom; - - } else { - // Our new height is larger, so we need to erase our border in its - // old position - damageRect.x = 0; - damageRect.width = mRect.width; - damageRect.y = mRect.height - border.bottom; - damageRect.height = border.bottom; - } -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 3 (%d, %d, %d, %d)\n", - this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); -#endif - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext, damageRect); - } - } - } - } + // Determine if we need to repaint our border + CheckInvalidateBorder(aPresContext, aMetrics, aReflowState); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index 4635c73dab5d..72ece6056488 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -550,9 +550,22 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext* aPresContext, } // Place and size the child - FinishReflowChild(firstChild, aPresContext, nsnull, + FinishReflowChild(firstChild, aPresContext, nsnull, kidMetrics, offset.x, offset.y, 0); + // Determine if we need to repaint our border + CheckInvalidateBorder(aPresContext, aDesiredSize, aReflowState); + + { + // Invalidate the frame + nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + if (!rect.IsEmpty()) { + Invalidate(aPresContext, rect, PR_FALSE); + } + } + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsHTMLFrameOuterFrame::Reflow: size=%d,%d status=%x", aDesiredSize.width, aDesiredSize.height, aStatus)); @@ -876,9 +889,9 @@ nsHTMLFrameInnerFrame::Paint(nsIPresContext* aPresContext, PRUint32 aFlags) { //printf("inner paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, - //aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); if there is - //not web shell paint based on our background color, otherwise let - //the web shell paint the sub document + //aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); + // if there is not web shell paint based on our background color, otherwise + // let the web shell paint the sub document // isPaginated is a temporary fix for Bug 75737 and this should all // be fixed correctly by Bug 75739 diff --git a/layout/generic/nsHTMLContainerFrame.cpp b/layout/generic/nsHTMLContainerFrame.cpp index 26c554d7b847..19a8cfe9c953 100644 --- a/layout/generic/nsHTMLContainerFrame.cpp +++ b/layout/generic/nsHTMLContainerFrame.cpp @@ -682,3 +682,103 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, } return NS_OK; } + +void +nsHTMLContainerFrame::CheckInvalidateBorder(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState) +{ + // XXX This method ought to deal with padding as well + // If this is a style change reflow targeted at this frame, we must repaint + // everything (well, we really just have to repaint the borders but we're + // a bunch of lazybones). + if (aReflowState.reason == eReflowReason_Incremental) { + nsIFrame* target; + aReflowState.reflowCommand->GetTarget(target); + if (target == this) { + nsReflowType type; + aReflowState.reflowCommand->GetType(type); + if (type == eReflowType_StyleChanged) { + +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 1 (%d, %d, %d, %d)\n", + this, 0, 0, mRect.width, mRect.height); +#endif + + // Lots of things could have changed so damage our entire bounds + nsRect damageRect(0, 0, mRect.width, mRect.height); + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext,damageRect); + } + + return; + } + } + } + + // If we changed size, we must invalidate the parts of us that have changed + // to make the border show up. + if ((aReflowState.reason == eReflowReason_Incremental || + aReflowState.reason == eReflowReason_Dirty)) { + nsMargin border = aReflowState.mComputedBorderPadding - + aReflowState.mComputedPadding; + + // See if our width changed + if ((aDesiredSize.width != mRect.width) && (border.right > 0)) { + nsRect damageRect; + + if (aDesiredSize.width < mRect.width) { + // Our new width is smaller, so we need to make sure that + // we paint our border in its new position + damageRect.x = aDesiredSize.width - border.right; + damageRect.width = border.right; + damageRect.y = 0; + damageRect.height = aDesiredSize.height; + } else { + // Our new width is larger, so we need to erase our border in its + // old position + damageRect.x = mRect.width - border.right; + damageRect.width = border.right; + damageRect.y = 0; + damageRect.height = mRect.height; + } + +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 2 (%d, %d, %d, %d)\n", + this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); +#endif + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext, damageRect); + } + } + + // See if our height changed + if ((aDesiredSize.height != mRect.height) && (border.bottom > 0)) { + nsRect damageRect; + + if (aDesiredSize.height < mRect.height) { + // Our new height is smaller, so we need to make sure that + // we paint our border in its new position + damageRect.x = 0; + damageRect.width = aDesiredSize.width; + damageRect.y = aDesiredSize.height - border.bottom; + damageRect.height = border.bottom; + + } else { + // Our new height is larger, so we need to erase our border in its + // old position + damageRect.x = 0; + damageRect.width = mRect.width; + damageRect.y = mRect.height - border.bottom; + damageRect.height = border.bottom; + } +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 3 (%d, %d, %d, %d)\n", + this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); +#endif + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext, damageRect); + } + } + } +} diff --git a/layout/generic/nsHTMLContainerFrame.h b/layout/generic/nsHTMLContainerFrame.h index dbf9b33007e5..277a27a6cc82 100644 --- a/layout/generic/nsHTMLContainerFrame.h +++ b/layout/generic/nsHTMLContainerFrame.h @@ -43,6 +43,8 @@ class nsAbsoluteFrame; class nsPlaceholderFrame; struct nsStyleDisplay; struct nsStylePosition; +struct nsHTMLReflowMetrics; +struct nsHTMLReflowState; // Some macros for container classes to do sanity checking on // width/height/x/y values computed during reflow. @@ -98,12 +100,24 @@ public: nsIFrame* aChildFrame, nsIFrame* aOldParentFrame, nsIFrame* aNewParentFrame); - + static nsresult ReparentFrameViewList(nsIPresContext* aPresContext, nsIFrame* aChildFrameList, nsIFrame* aOldParentFrame, nsIFrame* aNewParentFrame); + /** + * Helper method to invalidate portions of a standard container frame if the + * reflow state indicates that they have changed (specifically border and + * padding). + * @param aPresContext the presentation context + * @param aDesiredSize the new size of the frame + * @param aReflowState the reflow that was just done on this frame + */ + void CheckInvalidateBorder(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState); + protected: virtual PRIntn GetSkipSides() const = 0; }; diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index c89680728077..3f7cb18712d3 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -783,7 +783,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } nsresult rv = NS_OK; - PRBool isStyleChange = PR_FALSE; nsIFrame* target; switch (aReflowState.reason) { @@ -813,7 +812,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, switch (type) { case eReflowType_StyleChanged: rv = PrepareStyleChangedReflow(state); - isStyleChange = PR_TRUE; break; case eReflowType_ReflowDirty: // Do nothing; the dirty lines will already have been marked. @@ -908,87 +906,8 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif - // If this is an incremental reflow and we changed size, then make sure our - // border is repainted if necessary - if ((eReflowReason_Incremental == aReflowState.reason || - eReflowReason_Dirty == aReflowState.reason)) { - if (isStyleChange) { - // This is only true if it's a style change reflow targeted at this - // frame (rather than an ancestor) (I think). That seems to be - // what's wanted here. - // Lots of things could have changed so damage our entire - // bounds -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 1 (%d, %d, %d, %d)\n", - this, 0, 0, mRect.width, mRect.height); -#endif - nsRect damageRect(0, 0, mRect.width, mRect.height); - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext,damageRect); - } - } else { - nsMargin border = aReflowState.mComputedBorderPadding - - aReflowState.mComputedPadding; - - // See if our width changed - if ((aMetrics.width != mRect.width) && (border.right > 0)) { - nsRect damageRect; - - if (aMetrics.width < mRect.width) { - // Our new width is smaller, so we need to make sure that - // we paint our border in its new position - damageRect.x = aMetrics.width - border.right; - damageRect.width = border.right; - damageRect.y = 0; - damageRect.height = aMetrics.height; - - } else { - // Our new width is larger, so we need to erase our border in its - // old position - damageRect.x = mRect.width - border.right; - damageRect.width = border.right; - damageRect.y = 0; - damageRect.height = mRect.height; - } -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 2 (%d, %d, %d, %d)\n", - this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); -#endif - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext, damageRect); - } - } - - // See if our height changed - if ((aMetrics.height != mRect.height) && (border.bottom > 0)) { - nsRect damageRect; - - if (aMetrics.height < mRect.height) { - // Our new height is smaller, so we need to make sure that - // we paint our border in its new position - damageRect.x = 0; - damageRect.width = aMetrics.width; - damageRect.y = aMetrics.height - border.bottom; - damageRect.height = border.bottom; - - } else { - // Our new height is larger, so we need to erase our border in its - // old position - damageRect.x = 0; - damageRect.width = mRect.width; - damageRect.y = mRect.height - border.bottom; - damageRect.height = border.bottom; - } -#ifdef NOISY_BLOCK_INVALIDATE - printf("%p invalidate 3 (%d, %d, %d, %d)\n", - this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); -#endif - if (!damageRect.IsEmpty()) { - Invalidate(aPresContext, damageRect); - } - } - } - } + // Determine if we need to repaint our border + CheckInvalidateBorder(aPresContext, aMetrics, aReflowState); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage diff --git a/layout/html/base/src/nsHTMLContainerFrame.cpp b/layout/html/base/src/nsHTMLContainerFrame.cpp index 26c554d7b847..19a8cfe9c953 100644 --- a/layout/html/base/src/nsHTMLContainerFrame.cpp +++ b/layout/html/base/src/nsHTMLContainerFrame.cpp @@ -682,3 +682,103 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, } return NS_OK; } + +void +nsHTMLContainerFrame::CheckInvalidateBorder(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState) +{ + // XXX This method ought to deal with padding as well + // If this is a style change reflow targeted at this frame, we must repaint + // everything (well, we really just have to repaint the borders but we're + // a bunch of lazybones). + if (aReflowState.reason == eReflowReason_Incremental) { + nsIFrame* target; + aReflowState.reflowCommand->GetTarget(target); + if (target == this) { + nsReflowType type; + aReflowState.reflowCommand->GetType(type); + if (type == eReflowType_StyleChanged) { + +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 1 (%d, %d, %d, %d)\n", + this, 0, 0, mRect.width, mRect.height); +#endif + + // Lots of things could have changed so damage our entire bounds + nsRect damageRect(0, 0, mRect.width, mRect.height); + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext,damageRect); + } + + return; + } + } + } + + // If we changed size, we must invalidate the parts of us that have changed + // to make the border show up. + if ((aReflowState.reason == eReflowReason_Incremental || + aReflowState.reason == eReflowReason_Dirty)) { + nsMargin border = aReflowState.mComputedBorderPadding - + aReflowState.mComputedPadding; + + // See if our width changed + if ((aDesiredSize.width != mRect.width) && (border.right > 0)) { + nsRect damageRect; + + if (aDesiredSize.width < mRect.width) { + // Our new width is smaller, so we need to make sure that + // we paint our border in its new position + damageRect.x = aDesiredSize.width - border.right; + damageRect.width = border.right; + damageRect.y = 0; + damageRect.height = aDesiredSize.height; + } else { + // Our new width is larger, so we need to erase our border in its + // old position + damageRect.x = mRect.width - border.right; + damageRect.width = border.right; + damageRect.y = 0; + damageRect.height = mRect.height; + } + +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 2 (%d, %d, %d, %d)\n", + this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); +#endif + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext, damageRect); + } + } + + // See if our height changed + if ((aDesiredSize.height != mRect.height) && (border.bottom > 0)) { + nsRect damageRect; + + if (aDesiredSize.height < mRect.height) { + // Our new height is smaller, so we need to make sure that + // we paint our border in its new position + damageRect.x = 0; + damageRect.width = aDesiredSize.width; + damageRect.y = aDesiredSize.height - border.bottom; + damageRect.height = border.bottom; + + } else { + // Our new height is larger, so we need to erase our border in its + // old position + damageRect.x = 0; + damageRect.width = mRect.width; + damageRect.y = mRect.height - border.bottom; + damageRect.height = border.bottom; + } +#ifdef NOISY_BLOCK_INVALIDATE + printf("%p invalidate 3 (%d, %d, %d, %d)\n", + this, damageRect.x, damageRect.y, damageRect.width, damageRect.height); +#endif + if (!damageRect.IsEmpty()) { + Invalidate(aPresContext, damageRect); + } + } + } +} diff --git a/layout/html/base/src/nsHTMLContainerFrame.h b/layout/html/base/src/nsHTMLContainerFrame.h index dbf9b33007e5..277a27a6cc82 100644 --- a/layout/html/base/src/nsHTMLContainerFrame.h +++ b/layout/html/base/src/nsHTMLContainerFrame.h @@ -43,6 +43,8 @@ class nsAbsoluteFrame; class nsPlaceholderFrame; struct nsStyleDisplay; struct nsStylePosition; +struct nsHTMLReflowMetrics; +struct nsHTMLReflowState; // Some macros for container classes to do sanity checking on // width/height/x/y values computed during reflow. @@ -98,12 +100,24 @@ public: nsIFrame* aChildFrame, nsIFrame* aOldParentFrame, nsIFrame* aNewParentFrame); - + static nsresult ReparentFrameViewList(nsIPresContext* aPresContext, nsIFrame* aChildFrameList, nsIFrame* aOldParentFrame, nsIFrame* aNewParentFrame); + /** + * Helper method to invalidate portions of a standard container frame if the + * reflow state indicates that they have changed (specifically border and + * padding). + * @param aPresContext the presentation context + * @param aDesiredSize the new size of the frame + * @param aReflowState the reflow that was just done on this frame + */ + void CheckInvalidateBorder(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState); + protected: virtual PRIntn GetSkipSides() const = 0; }; diff --git a/layout/html/document/src/nsFrameFrame.cpp b/layout/html/document/src/nsFrameFrame.cpp index 4635c73dab5d..72ece6056488 100644 --- a/layout/html/document/src/nsFrameFrame.cpp +++ b/layout/html/document/src/nsFrameFrame.cpp @@ -550,9 +550,22 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext* aPresContext, } // Place and size the child - FinishReflowChild(firstChild, aPresContext, nsnull, + FinishReflowChild(firstChild, aPresContext, nsnull, kidMetrics, offset.x, offset.y, 0); + // Determine if we need to repaint our border + CheckInvalidateBorder(aPresContext, aDesiredSize, aReflowState); + + { + // Invalidate the frame + nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + if (!rect.IsEmpty()) { + Invalidate(aPresContext, rect, PR_FALSE); + } + } + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsHTMLFrameOuterFrame::Reflow: size=%d,%d status=%x", aDesiredSize.width, aDesiredSize.height, aStatus)); @@ -876,9 +889,9 @@ nsHTMLFrameInnerFrame::Paint(nsIPresContext* aPresContext, PRUint32 aFlags) { //printf("inner paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, - //aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); if there is - //not web shell paint based on our background color, otherwise let - //the web shell paint the sub document + //aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); + // if there is not web shell paint based on our background color, otherwise + // let the web shell paint the sub document // isPaginated is a temporary fix for Bug 75737 and this should all // be fixed correctly by Bug 75739