From 09fde7e34ca7a2e685098cb579fb4ff46da16b9d Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Sat, 16 Jan 1999 20:58:17 +0000 Subject: [PATCH] Changed nsHTMLReflowState to compute 'offsets' for relatively positioned elements git-svn-id: svn://10.0.0.236/trunk@17926 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsBlockFrame.cpp | 5 +- .../layout/generic/nsBlockReflowContext.cpp | 37 +---- mozilla/layout/generic/nsBlockReflowContext.h | 6 +- mozilla/layout/generic/nsBlockReflowState.cpp | 5 +- mozilla/layout/generic/nsBlockReflowState.h | 5 +- mozilla/layout/generic/nsHTMLReflowState.cpp | 152 ++++++++++++++---- mozilla/layout/html/base/src/nsBlockFrame.cpp | 5 +- .../html/base/src/nsBlockReflowContext.cpp | 37 +---- .../html/base/src/nsBlockReflowContext.h | 6 +- .../html/base/src/nsBlockReflowState.cpp | 5 +- .../layout/html/base/src/nsBlockReflowState.h | 5 +- .../html/base/src/nsHTMLReflowState.cpp | 152 ++++++++++++++---- mozilla/layout/html/base/src/nsIHTMLReflow.h | 3 + 13 files changed, 281 insertions(+), 142 deletions(-) diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/generic/nsBlockReflowContext.cpp b/mozilla/layout/generic/nsBlockReflowContext.cpp index e8733c5568b..1b64a796a53 100644 --- a/mozilla/layout/generic/nsBlockReflowContext.cpp +++ b/mozilla/layout/generic/nsBlockReflowContext.cpp @@ -74,6 +74,7 @@ nsresult nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, const nsRect& aSpace, PRBool aIsAdjacentWithTop, + nsMargin& aComputedOffsets, nsReflowStatus& aFrameReflowStatus) { nsresult rv = NS_OK; @@ -121,6 +122,7 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, // Setup reflow state for reflowing the frame nsHTMLReflowState reflowState(mPresContext, aFrame, mOuterReflowState, availSize); + aComputedOffsets = reflowState.computedOffsets; reflowState.lineLayout = nsnull; reflowState.mRunInFrame = mRunInFrame; reflowState.mCompactMarginWidth = mCompactMarginWidth; @@ -247,6 +249,7 @@ nsBlockReflowContext::CollapseMargins(const nsMargin& aMargin, PRBool nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, nscoord aPrevBottomMargin, + const nsMargin& aComputedOffsets, nsRect& aInFlowBounds, nsRect& aCombinedRect) { @@ -341,7 +344,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, mFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)stylePos); if (NS_STYLE_POSITION_RELATIVE == stylePos->mPosition) { - ComputeRelativePosition(mFrame, stylePos, x, y); + x += aComputedOffsets.left - aComputedOffsets.right; + y += aComputedOffsets.top - aComputedOffsets.bottom; } // Compute combined-rect in callers coordinate system. The value @@ -391,34 +395,3 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, return fits; } -void -nsBlockReflowContext::ComputeRelativePosition(nsIFrame* aFrame, - const nsStylePosition* aStylePos, - nscoord& aX, nscoord& aY) -{ - nsStyleCoord coord; - - nscoord dx = 0; - switch (aStylePos->mOffset.GetLeftUnit()) { - case eStyleUnit_Percent: - printf("XXX: not yet implemented: % relative position\n"); - case eStyleUnit_Auto: - break; - case eStyleUnit_Coord: - dx = aStylePos->mOffset.GetLeft(coord).GetCoordValue(); - break; - } - aX += dx; - - nscoord dy = 0; - switch (aStylePos->mOffset.GetTopUnit()) { - case eStyleUnit_Percent: - printf("XXX: not yet implemented: % relative position\n"); - case eStyleUnit_Auto: - break; - case eStyleUnit_Coord: - dy = aStylePos->mOffset.GetTop(coord).GetCoordValue(); - break; - } - aY += dy; -} diff --git a/mozilla/layout/generic/nsBlockReflowContext.h b/mozilla/layout/generic/nsBlockReflowContext.h index 57df1ab73cb..abc1d70e387 100644 --- a/mozilla/layout/generic/nsBlockReflowContext.h +++ b/mozilla/layout/generic/nsBlockReflowContext.h @@ -50,10 +50,12 @@ public: nsresult ReflowBlock(nsIFrame* aFrame, const nsRect& aSpace, PRBool aIsAdjacentWithTop, + nsMargin& aComputedOffsets, nsReflowStatus& aReflowStatus); PRBool PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, nscoord aPrevBottomMargin, + const nsMargin& aComputedOffsets, nsRect& aInFlowBounds, nsRect& aCombinedRect); @@ -106,10 +108,6 @@ public: return b; } - static void ComputeRelativePosition(nsIFrame* aFrame, - const nsStylePosition* aStylePos, - nscoord& aX, nscoord& aY); - protected: nsIPresContext& mPresContext; nsLineLayout& mLineLayout; diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index 2d5f7e4f101..32d5c35bd46 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -213,6 +213,81 @@ nsHTMLReflowState::CalculateLeftRightMargin(const nsHTMLReflowState* aContaining } } +void +nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs, + const nsStylePosition* aPosition) +{ + nsStyleCoord coord; + const nsHTMLReflowState* pcbrs = nsnull; + + // If any of the offsets are 'inherit' we need to find the positioned + // containing block + if ((eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit())) { + + pcbrs = cbrs; + + while (nsnull != pcbrs) { + const nsStylePosition* position; + pcbrs->frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if ((NS_STYLE_POSITION_ABSOLUTE == position->mPosition) || + (NS_STYLE_POSITION_RELATIVE == position->mPosition)) { + break; + } + + pcbrs = (const nsHTMLReflowState*)pcbrs->parentReflowState; // XXX cast + } + } + + // For relatively positioned elements 'auto' becomes 0 + if (eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = pcbrs ? pcbrs->computedOffsets.left : 0; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = 0; + } else { + ComputeHorizontalValue(cbrs->computedWidth, aPosition->mOffset.GetLeftUnit(), + aPosition->mOffset.GetLeft(coord), + computedOffsets.left); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) { + computedOffsets.top = pcbrs ? pcbrs->computedOffsets.top : 0; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || + ((NS_AUTOHEIGHT == cbrs->computedHeight) && + (eStyleUnit_Percent == aPosition->mOffset.GetTopUnit()))) { + computedOffsets.top = 0; + } else { + ComputeVerticalValue(cbrs->computedHeight, aPosition->mOffset.GetTopUnit(), + aPosition->mOffset.GetTop(coord), + computedOffsets.top); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = pcbrs ? pcbrs->computedOffsets.right : 0; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = 0; + } else { + ComputeHorizontalValue(cbrs->computedWidth, aPosition->mOffset.GetRightUnit(), + aPosition->mOffset.GetRight(coord), + computedOffsets.right); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit()) { + computedOffsets.bottom = pcbrs ? pcbrs->computedOffsets.bottom : 0; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || + ((NS_AUTOHEIGHT == cbrs->computedHeight) && + (eStyleUnit_Percent == aPosition->mOffset.GetBottomUnit()))) { + computedOffsets.bottom = 0; + } else { + ComputeVerticalValue(cbrs->computedHeight, aPosition->mOffset.GetBottomUnit(), + aPosition->mOffset.GetBottom(coord), + computedOffsets.bottom); + } +} + void nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, const nsHTMLReflowState* cbrs, @@ -265,7 +340,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, // Initialize the 'left' and 'right' computed offsets PRBool leftIsAuto = PR_FALSE, rightIsAuto = PR_FALSE; nsStyleCoord coord; - if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { + if (eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = cbrs->computedOffsets.left; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { if (NS_STYLE_DIRECTION_LTR == display->mDirection) { computedOffsets.left = placeholderOffset.x; } else { @@ -277,7 +354,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, aPosition->mOffset.GetLeft(coord), computedOffsets.left); } - if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { + if (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = cbrs->computedOffsets.right; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { if (NS_STYLE_DIRECTION_RTL == display->mDirection) { computedOffsets.right = placeholderOffset.x; } else { @@ -347,7 +426,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, // Initialize the 'top' and 'bottom' computed offsets PRBool bottomIsAuto = PR_FALSE; - if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || + if (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) { + computedOffsets.top = cbrs->computedOffsets.top; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || ((NS_AUTOHEIGHT == containingBlockHeight) && (eStyleUnit_Percent == aPosition->mOffset.GetTopUnit()))) { // Use the placeholder position @@ -357,7 +438,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, ComputeVerticalValue(containingBlockHeight, aPosition->mOffset.GetTopUnit(), aPosition->mOffset.GetTop(coord), computedOffsets.top); } - if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || + if (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit()) { + computedOffsets.bottom = cbrs->computedOffsets.bottom; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || ((NS_AUTOHEIGHT == containingBlockHeight) && (eStyleUnit_Percent == aPosition->mOffset.GetBottomUnit()))) { if (eStyleUnit_Auto == heightUnit) { @@ -447,36 +530,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) nsresult result = frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)pos); - // 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; - - // Calculate the line height. - // XXX Do we need to do this for all elements or just inline non-replaced - // elements? - mLineHeight = CalcLineHeight(aPresContext, frame); - - // See if it's an inline non-replaced element - if (NS_CSS_FRAME_TYPE_INLINE == frameType) { - // 'width' property doesn't apply to inline non-replaced elements. The - // 'height' is given by the element's 'line-height' value - if (mLineHeight >= 0) { - computedHeight = mLineHeight; - } - return; // nothing else to compute - } - // If this is the root frame then set the computed width and // height equal to the available space if (nsnull == parentReflowState) { computedWidth = availableWidth; computedHeight = availableHeight; + computedLeftMargin = computedRightMargin = computedTopMargin = computedBottomMargin = 0; } else { // Get the containing block reflow state @@ -484,6 +543,39 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) GetContainingBlockReflowState(parentReflowState); NS_ASSERTION(nsnull != cbrs, "no containing block"); + // See if the element is relatively positioned + if (NS_STYLE_POSITION_RELATIVE == pos->mPosition) { + ComputeRelativeOffsets(cbrs, pos); + } else { + // Initialize offsets to 0 + computedOffsets.SizeTo(0, 0, 0, 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; + + // Calculate the line height. + // XXX Do we need to do this for all elements or just inline non-replaced + // elements? + mLineHeight = CalcLineHeight(aPresContext, frame); + + // See if it's an inline non-replaced element + if (NS_CSS_FRAME_TYPE_INLINE == frameType) { + // 'width' property doesn't apply to inline non-replaced elements. The + // 'height' is given by the element's 'line-height' value + if (mLineHeight >= 0) { + computedHeight = mLineHeight; + } + return; // nothing else to compute + } + // Get the containing block width and height. We'll need them when // calculating the computed width and height. For all elements other // than absolutely positioned elements, the containing block is formed @@ -729,6 +821,7 @@ nsHTMLReflowState::ComputeHorizontalValue(nscoord aContainingBlockWidth, const nsStyleCoord& aCoord, nscoord& aResult) { + NS_PRECONDITION(eStyleUnit_Inherit != aUnit, "unexpected unit"); aResult = 0; if (eStyleUnit_Percent == aUnit) { float pct = aCoord.GetPercentValue(); @@ -745,6 +838,7 @@ nsHTMLReflowState::ComputeVerticalValue(nscoord aContainingBlockHeight, const nsStyleCoord& aCoord, nscoord& aResult) { + NS_PRECONDITION(eStyleUnit_Inherit != aUnit, "unexpected unit"); aResult = 0; if (eStyleUnit_Percent == aUnit) { // Verify no one is trying to calculate a percentage based height against diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp index e8733c5568b..1b64a796a53 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp @@ -74,6 +74,7 @@ nsresult nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, const nsRect& aSpace, PRBool aIsAdjacentWithTop, + nsMargin& aComputedOffsets, nsReflowStatus& aFrameReflowStatus) { nsresult rv = NS_OK; @@ -121,6 +122,7 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame, // Setup reflow state for reflowing the frame nsHTMLReflowState reflowState(mPresContext, aFrame, mOuterReflowState, availSize); + aComputedOffsets = reflowState.computedOffsets; reflowState.lineLayout = nsnull; reflowState.mRunInFrame = mRunInFrame; reflowState.mCompactMarginWidth = mCompactMarginWidth; @@ -247,6 +249,7 @@ nsBlockReflowContext::CollapseMargins(const nsMargin& aMargin, PRBool nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, nscoord aPrevBottomMargin, + const nsMargin& aComputedOffsets, nsRect& aInFlowBounds, nsRect& aCombinedRect) { @@ -341,7 +344,8 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, mFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)stylePos); if (NS_STYLE_POSITION_RELATIVE == stylePos->mPosition) { - ComputeRelativePosition(mFrame, stylePos, x, y); + x += aComputedOffsets.left - aComputedOffsets.right; + y += aComputedOffsets.top - aComputedOffsets.bottom; } // Compute combined-rect in callers coordinate system. The value @@ -391,34 +395,3 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, return fits; } -void -nsBlockReflowContext::ComputeRelativePosition(nsIFrame* aFrame, - const nsStylePosition* aStylePos, - nscoord& aX, nscoord& aY) -{ - nsStyleCoord coord; - - nscoord dx = 0; - switch (aStylePos->mOffset.GetLeftUnit()) { - case eStyleUnit_Percent: - printf("XXX: not yet implemented: % relative position\n"); - case eStyleUnit_Auto: - break; - case eStyleUnit_Coord: - dx = aStylePos->mOffset.GetLeft(coord).GetCoordValue(); - break; - } - aX += dx; - - nscoord dy = 0; - switch (aStylePos->mOffset.GetTopUnit()) { - case eStyleUnit_Percent: - printf("XXX: not yet implemented: % relative position\n"); - case eStyleUnit_Auto: - break; - case eStyleUnit_Coord: - dy = aStylePos->mOffset.GetTop(coord).GetCoordValue(); - break; - } - aY += dy; -} diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.h b/mozilla/layout/html/base/src/nsBlockReflowContext.h index 57df1ab73cb..abc1d70e387 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowContext.h +++ b/mozilla/layout/html/base/src/nsBlockReflowContext.h @@ -50,10 +50,12 @@ public: nsresult ReflowBlock(nsIFrame* aFrame, const nsRect& aSpace, PRBool aIsAdjacentWithTop, + nsMargin& aComputedOffsets, nsReflowStatus& aReflowStatus); PRBool PlaceBlock(PRBool aForceFit, PRBool aApplyTopMargin, nscoord aPrevBottomMargin, + const nsMargin& aComputedOffsets, nsRect& aInFlowBounds, nsRect& aCombinedRect); @@ -106,10 +108,6 @@ public: return b; } - static void ComputeRelativePosition(nsIFrame* aFrame, - const nsStylePosition* aStylePos, - nscoord& aX, nscoord& aY); - protected: nsIPresContext& mPresContext; nsLineLayout& mLineLayout; diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index ff559f4dc3d..3761f32401c 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -2121,8 +2121,9 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, nsRect availSpace(availX, aState.mY, availWidth, availHeight); WillReflowFrame(aState, aLine, frame); nsReflowStatus frameReflowStatus; + nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, aState.IsAdjacentWithTop(), - frameReflowStatus); + computedOffsets, frameReflowStatus); if (NS_FAILED(rv)) { return rv; } @@ -2147,7 +2148,7 @@ nsBaseIBFrame::ReflowBlockFrame(nsBlockReflowState& aState, PRBool isAdjacentWithTop = aState.IsAdjacentWithTop(); PRBool applyTopMargin = aState.ShouldApplyTopMargin(); aKeepReflowGoing = brc.PlaceBlock(isAdjacentWithTop, applyTopMargin, - aState.mPrevBottomMargin, + aState.mPrevBottomMargin, computedOffsets, aLine->mBounds, aLine->mCombinedArea); if (aKeepReflowGoing) { // Some of the child block fit diff --git a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp index 2d5f7e4f101..32d5c35bd46 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp +++ b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp @@ -213,6 +213,81 @@ nsHTMLReflowState::CalculateLeftRightMargin(const nsHTMLReflowState* aContaining } } +void +nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs, + const nsStylePosition* aPosition) +{ + nsStyleCoord coord; + const nsHTMLReflowState* pcbrs = nsnull; + + // If any of the offsets are 'inherit' we need to find the positioned + // containing block + if ((eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) || + (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit())) { + + pcbrs = cbrs; + + while (nsnull != pcbrs) { + const nsStylePosition* position; + pcbrs->frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if ((NS_STYLE_POSITION_ABSOLUTE == position->mPosition) || + (NS_STYLE_POSITION_RELATIVE == position->mPosition)) { + break; + } + + pcbrs = (const nsHTMLReflowState*)pcbrs->parentReflowState; // XXX cast + } + } + + // For relatively positioned elements 'auto' becomes 0 + if (eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = pcbrs ? pcbrs->computedOffsets.left : 0; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = 0; + } else { + ComputeHorizontalValue(cbrs->computedWidth, aPosition->mOffset.GetLeftUnit(), + aPosition->mOffset.GetLeft(coord), + computedOffsets.left); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) { + computedOffsets.top = pcbrs ? pcbrs->computedOffsets.top : 0; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || + ((NS_AUTOHEIGHT == cbrs->computedHeight) && + (eStyleUnit_Percent == aPosition->mOffset.GetTopUnit()))) { + computedOffsets.top = 0; + } else { + ComputeVerticalValue(cbrs->computedHeight, aPosition->mOffset.GetTopUnit(), + aPosition->mOffset.GetTop(coord), + computedOffsets.top); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = pcbrs ? pcbrs->computedOffsets.right : 0; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = 0; + } else { + ComputeHorizontalValue(cbrs->computedWidth, aPosition->mOffset.GetRightUnit(), + aPosition->mOffset.GetRight(coord), + computedOffsets.right); + } + + if (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit()) { + computedOffsets.bottom = pcbrs ? pcbrs->computedOffsets.bottom : 0; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || + ((NS_AUTOHEIGHT == cbrs->computedHeight) && + (eStyleUnit_Percent == aPosition->mOffset.GetBottomUnit()))) { + computedOffsets.bottom = 0; + } else { + ComputeVerticalValue(cbrs->computedHeight, aPosition->mOffset.GetBottomUnit(), + aPosition->mOffset.GetBottom(coord), + computedOffsets.bottom); + } +} + void nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, const nsHTMLReflowState* cbrs, @@ -265,7 +340,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, // Initialize the 'left' and 'right' computed offsets PRBool leftIsAuto = PR_FALSE, rightIsAuto = PR_FALSE; nsStyleCoord coord; - if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { + if (eStyleUnit_Inherit == aPosition->mOffset.GetLeftUnit()) { + computedOffsets.left = cbrs->computedOffsets.left; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetLeftUnit()) { if (NS_STYLE_DIRECTION_LTR == display->mDirection) { computedOffsets.left = placeholderOffset.x; } else { @@ -277,7 +354,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, aPosition->mOffset.GetLeft(coord), computedOffsets.left); } - if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { + if (eStyleUnit_Inherit == aPosition->mOffset.GetRightUnit()) { + computedOffsets.right = cbrs->computedOffsets.right; + } else if (eStyleUnit_Auto == aPosition->mOffset.GetRightUnit()) { if (NS_STYLE_DIRECTION_RTL == display->mDirection) { computedOffsets.right = placeholderOffset.x; } else { @@ -347,7 +426,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, // Initialize the 'top' and 'bottom' computed offsets PRBool bottomIsAuto = PR_FALSE; - if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || + if (eStyleUnit_Inherit == aPosition->mOffset.GetTopUnit()) { + computedOffsets.top = cbrs->computedOffsets.top; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetTopUnit()) || ((NS_AUTOHEIGHT == containingBlockHeight) && (eStyleUnit_Percent == aPosition->mOffset.GetTopUnit()))) { // Use the placeholder position @@ -357,7 +438,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsIPresContext& aPresContext, ComputeVerticalValue(containingBlockHeight, aPosition->mOffset.GetTopUnit(), aPosition->mOffset.GetTop(coord), computedOffsets.top); } - if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || + if (eStyleUnit_Inherit == aPosition->mOffset.GetBottomUnit()) { + computedOffsets.bottom = cbrs->computedOffsets.bottom; + } else if ((eStyleUnit_Auto == aPosition->mOffset.GetBottomUnit()) || ((NS_AUTOHEIGHT == containingBlockHeight) && (eStyleUnit_Percent == aPosition->mOffset.GetBottomUnit()))) { if (eStyleUnit_Auto == heightUnit) { @@ -447,36 +530,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) nsresult result = frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)pos); - // 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; - - // Calculate the line height. - // XXX Do we need to do this for all elements or just inline non-replaced - // elements? - mLineHeight = CalcLineHeight(aPresContext, frame); - - // See if it's an inline non-replaced element - if (NS_CSS_FRAME_TYPE_INLINE == frameType) { - // 'width' property doesn't apply to inline non-replaced elements. The - // 'height' is given by the element's 'line-height' value - if (mLineHeight >= 0) { - computedHeight = mLineHeight; - } - return; // nothing else to compute - } - // If this is the root frame then set the computed width and // height equal to the available space if (nsnull == parentReflowState) { computedWidth = availableWidth; computedHeight = availableHeight; + computedLeftMargin = computedRightMargin = computedTopMargin = computedBottomMargin = 0; } else { // Get the containing block reflow state @@ -484,6 +543,39 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) GetContainingBlockReflowState(parentReflowState); NS_ASSERTION(nsnull != cbrs, "no containing block"); + // See if the element is relatively positioned + if (NS_STYLE_POSITION_RELATIVE == pos->mPosition) { + ComputeRelativeOffsets(cbrs, pos); + } else { + // Initialize offsets to 0 + computedOffsets.SizeTo(0, 0, 0, 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; + + // Calculate the line height. + // XXX Do we need to do this for all elements or just inline non-replaced + // elements? + mLineHeight = CalcLineHeight(aPresContext, frame); + + // See if it's an inline non-replaced element + if (NS_CSS_FRAME_TYPE_INLINE == frameType) { + // 'width' property doesn't apply to inline non-replaced elements. The + // 'height' is given by the element's 'line-height' value + if (mLineHeight >= 0) { + computedHeight = mLineHeight; + } + return; // nothing else to compute + } + // Get the containing block width and height. We'll need them when // calculating the computed width and height. For all elements other // than absolutely positioned elements, the containing block is formed @@ -729,6 +821,7 @@ nsHTMLReflowState::ComputeHorizontalValue(nscoord aContainingBlockWidth, const nsStyleCoord& aCoord, nscoord& aResult) { + NS_PRECONDITION(eStyleUnit_Inherit != aUnit, "unexpected unit"); aResult = 0; if (eStyleUnit_Percent == aUnit) { float pct = aCoord.GetPercentValue(); @@ -745,6 +838,7 @@ nsHTMLReflowState::ComputeVerticalValue(nscoord aContainingBlockHeight, const nsStyleCoord& aCoord, nscoord& aResult) { + NS_PRECONDITION(eStyleUnit_Inherit != aUnit, "unexpected unit"); aResult = 0; if (eStyleUnit_Percent == aUnit) { // Verify no one is trying to calculate a percentage based height against diff --git a/mozilla/layout/html/base/src/nsIHTMLReflow.h b/mozilla/layout/html/base/src/nsIHTMLReflow.h index 80f915d8637..1a5de865612 100644 --- a/mozilla/layout/html/base/src/nsIHTMLReflow.h +++ b/mozilla/layout/html/base/src/nsIHTMLReflow.h @@ -322,6 +322,9 @@ protected: nscoord containingBlockWidth, nscoord containingBlockHeight); + void ComputeRelativeOffsets(const nsHTMLReflowState* cbrs, + const nsStylePosition* aPosition); + void CalculateLeftRightMargin(const nsHTMLReflowState* aContainingBlockRS, const nsStyleSpacing* aSpacing, nscoord aComputedWidth,