From c88c6e09b41f5378a85d11be8c7894b9fc8206f3 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Thu, 25 Jan 2007 02:01:07 +0000 Subject: [PATCH] Reflow reflow roots and the child of SVG foreignObject with an unconstrained height to avoid triggering page/column breaking. b=366956 r+sr=roc --- layout/base/nsCSSFrameConstructor.cpp | 7 +++-- layout/base/nsPresShell.cpp | 28 ++++++++++++++++++- layout/generic/nsViewportFrame.cpp | 4 +++ .../svg/base/src/nsSVGForeignObjectFrame.cpp | 14 ++++++++-- layout/svg/base/src/nsSVGOuterSVGFrame.cpp | 1 + layout/svg/base/src/svg.css | 2 ++ layout/xul/base/src/nsBoxFrame.cpp | 2 ++ layout/xul/base/src/nsLeafBoxFrame.cpp | 2 ++ 8 files changed, 54 insertions(+), 6 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 3ae206f4c312..5d5f3fb76b46 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7326,12 +7326,13 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState, ResolvePseudoStyleFor(aContent, nsCSSAnonBoxes::mozSVGForeignContent, aStyleContext); - nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle); + nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle, + NS_BLOCK_SPACE_MGR | + NS_BLOCK_MARGIN_ROOT | + NS_FRAME_REFLOW_ROOT); if (NS_UNLIKELY(!blockFrame)) return NS_ERROR_OUT_OF_MEMORY; - blockFrame->AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT | - NS_FRAME_REFLOW_ROOT); // Claim to be relatively positioned so that we end up being the // absolute containing block. nsFrameConstructorSaveState saveState; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index a2dc9056ab36..261e22f9116a 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -6046,7 +6046,27 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) else size = target->GetSize(); - nsHTMLReflowState reflowState(mPresContext, target, rcx, size); + NS_ASSERTION(!target->GetNextInFlow() && !target->GetPrevInFlow(), + "reflow roots should never split"); + + // Don't pass size directly to the reflow state, since a + // constrained height implies page/column breaking. + nsHTMLReflowState reflowState(mPresContext, target, rcx, + nsSize(size.width, NS_UNCONSTRAINEDSIZE)); + + // fix the computed height + NS_ASSERTION(reflowState.mComputedMargin == nsMargin(0, 0, 0, 0), + "reflow state should not set margin for reflow roots"); + reflowState.mComputedHeight = + size.height - reflowState.mComputedBorderPadding.TopBottom(); + NS_ASSERTION(reflowState.mComputedWidth == + size.width - + reflowState.mComputedBorderPadding.LeftRight(), + "reflow state computed incorrect width"); + + // except the viewport frame does want availableHeight set + if (target == root) + reflowState.availableHeight = size.height; nsReflowStatus status; target->Reflow(mPresContext, desiredSize, reflowState, status); @@ -6058,6 +6078,12 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) desiredSize.height == size.height), "non-root frame's desired size changed during an " "incremental reflow"); + NS_ASSERTION(desiredSize.mOverflowArea == + nsRect(nsPoint(0, 0), + nsSize(desiredSize.width, desiredSize.height)), + "reflow roots must not have visible overflow"); + NS_ASSERTION(status == NS_FRAME_COMPLETE, + "reflow roots should never split"); target->SetSize(nsSize(desiredSize.width, desiredSize.height)); diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index fd6aa3d73e05..30e681d0ecf8 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -330,6 +330,10 @@ ViewportFrame::Reflow(nsPresContext* aPresContext, Invalidate(damageRect, PR_FALSE); } + // XXX Should we do something to clip our children to this? + aDesiredSize.mOverflowArea = + nsRect(nsPoint(0, 0), nsSize(aDesiredSize.width, aDesiredSize.height)); + NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return rv; diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index 2b59118de2a1..a0c2b43dd2f1 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -517,11 +517,21 @@ nsSVGForeignObjectFrame::DoReflow() mInReflow = PR_TRUE; - // create a new reflow state, setting our max size to (width,height): nsHTMLReflowState reflowState(presContext, kid, - renderingContext, size); + renderingContext, + nsSize(size.width, NS_UNCONSTRAINEDSIZE)); nsHTMLReflowMetrics desiredSize; nsReflowStatus status; + + // We don't use size.height above because that tells the child to do + // page/column breaking at that height. + NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0, 0, 0, 0) && + reflowState.mComputedMargin == nsMargin(0, 0, 0, 0), + "style system should ensure that :-moz-svg-foreign content " + "does not get styled"); + NS_ASSERTION(reflowState.mComputedWidth == size.width, + "reflow state made child wrong size"); + reflowState.mComputedHeight = size.height; ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, status); diff --git a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp index cfdc53a94b83..72f2835b5d5a 100644 --- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp @@ -709,6 +709,7 @@ nsSVGOuterSVGFrame::CalculateAvailableSpace(nsRect *maxRect, { *preferredRect = aPresContext->GetVisibleArea(); + // XXXldb What about margin? if (aReflowState.availableWidth != NS_INTRINSICSIZE) maxRect->width = aReflowState.availableWidth; else if (aReflowState.parentReflowState && diff --git a/layout/svg/base/src/svg.css b/layout/svg/base/src/svg.css index 47fa34c26908..ee5b96f61916 100644 --- a/layout/svg/base/src/svg.css +++ b/layout/svg/base/src/svg.css @@ -72,4 +72,6 @@ foreignObject { *|*::-moz-svg-foreign-content { display: block !important; position: static !important; + /* so we don't report overflow that confuses the reflow root code */ + overflow: -moz-hidden-unscrollable ! important; } diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index 984846bfe910..bcfc28eb45bb 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -805,6 +805,8 @@ nsBoxFrame::Reflow(nsPresContext* aPresContext, nsRect* overflowArea = GetOverflowAreaProperty(); NS_ASSERTION(overflowArea, "Failed to set overflow area property"); aDesiredSize.mOverflowArea = *overflowArea; + } else { + aDesiredSize.mOverflowArea = nsRect(nsPoint(0, 0), GetSize()); } #ifdef DO_NOISY_REFLOW diff --git a/layout/xul/base/src/nsLeafBoxFrame.cpp b/layout/xul/base/src/nsLeafBoxFrame.cpp index 9187f77797e2..1a93a993cb27 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -358,6 +358,8 @@ nsLeafBoxFrame::Reflow(nsPresContext* aPresContext, nsRect* overflowArea = GetOverflowAreaProperty(); NS_ASSERTION(overflowArea, "Failed to set overflow area property"); aDesiredSize.mOverflowArea = *overflowArea; + } else { + aDesiredSize.mOverflowArea = nsRect(nsPoint(0, 0), GetSize()); } #ifdef DO_NOISY_REFLOW