From 008a69b28f03e0c216a768ce85da7a3d5f117fe3 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Thu, 31 Dec 1998 05:35:38 +0000 Subject: [PATCH] Better computation of computed width and height and margins for block-level elements git-svn-id: svn://10.0.0.236/trunk@17037 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsHTMLFrame.cpp | 19 +- .../html/base/src/nsFrameReflowState.cpp | 177 ++++++++++-------- mozilla/layout/html/base/src/nsHTMLFrame.cpp | 19 +- mozilla/layout/html/base/src/nsIHTMLReflow.h | 7 +- mozilla/layout/html/document/src/ua.css | 1 + mozilla/layout/style/ua.css | 1 + 6 files changed, 123 insertions(+), 101 deletions(-) diff --git a/mozilla/layout/generic/nsHTMLFrame.cpp b/mozilla/layout/generic/nsHTMLFrame.cpp index eaf986eff23..4a9f856121d 100644 --- a/mozilla/layout/generic/nsHTMLFrame.cpp +++ b/mozilla/layout/generic/nsHTMLFrame.cpp @@ -167,27 +167,21 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow our one and only child frame if (nsnull != mFirstChild) { // Note: the root frame does not have border or padding... - - // Compute the margins around the child frame - nsMargin childMargin; - nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, childMargin); - - // Compute the child frame's available space - nsSize kidMaxSize(aReflowState.maxSize.width - childMargin.left - childMargin.right, - aReflowState.maxSize.height - childMargin.top - childMargin.bottom); nsHTMLReflowMetrics desiredSize(nsnull); // We must pass in that the available height is unconstrained, because // constrained is only for when we're paginated... nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, - nsSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE)); + nsSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE)); if (isChildInitialReflow) { kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; } // For a height that's 'auto', make the frame as big as the available space - if (!kidReflowState.HaveFixedContentHeight()) { - kidReflowState.computedHeight = kidMaxSize.height; + // minus and top and bottom margins + if (NS_AUTOHEIGHT == kidReflowState.computedHeight) { + kidReflowState.computedHeight = aReflowState.maxSize.height - + kidReflowState.computedTopMargin - kidReflowState.computedTopMargin; // Computed height is for the content area so reduce it by the amount of // space taken up by border and padding @@ -201,7 +195,8 @@ RootFrame::Reflow(nsIPresContext& aPresContext, if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { ReflowChild(mFirstChild, aPresContext, desiredSize, kidReflowState, aStatus); - nsRect rect(childMargin.left, childMargin.top, desiredSize.width, desiredSize.height); + nsRect rect(kidReflowState.computedLeftMargin, kidReflowState.computedTopMargin, + desiredSize.width, desiredSize.height); mFirstChild->SetRect(rect); // XXX We should resolve the details of who/when DidReflow() diff --git a/mozilla/layout/html/base/src/nsFrameReflowState.cpp b/mozilla/layout/html/base/src/nsFrameReflowState.cpp index 665a7965a49..5ea02977d2d 100644 --- a/mozilla/layout/html/base/src/nsFrameReflowState.cpp +++ b/mozilla/layout/html/base/src/nsFrameReflowState.cpp @@ -175,12 +175,15 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) nsresult result = frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)pos); - // Initialize the computed values to default values - // XXX Use specified values as defaults - computedWidth = 0; - computedLeftMargin = computedRightMargin = 0; - computedHeight = 0; - computedTopMargin = computedBottomMargin = 0; + // Compute margins from the specified margin style information + nsMargin margin; + ComputeMarginFor(frame, parentReflowState, margin); + + // These become the default computed values, and may be adjusted below + computedLeftMargin = margin.left; + computedRightMargin = margin.right; + computedTopMargin = margin.top; + computedBottomMargin = margin.bottom; mLineHeight = CalcLineHeight(aPresContext, frame); @@ -200,89 +203,117 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) break; } - // Look for stylistic constraints on the width/height - if (NS_OK == result) { - nscoord containingBlockWidth, containingBlockHeight; - nscoord width = -1, height = -1; - PRIntn widthUnit = pos->mWidth.GetUnit(); - PRIntn heightUnit = pos->mHeight.GetUnit(); + // If this is the root frame then set the computed width and + // height equal to the available space + if (nsnull == parentReflowState) { + computedWidth = maxSize.width; + computedHeight = maxSize.height; - // When a percentage is specified we need to find the containing - // block to use as the basis for the percentage computation. - if ((eStyleUnit_Percent == widthUnit) || - (eStyleUnit_Percent == heightUnit)) { - const nsHTMLReflowState* cbrs = - GetContainingBlockReflowState(parentReflowState); + } else { + // Get the containing block reflow state, because we'll need its + // computed width + const nsHTMLReflowState* cbrs = + GetContainingBlockReflowState(parentReflowState); + NS_ASSERTION(nsnull != cbrs, "no containing block"); - // If there is no containing block then pretend the width or - // height units are auto. - if (nsnull == cbrs) { - if (eStyleUnit_Percent == widthUnit) { - widthUnit = eStyleUnit_Auto; - } - if (eStyleUnit_Percent == heightUnit) { - heightUnit = eStyleUnit_Auto; - } - } - else { - if (eStyleUnit_Percent == widthUnit) { - containingBlockWidth = cbrs->computedWidth; - } - if (eStyleUnit_Percent == heightUnit) { - if (NS_UNCONSTRAINEDSIZE == cbrs->maxSize.height) { - // CSS2 spec, 10.5: if the height of the containing block - // is not specified explicitly then the value is - // interpreted like auto. - heightUnit = eStyleUnit_Auto; - } - else { - containingBlockHeight = cbrs->maxSize.height; - } - } + // Get the containing block width and height. We'll need them when + // calculating the computed width and height + nscoord containingBlockWidth = cbrs->computedWidth; + nscoord containingBlockHeight = cbrs->computedHeight; + PRIntn widthUnit = pos->mWidth.GetUnit(); + PRIntn heightUnit = pos->mHeight.GetUnit(); + + // Check for a percentage based height + if (eStyleUnit_Percent == heightUnit) { + // If the height of the containing block depends on the content height, + // the height is interpreted like 'auto' + if (NS_AUTOHEIGHT == cbrs->computedHeight) { + heightUnit = eStyleUnit_Auto; } } - switch (widthUnit) { - case eStyleUnit_Coord: - width = pos->mWidth.GetCoordValue(); - break; - case eStyleUnit_Percent: - width = nscoord(pos->mWidth.GetPercentValue() * containingBlockWidth); - break; - case eStyleUnit_Auto: - { - // XXX See section 10.3 of the css2 spec and then write this code! - nsMargin margin; - nsMargin borderPadding; - ComputeMarginFor(frame, parentReflowState, margin); - ComputeBorderPaddingFor(frame, parentReflowState, borderPadding); - width = maxSize.width - margin.left - margin.right - borderPadding.left - - borderPadding.right; - break; + // Compute border and padding + nsMargin borderPadding; + ComputeBorderPaddingFor(frame, parentReflowState, borderPadding); + + // Get the spacing style information + const nsStyleSpacing* spacing; + frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing); + + // Compute the content width + PRBool isAutoLeftMargin = eStyleUnit_Auto == spacing->mMargin.GetLeftUnit(); + PRBool isAutoRightMargin = eStyleUnit_Auto == spacing->mMargin.GetRightUnit(); + + if (eStyleUnit_Auto == widthUnit) { + // 'auto' values for left or right margins become 0 + if (isAutoLeftMargin) { + computedLeftMargin = 0; + } + if (isAutoRightMargin) { + computedRightMargin = 0; + } + + computedWidth = containingBlockWidth - computedLeftMargin - + computedRightMargin - borderPadding.left - borderPadding.right; + + } else { + if (eStyleUnit_Coord == widthUnit) { + computedWidth = pos->mWidth.GetCoordValue(); + } else if (eStyleUnit_Percent == widthUnit) { + computedWidth = nscoord(pos->mWidth.GetPercentValue() * containingBlockWidth); + } else { + NS_ASSERTION(PR_FALSE, "unexpected width constraint"); + } + + // Calculate the computed left and right margin + nscoord extra = containingBlockWidth - computedWidth - borderPadding.left - + borderPadding.right; + + // See whether we're over constrained + if (!isAutoLeftMargin && !isAutoRightMargin) { + // Neither margin is 'auto' so we're over constrained. Use the + // 'direction' property to tell which margin to ignore + const nsStyleDisplay* display; + frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); + + if (NS_STYLE_DIRECTION_LTR == display->mDirection) { + isAutoRightMargin = PR_TRUE; + } else { + isAutoLeftMargin = PR_TRUE; + } + } + + if (isAutoLeftMargin) { + if (isAutoRightMargin) { + // Both margins are 'auto' so their computed values are equal + if (extra <= 0) { + computedLeftMargin = computedRightMargin = 0; + } else { + computedLeftMargin = (extra + 1) / 2; + computedRightMargin = extra - computedLeftMargin; + } + } else { + computedLeftMargin = PR_MAX(0, extra - computedRightMargin); + } + + } else if (isAutoRightMargin) { + computedRightMargin = PR_MAX(0, extra - computedLeftMargin); } } + + // Compute the content height switch (heightUnit) { case eStyleUnit_Coord: - height = pos->mHeight.GetCoordValue(); + computedHeight = pos->mHeight.GetCoordValue(); break; case eStyleUnit_Percent: - height = nscoord(pos->mHeight.GetPercentValue() * containingBlockHeight); + computedHeight = nscoord(pos->mHeight.GetPercentValue() * containingBlockHeight); break; case eStyleUnit_Auto: - // XXX See section 10.6 of the css2 spec and then write this code! + computedHeight = NS_AUTOHEIGHT; break; } - - if (width > 0) { - computedWidth = width; - } - if (height > 0) { - computedHeight = height; - } } - - // XXX this is probably a good place to calculate auto margins too - // (section 10.3/10.6 of the spec) } nscoord diff --git a/mozilla/layout/html/base/src/nsHTMLFrame.cpp b/mozilla/layout/html/base/src/nsHTMLFrame.cpp index eaf986eff23..4a9f856121d 100644 --- a/mozilla/layout/html/base/src/nsHTMLFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLFrame.cpp @@ -167,27 +167,21 @@ RootFrame::Reflow(nsIPresContext& aPresContext, // Reflow our one and only child frame if (nsnull != mFirstChild) { // Note: the root frame does not have border or padding... - - // Compute the margins around the child frame - nsMargin childMargin; - nsHTMLReflowState::ComputeMarginFor(mFirstChild, &aReflowState, childMargin); - - // Compute the child frame's available space - nsSize kidMaxSize(aReflowState.maxSize.width - childMargin.left - childMargin.right, - aReflowState.maxSize.height - childMargin.top - childMargin.bottom); nsHTMLReflowMetrics desiredSize(nsnull); // We must pass in that the available height is unconstrained, because // constrained is only for when we're paginated... nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, - nsSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE)); + nsSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE)); if (isChildInitialReflow) { kidReflowState.reason = eReflowReason_Initial; kidReflowState.reflowCommand = nsnull; } // For a height that's 'auto', make the frame as big as the available space - if (!kidReflowState.HaveFixedContentHeight()) { - kidReflowState.computedHeight = kidMaxSize.height; + // minus and top and bottom margins + if (NS_AUTOHEIGHT == kidReflowState.computedHeight) { + kidReflowState.computedHeight = aReflowState.maxSize.height - + kidReflowState.computedTopMargin - kidReflowState.computedTopMargin; // Computed height is for the content area so reduce it by the amount of // space taken up by border and padding @@ -201,7 +195,8 @@ RootFrame::Reflow(nsIPresContext& aPresContext, if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { ReflowChild(mFirstChild, aPresContext, desiredSize, kidReflowState, aStatus); - nsRect rect(childMargin.left, childMargin.top, desiredSize.width, desiredSize.height); + nsRect rect(kidReflowState.computedLeftMargin, kidReflowState.computedTopMargin, + desiredSize.width, desiredSize.height); mFirstChild->SetRect(rect); // XXX We should resolve the details of who/when DidReflow() diff --git a/mozilla/layout/html/base/src/nsIHTMLReflow.h b/mozilla/layout/html/base/src/nsIHTMLReflow.h index 782401be6dc..9aadcf06294 100644 --- a/mozilla/layout/html/base/src/nsIHTMLReflow.h +++ b/mozilla/layout/html/base/src/nsIHTMLReflow.h @@ -306,13 +306,12 @@ struct nsHTMLReflowState : nsReflowState { nsIFrame* aFrame); protected: - // This method initializes the widthConstraint, heightConstraint and - // minSize values appropriately. It also initializes the frameType - // value as well. This method is automatically called by the various - // constructors. + // This method initializes various data members. It is automatically + // called by the various constructors void Init(nsIPresContext& aPresContext) { mRunInFrame = nsnull; mCompactMarginWidth = 0; + computedWidth = computedHeight = 0; DetermineFrameType(aPresContext); InitConstraints(aPresContext); } diff --git a/mozilla/layout/html/document/src/ua.css b/mozilla/layout/html/document/src/ua.css index 1b3a8fac742..e8b4dee592d 100644 --- a/mozilla/layout/html/document/src/ua.css +++ b/mozilla/layout/html/document/src/ua.css @@ -533,6 +533,7 @@ NOFRAMES { } :ROOT { + display: block; background-color: inherit; } diff --git a/mozilla/layout/style/ua.css b/mozilla/layout/style/ua.css index 1b3a8fac742..e8b4dee592d 100644 --- a/mozilla/layout/style/ua.css +++ b/mozilla/layout/style/ua.css @@ -533,6 +533,7 @@ NOFRAMES { } :ROOT { + display: block; background-color: inherit; }