Bug 1183431 - Ensure hypothetical box has a writing mode with the same block direction as the absolute containing block. r=dholbert

This commit is contained in:
Jonathan Kew 2015-08-06 21:01:31 +01:00
Родитель 04f89231e4
Коммит c97e4db638
4 изменённых файлов: 161 добавлений и 69 удалений

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

@ -587,4 +587,4 @@ load 1156222.html
load 1157011.html
load 1169420-1.html
load 1169420-2.html
asserts(1) load 1183431.html
load 1183431.html

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

@ -995,9 +995,9 @@ nsHTMLReflowState::ApplyRelativePositioning(nsIFrame* aFrame,
}
nsIFrame*
nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
nscoord& aCBIStartEdge,
nscoord& aCBISize)
nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
nscoord& aCBIStartEdge,
LogicalSize& aCBSize)
{
aFrame = aFrame->GetContainingBlock();
NS_ASSERTION(aFrame != frame, "How did that happen?");
@ -1021,7 +1021,7 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
WritingMode stateWM = state->GetWritingMode();
aCBIStartEdge =
state->ComputedLogicalBorderPadding().ConvertTo(wm, stateWM).IStart(wm);
aCBISize = state->ComputedSize(wm).ISize(wm);
aCBSize = state->ComputedSize(wm);
} 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
@ -1030,7 +1030,7 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
"aFrame shouldn't be in reflow; we'll lie if it is");
LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(wm);
aCBIStartEdge = borderPadding.IStart(wm);
aCBISize = aFrame->ISize(wm) - borderPadding.IStartEnd(wm);
aCBSize = aFrame->GetLogicalSize(wm) - borderPadding.Size(wm);
}
return aFrame;
@ -1080,71 +1080,81 @@ GetIntrinsicSizeFor(nsIFrame* aFrame, nsSize& aIntrinsicSize, nsIAtom* aFrameTyp
}
/**
* aInsideBoxSizing returns the part of the horizontal padding, border,
* and margin that goes inside the edge given by box-sizing;
* aInsideBoxSizing returns the part of the padding, border, and margin
* in the aAxis dimension that goes inside the edge given by box-sizing;
* aOutsideBoxSizing returns the rest.
*/
void
nsHTMLReflowState::CalculateInlineBorderPaddingMargin(
nscoord aContainingBlockISize,
nsHTMLReflowState::CalculateBorderPaddingMargin(
LogicalAxis aAxis,
nscoord aContainingBlockSize,
nscoord* aInsideBoxSizing,
nscoord* aOutsideBoxSizing)
{
WritingMode wm = GetWritingMode();
mozilla::css::Side inlineStart = wm.PhysicalSide(eLogicalSideIStart);
mozilla::css::Side inlineEnd = wm.PhysicalSide(eLogicalSideIEnd);
mozilla::css::Side startSide =
wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeStart));
mozilla::css::Side endSide =
wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeEnd));
const LogicalMargin& border =
LogicalMargin(wm, mStyleBorder->GetComputedBorder());
LogicalMargin padding(wm), margin(wm);
nsMargin styleBorder = mStyleBorder->GetComputedBorder();
nscoord borderStartEnd =
styleBorder.Side(startSide) + styleBorder.Side(endSide);
nscoord paddingStartEnd, marginStartEnd;
// See if the style system can provide us the padding directly
nsMargin stylePadding;
if (mStylePadding->GetPadding(stylePadding)) {
padding = LogicalMargin(wm, stylePadding);
paddingStartEnd =
stylePadding.Side(startSide) + stylePadding.Side(endSide);
} else {
// We have to compute the inline start and end values
padding.IStart(wm) = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockISize,
mStylePadding->mPadding.Get(inlineStart));
padding.IEnd(wm) = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockISize,
mStylePadding->mPadding.Get(inlineEnd));
// We have to compute the start and end values
nscoord start, end;
start = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockSize,
mStylePadding->mPadding.Get(startSide));
end = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockSize,
mStylePadding->mPadding.Get(endSide));
paddingStartEnd = start + end;
}
// See if the style system can provide us the margin directly
nsMargin styleMargin;
if (mStyleMargin->GetMargin(styleMargin)) {
margin = LogicalMargin(wm, styleMargin);
marginStartEnd =
styleMargin.Side(startSide) + styleMargin.Side(endSide);
} else {
// We have to compute the left and right values
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(inlineStart)) {
nscoord start, end;
// We have to compute the start and end values
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(startSide)) {
// XXX FIXME (or does CalculateBlockSideMargins do this?)
margin.IStart(wm) = 0; // just ignore
start = 0; // just ignore
} else {
margin.IStart(wm) = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockISize,
mStyleMargin->mMargin.Get(inlineStart));
start = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockSize,
mStyleMargin->mMargin.Get(startSide));
}
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(inlineEnd)) {
if (eStyleUnit_Auto == mStyleMargin->mMargin.GetUnit(endSide)) {
// XXX FIXME (or does CalculateBlockSideMargins do this?)
margin.IEnd(wm) = 0; // just ignore
end = 0; // just ignore
} else {
margin.IEnd(wm) = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockISize,
mStyleMargin->mMargin.Get(inlineEnd));
end = nsLayoutUtils::
ComputeCBDependentValue(aContainingBlockSize,
mStyleMargin->mMargin.Get(endSide));
}
marginStartEnd = start + end;
}
nscoord outside =
padding.IStartEnd(wm) + border.IStartEnd(wm) + margin.IStartEnd(wm);
nscoord outside = paddingStartEnd + borderStartEnd + marginStartEnd;
nscoord inside = 0;
switch (mStylePosition->mBoxSizing) {
case NS_STYLE_BOX_SIZING_BORDER:
inside += border.IStartEnd(wm);
inside += borderStartEnd;
// fall through
case NS_STYLE_BOX_SIZING_PADDING:
inside += padding.IStartEnd(wm);
inside += paddingStartEnd;
}
outside -= inside;
*aInsideBoxSizing = inside;
@ -1178,8 +1188,12 @@ static bool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
// Calculate the hypothetical box that the element would have if it were in
// the flow. The values returned are relative to the padding edge of the
// absolute containing block, in the actual containing block's writing mode.
// cbrs->frame is the actual containing block
// absolute containing block. The writing-mode of the hypothetical box will
// have the same block direction as the absolute containing block, but may
// differ in inline-bidi direction.
// In the code below, |cbrs->frame| is the absolute containing block, while
// |containingBlock| is the nearest block container of the placeholder frame,
// which may be different from the absolute containing block.
void
nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
@ -1192,16 +1206,20 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// Find the nearest containing block frame to the placeholder frame,
// and its inline-start edge and width.
nscoord blockIStartContentEdge, blockContentISize;
nscoord blockIStartContentEdge;
// Dummy writing mode for blockContentSize, will be changed as needed by
// GetHypotheticalBoxContainer.
WritingMode cbwm = cbrs->GetWritingMode();
LogicalSize blockContentSize(cbwm);
nsIFrame* containingBlock =
GetHypotheticalBoxContainer(aPlaceholderFrame, blockIStartContentEdge,
blockContentISize);
blockContentSize);
// Now blockContentSize is in containingBlock's writing mode.
// If it's a replaced element and it has a 'auto' value for
//'inline size', see if we can get the intrinsic size. This will allow
// us to exactly determine both the inline edges
WritingMode wm = containingBlock->GetWritingMode();
aHypotheticalBox.mWritingMode = wm;
nsStyleCoord styleISize = mStylePosition->ISize(wm);
bool isAutoISize = styleISize.GetUnit() == eStyleUnit_Auto;
@ -1230,8 +1248,9 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// been in the flow. Note that we ignore any 'auto' and 'inherit'
// values
nscoord insideBoxSizing, outsideBoxSizing;
CalculateInlineBorderPaddingMargin(blockContentISize,
&insideBoxSizing, &outsideBoxSizing);
CalculateBorderPaddingMargin(eLogicalAxisInline,
blockContentSize.ISize(wm),
&insideBoxSizing, &outsideBoxSizing);
if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
// It's a replaced element with an 'auto' inline size so the box
@ -1244,14 +1263,14 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
} else if (isAutoISize) {
// The box inline size is the containing block inline size
boxISize = blockContentISize;
boxISize = blockContentSize.ISize(wm);
knowBoxISize = 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 computed
// value calculated using the absolute containing block width
boxISize = ComputeISizeValue(blockContentISize,
boxISize = ComputeISizeValue(blockContentSize.ISize(wm),
insideBoxSizing, outsideBoxSizing,
styleISize) +
insideBoxSizing + outsideBoxSizing;
@ -1263,7 +1282,6 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// space of its containing block
// XXXbz the placeholder is not fully reflowed yet if our containing block is
// relatively positioned...
WritingMode cbwm = cbrs->GetWritingMode();
nsSize containerSize = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
? cbrs->ComputedSizeAsContainerIfConstrained()
: containingBlock->GetSize();
@ -1368,7 +1386,8 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// We can't compute the inline-end edge because we don't know the desired
// inline-size. So instead use the end content edge of the block parent,
// but remember it's not exact
aHypotheticalBox.mIEnd = blockIStartContentEdge + blockContentISize;
aHypotheticalBox.mIEnd =
blockIStartContentEdge + blockContentSize.ISize(wm);
#ifdef DEBUG
aHypotheticalBox.mIEndIsExact = false;
#endif
@ -1411,9 +1430,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// scroll, and thus avoid the resulting incremental reflow bugs.
cbOffset = containingBlock->GetOffsetTo(cbrs->frame);
}
nsSize cbrsSize =
cbrs->ComputedPhysicalSize() +
cbrs->ComputedLogicalBorderPadding().Size(cbwm).GetPhysicalSize(cbwm);
nsSize cbrsSize = cbrs->ComputedSizeAsContainerIfConstrained();
LogicalPoint logCBOffs(wm, cbOffset, cbrsSize - containerSize);
aHypotheticalBox.mIStart += logCBOffs.I(wm);
aHypotheticalBox.mIEnd += logCBOffs.I(wm);
@ -1428,6 +1445,74 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
aHypotheticalBox.mIStart -= border.IStart(wm);
aHypotheticalBox.mIEnd -= border.IStart(wm);
aHypotheticalBox.mBStart -= border.BStart(wm);
// At this point, we have computed aHypotheticalBox using the writing mode
// of the placeholder's containing block.
if (cbwm.GetBlockDir() != wm.GetBlockDir()) {
// If the block direction we used in calculating aHypotheticalBox does not
// match the absolute containing block's, we need to convert here so that
// aHypotheticalBox is usable in relation to the absolute containing block.
// This requires computing or measuring the abspos frame's block-size,
// which is not otherwise required/used here (as aHypotheticalBox records
// only the block-start coordinate).
// This is similar to the inline-size calculation for a replaced
// inline-level element or a block-level element (above), except that
// 'auto' sizing is handled differently in the block direction for non-
// replaced elements and replaced elements lacking an intrinsic size.
// Determine the total amount of block direction
// 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.
nscoord insideBoxSizing, outsideBoxSizing;
CalculateBorderPaddingMargin(eLogicalAxisBlock,
blockContentSize.BSize(wm),
&insideBoxSizing, &outsideBoxSizing);
nscoord boxBSize;
nsStyleCoord styleBSize = mStylePosition->BSize(wm);
bool isAutoBSize = styleBSize.GetUnit() == eStyleUnit_Auto;
if (isAutoBSize) {
if (NS_FRAME_IS_REPLACED(mFrameType) && knowIntrinsicSize) {
// It's a replaced element with an 'auto' block size so the box
// block size is its intrinsic size plus any border/padding/margin
boxBSize = LogicalSize(wm, intrinsicSize).BSize(wm) +
outsideBoxSizing + insideBoxSizing;
} else {
// XXX Bug 1191801
// Figure out how to get the correct boxBSize here (need to reflow the
// positioned frame?)
boxBSize = 0;
}
} 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
// computed value calculated using the absolute containing block height.
boxBSize = ComputeBSizeValue(blockContentSize.BSize(wm),
insideBoxSizing, styleBSize) +
insideBoxSizing + outsideBoxSizing;
}
LogicalSize boxSize(wm, knowBoxISize ? boxISize : 0, boxBSize);
LogicalPoint origin(wm, aHypotheticalBox.mIStart,
aHypotheticalBox.mBStart);
origin = origin.ConvertTo(cbwm, wm, cbrsSize -
boxSize.GetPhysicalSize(wm));
aHypotheticalBox.mIStart = origin.I(cbwm);
aHypotheticalBox.mIEnd = aHypotheticalBox.mIStart +
boxSize.ConvertTo(cbwm, wm).ISize(cbwm);
#ifdef DEBUG
aHypotheticalBox.mIEndIsExact = false; // it may be fake
#endif
aHypotheticalBox.mBStart = origin.B(cbwm);
aHypotheticalBox.mWritingMode = cbwm;
} else {
aHypotheticalBox.mWritingMode = wm;
}
}
void
@ -1523,8 +1608,6 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
if (bStartIsAuto && bEndIsAuto) {
// Treat 'top' like 'static-position'
NS_ASSERTION(hypotheticalBox.mWritingMode.GetBlockDir() == cbwm.GetBlockDir(),
"block direction mismatch");
offsets.BStart(cbwm) = hypotheticalBox.mBStart;
bStartIsAuto = false;
}

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

@ -909,13 +909,18 @@ protected:
// Returns the nearest containing block or block frame (whether or not
// it is a containing block) for the specified frame. Also returns
// the inline-start edge and inline size of the containing block's
// the inline-start edge and logical size of the containing block's
// content area.
// These are returned in the coordinate space of the containing block.
nsIFrame* GetHypotheticalBoxContainer(nsIFrame* aFrame,
nscoord& aCBIStartEdge,
nscoord& aCBISize);
mozilla::LogicalSize& aCBSize);
// Calculate a "hypothetical box" position where the placeholder frame
// (for a position:fixed/absolute element) would have been placed if it were
// positioned statically. The hypothetical box will have a writing mode with
// the same block direction as the absolute containing block (cbrs->frame),
// though it may differ in inline-bidi direction.
void CalculateHypotheticalBox(nsPresContext* aPresContext,
nsIFrame* aPlaceholderFrame,
const nsHTMLReflowState* cbrs,
@ -932,9 +937,13 @@ protected:
// data members
void ComputeMinMaxValues(const mozilla::LogicalSize& aContainingBlockSize);
void CalculateInlineBorderPaddingMargin(nscoord aContainingBlockISize,
nscoord* aInsideBoxSizing,
nscoord* aOutsideBoxSizing);
// aInsideBoxSizing returns the part of the padding, border, and margin
// in the aAxis dimension that goes inside the edge given by box-sizing;
// aOutsideBoxSizing returns the rest.
void CalculateBorderPaddingMargin(mozilla::LogicalAxis aAxis,
nscoord aContainingBlockSize,
nscoord* aInsideBoxSizing,
nscoord* aOutsideBoxSizing);
void CalculateBlockSideMargins(nsIAtom* aFrameType);
};

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

@ -100,27 +100,27 @@ fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) == s71-abs-pos-non-replaced-vrl
fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) == s71-abs-pos-non-replaced-vrl-094.xht s71-abs-pos-non-replaced-vrl-094-ref.xht
fuzzy-if(cocoaWidget,15,5) fuzzy-if(d2d,102,164) == s71-abs-pos-non-replaced-vrl-096.xht s71-abs-pos-non-replaced-vrl-096-ref.xht
asserts(2) fails == 1183431-orthogonal-modes-1a.html 1183431-orthogonal-modes-1-ref.html
== 1183431-orthogonal-modes-1a.html 1183431-orthogonal-modes-1-ref.html
== 1183431-orthogonal-modes-1b.html 1183431-orthogonal-modes-1-ref.html
== 1183431-orthogonal-modes-1c.html 1183431-orthogonal-modes-1-ref.html
asserts(2) fails == 1183431-orthogonal-modes-2a.html 1183431-orthogonal-modes-2-ref.html
== 1183431-orthogonal-modes-2a.html 1183431-orthogonal-modes-2-ref.html
== 1183431-orthogonal-modes-2b.html 1183431-orthogonal-modes-2-ref.html
== 1183431-orthogonal-modes-2c.html 1183431-orthogonal-modes-2-ref.html
asserts(2) fails == 1183431-orthogonal-modes-3a.html 1183431-orthogonal-modes-3-ref.html
== 1183431-orthogonal-modes-3a.html 1183431-orthogonal-modes-3-ref.html
== 1183431-orthogonal-modes-3b.html 1183431-orthogonal-modes-3-ref.html
== 1183431-orthogonal-modes-3c.html 1183431-orthogonal-modes-3-ref.html
asserts(2) fails == 1183431-orthogonal-modes-4a.html 1183431-orthogonal-modes-4-ref.html
== 1183431-orthogonal-modes-4a.html 1183431-orthogonal-modes-4-ref.html
== 1183431-orthogonal-modes-4b.html 1183431-orthogonal-modes-4-ref.html
== 1183431-orthogonal-modes-4c.html 1183431-orthogonal-modes-4-ref.html
asserts(2) fails == 1183431-orthogonal-modes-5a.html 1183431-orthogonal-modes-5-ref.html
== 1183431-orthogonal-modes-5a.html 1183431-orthogonal-modes-5-ref.html
== 1183431-orthogonal-modes-5b.html 1183431-orthogonal-modes-5-ref.html
== 1183431-orthogonal-modes-5c.html 1183431-orthogonal-modes-5-ref.html
asserts(2) fails == 1183431-orthogonal-modes-6a.html 1183431-orthogonal-modes-6-ref.html
fails == 1183431-orthogonal-modes-6a.html 1183431-orthogonal-modes-6-ref.html # bug 1191801
== 1183431-orthogonal-modes-6b.html 1183431-orthogonal-modes-6-ref.html
fails == 1183431-orthogonal-modes-6c.html 1183431-orthogonal-modes-6-ref.html
asserts(2) fails == 1183431-orthogonal-modes-7a.html 1183431-orthogonal-modes-7-ref.html
== 1183431-orthogonal-modes-6c.html 1183431-orthogonal-modes-6-ref.html
== 1183431-orthogonal-modes-7a.html 1183431-orthogonal-modes-7-ref.html
== 1183431-orthogonal-modes-7b.html 1183431-orthogonal-modes-7-ref.html
== 1183431-orthogonal-modes-7c.html 1183431-orthogonal-modes-7-ref.html
asserts(2) fails == 1183431-orthogonal-modes-8a.html 1183431-orthogonal-modes-8-ref.html
fails == 1183431-orthogonal-modes-8a.html 1183431-orthogonal-modes-8-ref.html # bug 1191801
== 1183431-orthogonal-modes-8b.html 1183431-orthogonal-modes-8-ref.html
== 1183431-orthogonal-modes-8c.html 1183431-orthogonal-modes-8-ref.html