Fix computation of a hypothetical box for abs pos frames which are descendants

of a rel-pos block.  Bug 363637, r+sr=dbaron
This commit is contained in:
bzbarsky%mit.edu 2006-12-18 03:00:23 +00:00
Родитель 9e8c9730ea
Коммит a96b2700a6
4 изменённых файлов: 168 добавлений и 41 удалений

Просмотреть файл

@ -537,37 +537,43 @@ nsHTMLReflowState::ComputeRelativeOffsets(const nsHTMLReflowState* cbrs,
}
}
// Returns the nearest containing block frame for the specified frame.
// Also returns the left, top, right, and bottom edges of the specified
// frame's content area. These are in the coordinate space of the block
// frame itself
static nsIFrame*
GetNearestContainingBlock(nsIFrame* aFrame, nsMargin& aContentArea)
nsIFrame*
nsHTMLReflowState::GetNearestContainingBlock(nsIFrame* aFrame, nscoord& aCBLeftEdge,
nscoord& aCBWidth)
{
for (aFrame = aFrame->GetParent(); aFrame && !aFrame->IsContainingBlock();
aFrame = aFrame->GetParent())
/* do nothing */;
if (aFrame) {
nsSize size = aFrame->GetSize();
NS_ASSERTION(aFrame, "Must find containing block somewhere");
NS_ASSERTION(aFrame != frame, "How did that happen?");
aContentArea.left = 0;
aContentArea.top = 0;
aContentArea.right = size.width;
aContentArea.bottom = size.height;
// Subtract off for border and padding. If it can't be computed because
// it's percentage based (for example) then just ignore it
nsStyleBorderPadding bPad;
nsMargin borderPadding;
nsStyleContext* styleContext = aFrame->GetStyleContext();
styleContext->GetBorderPaddingFor(bPad);
if (bPad.GetBorderPadding(borderPadding)) {
aContentArea.left += borderPadding.left;
aContentArea.top += borderPadding.top;
aContentArea.right -= borderPadding.right;
aContentArea.bottom -= borderPadding.bottom;
/* Now aFrame is the containing block we want */
/* Check whether the containing block is currently being reflown.
If so, use the info from the reflow state. */
const nsHTMLReflowState* state;
if (aFrame->GetStateBits() & NS_FRAME_IN_REFLOW) {
for (state = parentReflowState; state && state->frame != aFrame;
state = state->parentReflowState) {
/* do nothing */
}
} else {
state = nsnull;
}
if (state) {
aCBLeftEdge = state->mComputedBorderPadding.left;
aCBWidth = state->mComputedWidth;
} else {
/* Didn't find a reflow state for aFrame. Just compute the information we
want, on the assumption that aFrame already knows its size. This really
ought to be true by now. */
NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IN_REFLOW,
"aFrame shouldn't be in reflow; we'll lie if it is");
nsMargin borderPadding = aFrame->GetUsedBorderAndPadding();
aCBLeftEdge = borderPadding.left;
aCBWidth = aFrame->GetSize().width - borderPadding.LeftRight();
}
return aFrame;
@ -705,9 +711,10 @@ static PRBool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
// absolute containing block
void
nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
nsIFrame* aContainingBlock,
nsMargin& aBlockContentArea,
nsIFrame* aPlaceholderFrame,
nsIFrame* aContainingBlock,
nscoord aBlockLeftContentEdge,
nscoord aBlockContentWidth,
const nsHTMLReflowState* cbrs,
nsHypotheticalBox& aHypotheticalBox)
{
@ -741,8 +748,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// Determine the total amount of horizontal border/padding/margin that
// the element would have had if it had been in the flow. Note that we
// ignore any 'auto' and 'inherit' values
horizBorderPaddingMargin = CalculateHorizBorderPaddingMargin(aBlockContentArea.right -
aBlockContentArea.left);
horizBorderPaddingMargin = CalculateHorizBorderPaddingMargin(aBlockContentWidth);
if (NS_FRAME_IS_REPLACED(mFrameType) && (eStyleUnit_Auto == widthUnit)) {
// It's a replaced element with an 'auto' width so the box width is
@ -754,15 +760,15 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
} else if (eStyleUnit_Auto == widthUnit) {
// The box width is the containing block width
boxWidth = aBlockContentArea.right - aBlockContentArea.left;
boxWidth = aBlockContentWidth;
knowBoxWidth = PR_TRUE;
} else {
// We need to compute it. It's important we do this, because if it's
// percentage based this computed value may be different from the comnputed
// value calculated using the absolute containing block width
ComputeHorizontalValue(aBlockContentArea.right - aBlockContentArea.left,
widthUnit, mStylePosition->mWidth, boxWidth);
ComputeHorizontalValue(aBlockContentWidth, widthUnit, mStylePosition->mWidth,
boxWidth);
boxWidth += horizBorderPaddingMargin;
knowBoxWidth = PR_TRUE;
}
@ -843,7 +849,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// The placeholder represents the left edge of the hypothetical box
aHypotheticalBox.mLeft = placeholderOffset.x;
} else {
aHypotheticalBox.mLeft = aBlockContentArea.left;
aHypotheticalBox.mLeft = aBlockLeftContentEdge;
}
aHypotheticalBox.mLeftIsExact = PR_TRUE;
@ -854,7 +860,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// We can't compute the right edge because we don't know the desired
// width. So instead use the right content edge of the block parent,
// but remember it's not exact
aHypotheticalBox.mRight = aBlockContentArea.right;
aHypotheticalBox.mRight = aBlockLeftContentEdge + aBlockContentWidth;
aHypotheticalBox.mRightIsExact = PR_FALSE;
}
@ -863,7 +869,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
if (NS_STYLE_DISPLAY_INLINE == mStyleDisplay->mOriginalDisplay) {
aHypotheticalBox.mRight = placeholderOffset.x;
} else {
aHypotheticalBox.mRight = aBlockContentArea.right;
aHypotheticalBox.mRight = aBlockLeftContentEdge + aBlockContentWidth;
}
aHypotheticalBox.mRightIsExact = PR_TRUE;
@ -874,7 +880,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// We can't compute the left edge because we don't know the desired
// width. So instead use the left content edge of the block parent,
// but remember it's not exact
aHypotheticalBox.mLeft = aBlockContentArea.left;
aHypotheticalBox.mLeft = aBlockLeftContentEdge;
aHypotheticalBox.mLeftIsExact = PR_FALSE;
}
@ -931,10 +937,10 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
NS_ASSERTION(nsnull != placeholderFrame, "no placeholder frame");
// Find the nearest containing block frame to the placeholder frame,
// and return its content area left, top, right, and bottom edges
nsMargin cbContentArea;
nsIFrame* cbFrame = GetNearestContainingBlock(placeholderFrame,
cbContentArea);
// and return its left edge and width.
nscoord cbLeftEdge, cbWidth;
nsIFrame* cbFrame = GetNearestContainingBlock(placeholderFrame, cbLeftEdge,
cbWidth);
// If both 'left' and 'right' are 'auto' or both 'top' and 'bottom' are
// 'auto', then compute the hypothetical box of where the element would
@ -946,7 +952,7 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
(eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
CalculateHypotheticalBox(aPresContext, placeholderFrame, cbFrame,
cbContentArea, cbrs, hypotheticalBox);
cbLeftEdge, cbWidth, cbrs, hypotheticalBox);
}
// Initialize the 'left' and 'right' computed offsets

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<style>
body { background: white; }
.rel, body { position: relative; }
div > div { direction: ltr; height: 10px; }
div > div > div { width: 100px; background: lime; }
.rtl { direction: rtl; }
#testpercentmargin > div > div { margin: 0 4%; }
#testabsolutemargin > div > div { margin: 0 20px; }
#testpercentpadding > div { padding: 0 4%; }
#testabsolutepadding > div { padding: 0 20px; }
#testborderparent > div { border-width: 0 20px; border-color: white; border-style: solid; }
#testborderkid > div > div { border-width: 0 20px; border-color: white; border-style: solid; }
</style>
<body style="width: 500px; margin-left: 100px;">
<div id="testplain">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testpercentmargin">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testabsolutemargin">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testpercentpadding">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testabsolutepadding">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testborderparent">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testborderkid">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<style>
body { background: white; }
.rel, body { position: relative; }
div > div { direction: ltr; height: 10px; }
div > div > div { width: 100px; background: lime; position: absolute }
.rtl { direction: rtl; }
#testpercentmargin > div > div { margin: 0 4%; }
#testabsolutemargin > div > div { margin: 0 20px; }
#testpercentpadding > div { padding: 0 4%; }
#testabsolutepadding > div { padding: 0 20px; }
#testborderparent > div { border-width: 0 20px; border-color: white; border-style: solid; }
#testborderkid > div > div { border-width: 0 20px; border-color: white; border-style: solid; }
</style>
<body style="width: 500px; margin-left: 100px;">
<div id="testplain">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testpercentmargin">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testabsolutemargin">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testpercentpadding">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testabsolutepadding">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testborderparent">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
<div id="testborderkid">
<div><div></div></div>
<div class="rel"><div></div></div>
<div class="rtl"><div></div></div>
<div class="rel rtl"><div></div></div>
</div>
</body>
</html>

Просмотреть файл

@ -28,6 +28,7 @@ f== bugs/360065-1.html bugs/360065-1-ref.html # bug 18217
!= bugs/315620-1b.html bugs/315620-1-ref.html
== bugs/315620-2a.xhtml bugs/315620-2-ref.xhtml
!= bugs/315620-2b.xhtml bugs/315620-2-ref.xhtml
== bugs/363637-1.html bugs/363637-1-ref.html
# table-dom/
== table-dom/appendCells1.html table-dom/appendCells1-ref.html