зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1079151 - patch 1 - Update constraint calculations in nsHTMLReflowState to work with logical coordinates. r=smontagu
This commit is contained in:
Родитель
2e16faf502
Коммит
e4a31ad160
|
@ -1002,7 +1002,7 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
|
||||||
state = nullptr;
|
state = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
WritingMode wm = GetWritingMode();
|
WritingMode wm = aFrame->GetWritingMode();
|
||||||
if (state) {
|
if (state) {
|
||||||
WritingMode stateWM = state->GetWritingMode();
|
WritingMode stateWM = state->GetWritingMode();
|
||||||
aCBIStartEdge =
|
aCBIStartEdge =
|
||||||
|
@ -1016,31 +1016,31 @@ nsHTMLReflowState::GetHypotheticalBoxContainer(nsIFrame* aFrame,
|
||||||
"aFrame shouldn't be in reflow; we'll lie if it is");
|
"aFrame shouldn't be in reflow; we'll lie if it is");
|
||||||
LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(wm);
|
LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(wm);
|
||||||
aCBIStartEdge = borderPadding.IStart(wm);
|
aCBIStartEdge = borderPadding.IStart(wm);
|
||||||
aCBISize = aFrame->GetLogicalSize(wm).ISize(wm) -
|
aCBISize = aFrame->ISize(wm) - borderPadding.IStartEnd(wm);
|
||||||
borderPadding.IStartEnd(wm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return aFrame;
|
return aFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When determining the hypothetical box that would have been if the element
|
// When determining the hypothetical box that would have been if the element
|
||||||
// had been in the flow we may not be able to exactly determine both the left
|
// had been in the flow we may not be able to exactly determine both the IStart
|
||||||
// and right edges. For example, if the element is a non-replaced inline-level
|
// and IEnd edges. For example, if the element is a non-replaced inline-level
|
||||||
// element we would have to reflow it in order to determine it desired width.
|
// element we would have to reflow it in order to determine its desired ISize.
|
||||||
// In that case depending on the progression direction either the left or
|
// In that case depending on the progression direction either the IStart or
|
||||||
// right edge would be marked as not being exact
|
// IEnd edge would be marked as not being exact.
|
||||||
struct nsHypotheticalBox {
|
struct nsHypotheticalBox {
|
||||||
// offsets from left edge of containing block (which is a padding edge)
|
// offsets from inline-start edge of containing block (which is a padding edge)
|
||||||
nscoord mLeft, mRight;
|
nscoord mIStart, mIEnd;
|
||||||
// offset from top edge of containing block (which is a padding edge)
|
// offset from block-start edge of containing block (which is a padding edge)
|
||||||
nscoord mTop;
|
nscoord mBStart;
|
||||||
|
WritingMode mWritingMode;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool mLeftIsExact, mRightIsExact;
|
bool mIStartIsExact, mIEndIsExact;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsHypotheticalBox() {
|
nsHypotheticalBox() {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mLeftIsExact = mRightIsExact = false;
|
mIStartIsExact = mIEndIsExact = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1164,15 +1164,11 @@ static bool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
|
||||||
|
|
||||||
// Calculate the hypothetical box that the element would have if it were in
|
// 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
|
// the flow. The values returned are relative to the padding edge of the
|
||||||
// absolute containing block
|
// absolute containing block, in the actual containing block's writing mode.
|
||||||
// aContainingBlock is the placeholder's containing block (XXX rename it?)
|
|
||||||
// cbrs->frame is the actual containing block
|
// cbrs->frame is the actual containing block
|
||||||
void
|
void
|
||||||
nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
nsIFrame* aPlaceholderFrame,
|
nsIFrame* aPlaceholderFrame,
|
||||||
nsIFrame* aContainingBlock,
|
|
||||||
nscoord aBlockIStartContentEdge,
|
|
||||||
nscoord aBlockContentISize,
|
|
||||||
const nsHTMLReflowState* cbrs,
|
const nsHTMLReflowState* cbrs,
|
||||||
nsHypotheticalBox& aHypotheticalBox,
|
nsHypotheticalBox& aHypotheticalBox,
|
||||||
nsIAtom* aFrameType)
|
nsIAtom* aFrameType)
|
||||||
|
@ -1180,11 +1176,20 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
|
NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
|
||||||
"mOriginalDisplay has not been properly initialized");
|
"mOriginalDisplay has not been properly initialized");
|
||||||
|
|
||||||
|
// Find the nearest containing block frame to the placeholder frame,
|
||||||
|
// and its inline-start edge and width.
|
||||||
|
nscoord blockIStartContentEdge, blockContentISize;
|
||||||
|
nsIFrame* containingBlock =
|
||||||
|
GetHypotheticalBoxContainer(aPlaceholderFrame, blockIStartContentEdge,
|
||||||
|
blockContentISize);
|
||||||
|
|
||||||
// If it's a replaced element and it has a 'auto' value for
|
// 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
|
//'inline size', see if we can get the intrinsic size. This will allow
|
||||||
// us to exactly determine both the inline edges
|
// us to exactly determine both the inline edges
|
||||||
WritingMode cbWM = cbrs->GetWritingMode();
|
WritingMode wm = containingBlock->GetWritingMode();
|
||||||
nsStyleCoord styleISize = mStylePosition->ISize(cbWM);
|
aHypotheticalBox.mWritingMode = wm;
|
||||||
|
|
||||||
|
nsStyleCoord styleISize = mStylePosition->ISize(wm);
|
||||||
bool isAutoISize = styleISize.GetUnit() == eStyleUnit_Auto;
|
bool isAutoISize = styleISize.GetUnit() == eStyleUnit_Auto;
|
||||||
nsSize intrinsicSize;
|
nsSize intrinsicSize;
|
||||||
bool knowIntrinsicSize = false;
|
bool knowIntrinsicSize = false;
|
||||||
|
@ -1211,28 +1216,28 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
// been in the flow. Note that we ignore any 'auto' and 'inherit'
|
// been in the flow. Note that we ignore any 'auto' and 'inherit'
|
||||||
// values
|
// values
|
||||||
nscoord insideBoxSizing, outsideBoxSizing;
|
nscoord insideBoxSizing, outsideBoxSizing;
|
||||||
CalculateInlineBorderPaddingMargin(aBlockContentISize,
|
CalculateInlineBorderPaddingMargin(blockContentISize,
|
||||||
&insideBoxSizing, &outsideBoxSizing);
|
&insideBoxSizing, &outsideBoxSizing);
|
||||||
|
|
||||||
if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
|
if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
|
||||||
// It's a replaced element with an 'auto' inline size so the box
|
// It's a replaced element with an 'auto' inline size so the box
|
||||||
// inline size is its intrinsic size plus any border/padding/margin
|
// inline size is its intrinsic size plus any border/padding/margin
|
||||||
if (knowIntrinsicSize) {
|
if (knowIntrinsicSize) {
|
||||||
boxISize = LogicalSize(cbWM, intrinsicSize).ISize(cbWM) +
|
boxISize = LogicalSize(wm, intrinsicSize).ISize(wm) +
|
||||||
outsideBoxSizing + insideBoxSizing;
|
outsideBoxSizing + insideBoxSizing;
|
||||||
knowBoxISize = true;
|
knowBoxISize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isAutoISize) {
|
} else if (isAutoISize) {
|
||||||
// The box inline size is the containing block inline size
|
// The box inline size is the containing block inline size
|
||||||
boxISize = aBlockContentISize;
|
boxISize = blockContentISize;
|
||||||
knowBoxISize = true;
|
knowBoxISize = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// We need to compute it. It's important we do this, because if it's
|
// 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
|
// percentage based this computed value may be different from the computed
|
||||||
// value calculated using the absolute containing block width
|
// value calculated using the absolute containing block width
|
||||||
boxISize = ComputeISizeValue(aBlockContentISize,
|
boxISize = ComputeISizeValue(blockContentISize,
|
||||||
insideBoxSizing, outsideBoxSizing,
|
insideBoxSizing, outsideBoxSizing,
|
||||||
styleISize) +
|
styleISize) +
|
||||||
insideBoxSizing + outsideBoxSizing;
|
insideBoxSizing + outsideBoxSizing;
|
||||||
|
@ -1240,29 +1245,39 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the 'direction' of the block
|
|
||||||
const nsStyleVisibility* blockVis = aContainingBlock->StyleVisibility();
|
|
||||||
|
|
||||||
// Get the placeholder x-offset and y-offset in the coordinate
|
// Get the placeholder x-offset and y-offset in the coordinate
|
||||||
// space of its containing block
|
// space of its containing block
|
||||||
// XXXbz the placeholder is not fully reflowed yet if our containing block is
|
// XXXbz the placeholder is not fully reflowed yet if our containing block is
|
||||||
// relatively positioned...
|
// relatively positioned...
|
||||||
nsPoint placeholderOffset = aPlaceholderFrame->GetOffsetTo(aContainingBlock);
|
WritingMode cbwm = cbrs->GetWritingMode();
|
||||||
|
nscoord containerWidth = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
|
||||||
|
? cbrs->ComputedWidth() +
|
||||||
|
cbrs->ComputedLogicalBorderPadding().LeftRight(cbwm)
|
||||||
|
: containingBlock->GetSize().width;
|
||||||
|
LogicalPoint placeholderOffset(wm, aPlaceholderFrame->GetOffsetTo(containingBlock),
|
||||||
|
containerWidth);
|
||||||
|
|
||||||
// First, determine the hypothetical box's mTop. We want to check the
|
// XXX hack to correct for lack of LogicalPoint bidi support in vertical mode
|
||||||
// content insertion frame of aContainingBlock for block-ness, but make
|
if (wm.IsVertical() && !wm.IsBidiLTR()) {
|
||||||
|
placeholderOffset.I(wm) = cbrs->ComputedHeight() +
|
||||||
|
cbrs->ComputedLogicalBorderPadding().TopBottom(cbwm) -
|
||||||
|
placeholderOffset.I(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, determine the hypothetical box's mBStart. We want to check the
|
||||||
|
// content insertion frame of containingBlock for block-ness, but make
|
||||||
// sure to compute all coordinates in the coordinate system of
|
// sure to compute all coordinates in the coordinate system of
|
||||||
// aContainingBlock.
|
// containingBlock.
|
||||||
nsBlockFrame* blockFrame =
|
nsBlockFrame* blockFrame =
|
||||||
nsLayoutUtils::GetAsBlock(aContainingBlock->GetContentInsertionFrame());
|
nsLayoutUtils::GetAsBlock(containingBlock->GetContentInsertionFrame());
|
||||||
if (blockFrame) {
|
if (blockFrame) {
|
||||||
nscoord blockYOffset = blockFrame->GetOffsetTo(aContainingBlock).y;
|
LogicalPoint blockOffset(wm, blockFrame->GetOffsetTo(containingBlock), 0);
|
||||||
bool isValid;
|
bool isValid;
|
||||||
nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
|
nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
// Give up. We're probably dealing with somebody using
|
// Give up. We're probably dealing with somebody using
|
||||||
// position:absolute inside native-anonymous content anyway.
|
// position:absolute inside native-anonymous content anyway.
|
||||||
aHypotheticalBox.mTop = placeholderOffset.y;
|
aHypotheticalBox.mBStart = placeholderOffset.B(wm);
|
||||||
} else {
|
} else {
|
||||||
NS_ASSERTION(iter.GetContainer() == blockFrame,
|
NS_ASSERTION(iter.GetContainer() == blockFrame,
|
||||||
"Found placeholder in wrong block!");
|
"Found placeholder in wrong block!");
|
||||||
|
@ -1270,10 +1285,13 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
|
|
||||||
// How we determine the hypothetical box depends on whether the element
|
// How we determine the hypothetical box depends on whether the element
|
||||||
// would have been inline-level or block-level
|
// would have been inline-level or block-level
|
||||||
|
LogicalRect lineBounds =
|
||||||
|
lineBox->GetBounds().ConvertTo(wm, lineBox->mWritingMode,
|
||||||
|
lineBox->mContainerWidth);
|
||||||
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
|
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
|
||||||
// Use the top of the inline box which the placeholder lives in
|
// Use the block-start of the inline box which the placeholder lives in
|
||||||
// as the hypothetical box's top.
|
// as the hypothetical box's block-start.
|
||||||
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
|
aHypotheticalBox.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
|
||||||
} else {
|
} else {
|
||||||
// The element would have been block-level which means it would
|
// The element would have been block-level which means it would
|
||||||
// be below the line containing the placeholder frame, unless
|
// be below the line containing the placeholder frame, unless
|
||||||
|
@ -1298,81 +1316,51 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
// The top of the hypothetical box is the top of the line
|
// The top of the hypothetical box is the top of the line
|
||||||
// containing the placeholder, since there is nothing in the
|
// containing the placeholder, since there is nothing in the
|
||||||
// line before our placeholder except empty frames.
|
// line before our placeholder except empty frames.
|
||||||
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
|
aHypotheticalBox.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
|
||||||
} else {
|
} else {
|
||||||
// The top of the hypothetical box is just below the line
|
// The top of the hypothetical box is just below the line
|
||||||
// containing the placeholder.
|
// containing the placeholder.
|
||||||
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().YMost() + blockYOffset;
|
aHypotheticalBox.mBStart = lineBounds.BEnd(wm) + blockOffset.B(wm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just use the placeholder's y-offset wrt the containing block
|
// Just use the placeholder's block-offset wrt the containing block
|
||||||
aHypotheticalBox.mTop = placeholderOffset.y;
|
aHypotheticalBox.mBStart = placeholderOffset.B(wm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The containing block is not a block, so it's probably something
|
// The containing block is not a block, so it's probably something
|
||||||
// like a XUL box, etc.
|
// like a XUL box, etc.
|
||||||
// Just use the placeholder's y-offset
|
// Just use the placeholder's block-offset
|
||||||
aHypotheticalBox.mTop = placeholderOffset.y;
|
aHypotheticalBox.mBStart = placeholderOffset.B(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, determine the hypothetical box's mLeft & mRight
|
// Second, determine the hypothetical box's mIStart & mIEnd.
|
||||||
// To determine the left and right offsets we need to look at the block's 'direction'
|
// How we determine the hypothetical box depends on whether the element
|
||||||
if (NS_STYLE_DIRECTION_LTR == blockVis->mDirection) {
|
// would have been inline-level or block-level
|
||||||
// How we determine the hypothetical box depends on whether the element
|
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
|
||||||
// would have been inline-level or block-level
|
// The placeholder represents the left edge of the hypothetical box
|
||||||
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
|
aHypotheticalBox.mIStart = placeholderOffset.I(wm);
|
||||||
// The placeholder represents the left edge of the hypothetical box
|
|
||||||
aHypotheticalBox.mLeft = placeholderOffset.x;
|
|
||||||
} else {
|
|
||||||
aHypotheticalBox.mLeft = aBlockIStartContentEdge;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
aHypotheticalBox.mLeftIsExact = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (knowBoxISize) {
|
|
||||||
aHypotheticalBox.mRight = aHypotheticalBox.mLeft + boxISize;
|
|
||||||
#ifdef DEBUG
|
|
||||||
aHypotheticalBox.mRightIsExact = true;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
// 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 = aBlockIStartContentEdge + aBlockContentISize;
|
|
||||||
#ifdef DEBUG
|
|
||||||
aHypotheticalBox.mRightIsExact = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// The placeholder represents the right edge of the hypothetical box
|
aHypotheticalBox.mIStart = blockIStartContentEdge;
|
||||||
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
|
}
|
||||||
aHypotheticalBox.mRight = placeholderOffset.x;
|
|
||||||
} else {
|
|
||||||
aHypotheticalBox.mRight = aBlockIStartContentEdge + aBlockContentISize;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
aHypotheticalBox.mRightIsExact = true;
|
aHypotheticalBox.mIStartIsExact = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (knowBoxISize) {
|
if (knowBoxISize) {
|
||||||
aHypotheticalBox.mLeft = aHypotheticalBox.mRight - boxISize;
|
aHypotheticalBox.mIEnd = aHypotheticalBox.mIStart + boxISize;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
aHypotheticalBox.mLeftIsExact = true;
|
aHypotheticalBox.mIEndIsExact = true;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// We can't compute the left edge because we don't know the desired
|
// We can't compute the inline-end edge because we don't know the desired
|
||||||
// width. So instead use the left content edge of the block parent,
|
// inline-size. So instead use the end content edge of the block parent,
|
||||||
// but remember it's not exact
|
// but remember it's not exact
|
||||||
aHypotheticalBox.mLeft = aBlockIStartContentEdge;
|
aHypotheticalBox.mIEnd = blockIStartContentEdge + blockContentISize;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
aHypotheticalBox.mLeftIsExact = false;
|
aHypotheticalBox.mIEndIsExact = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The current coordinate space is that of the nearest block to the placeholder.
|
// The current coordinate space is that of the nearest block to the placeholder.
|
||||||
|
@ -1385,44 +1373,49 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
// Exclude cases inside -moz-transform where fixed is like absolute.
|
// Exclude cases inside -moz-transform where fixed is like absolute.
|
||||||
nsLayoutUtils::IsReallyFixedPos(frame)) {
|
nsLayoutUtils::IsReallyFixedPos(frame)) {
|
||||||
// In this case, cbrs->frame will likely be an ancestor of
|
// In this case, cbrs->frame will likely be an ancestor of
|
||||||
// aContainingBlock, so can just walk our way up the frame tree.
|
// containingBlock, so can just walk our way up the frame tree.
|
||||||
// Make sure to not add positions of frames whose parent is a
|
// Make sure to not add positions of frames whose parent is a
|
||||||
// scrollFrame, since we're doing fixed positioning, which assumes
|
// scrollFrame, since we're doing fixed positioning, which assumes
|
||||||
// everything is scrolled to (0,0).
|
// everything is scrolled to (0,0).
|
||||||
cbOffset.MoveTo(0, 0);
|
cbOffset.MoveTo(0, 0);
|
||||||
do {
|
do {
|
||||||
cbOffset += aContainingBlock->GetPositionIgnoringScrolling();
|
cbOffset += containingBlock->GetPositionIgnoringScrolling();
|
||||||
nsContainerFrame* parent = aContainingBlock->GetParent();
|
nsContainerFrame* parent = containingBlock->GetParent();
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
// Oops, our absolute containing block isn't an ancestor of the
|
// Oops, our absolute containing block isn't an ancestor of the
|
||||||
// placeholder's containing block. This can happen if the placeholder
|
// placeholder's containing block. This can happen if the placeholder
|
||||||
// is pushed to a different page in a printing context. 'cbOffset' is
|
// is pushed to a different page in a printing context. 'cbOffset' is
|
||||||
// currently relative to the root frame (aContainingBlock) - so just
|
// currently relative to the root frame (containingBlock) - so just
|
||||||
// subtract the offset to the absolute containing block to make it
|
// subtract the offset to the absolute containing block to make it
|
||||||
// relative to that.
|
// relative to that.
|
||||||
cbOffset -= aContainingBlock->GetOffsetTo(cbrs->frame);
|
cbOffset -= containingBlock->GetOffsetTo(cbrs->frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
aContainingBlock = parent;
|
containingBlock = parent;
|
||||||
} while (aContainingBlock != cbrs->frame);
|
} while (containingBlock != cbrs->frame);
|
||||||
} else {
|
} else {
|
||||||
// XXXldb We need to either ignore scrolling for the absolute
|
// XXXldb We need to either ignore scrolling for the absolute
|
||||||
// positioning case too (and take the incompatibility) or figure out
|
// positioning case too (and take the incompatibility) or figure out
|
||||||
// how to make these positioned elements actually *move* when we
|
// how to make these positioned elements actually *move* when we
|
||||||
// scroll, and thus avoid the resulting incremental reflow bugs.
|
// scroll, and thus avoid the resulting incremental reflow bugs.
|
||||||
cbOffset = aContainingBlock->GetOffsetTo(cbrs->frame);
|
cbOffset = containingBlock->GetOffsetTo(cbrs->frame);
|
||||||
}
|
}
|
||||||
aHypotheticalBox.mLeft += cbOffset.x;
|
nscoord cbrsWidth = cbrs->ComputedWidth() +
|
||||||
aHypotheticalBox.mTop += cbOffset.y;
|
cbrs->ComputedLogicalBorderPadding().LeftRight(cbwm);
|
||||||
aHypotheticalBox.mRight += cbOffset.x;
|
LogicalPoint logCBOffs(wm, cbOffset, cbrsWidth - containerWidth);
|
||||||
|
aHypotheticalBox.mIStart += logCBOffs.I(wm);
|
||||||
|
aHypotheticalBox.mIEnd += logCBOffs.I(wm);
|
||||||
|
aHypotheticalBox.mBStart += logCBOffs.B(wm);
|
||||||
|
|
||||||
// The specified offsets are relative to the absolute containing block's
|
// The specified offsets are relative to the absolute containing block's
|
||||||
// padding edge and our current values are relative to the border edge, so
|
// padding edge and our current values are relative to the border edge, so
|
||||||
// translate.
|
// translate.
|
||||||
nsMargin border = cbrs->ComputedPhysicalBorderPadding() - cbrs->ComputedPhysicalPadding();
|
LogicalMargin border =
|
||||||
aHypotheticalBox.mLeft -= border.left;
|
cbrs->ComputedLogicalBorderPadding() - cbrs->ComputedLogicalPadding();
|
||||||
aHypotheticalBox.mRight -= border.left;
|
border = border.ConvertTo(wm, cbrs->GetWritingMode());
|
||||||
aHypotheticalBox.mTop -= border.top;
|
aHypotheticalBox.mIStart -= border.IStart(wm);
|
||||||
|
aHypotheticalBox.mIEnd -= border.IStart(wm);
|
||||||
|
aHypotheticalBox.mBStart -= border.BStart(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1432,8 +1425,9 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
|
||||||
nsIAtom* aFrameType)
|
nsIAtom* aFrameType)
|
||||||
{
|
{
|
||||||
WritingMode wm = GetWritingMode();
|
WritingMode wm = GetWritingMode();
|
||||||
NS_PRECONDITION(aCBSize.BSize(wm) != NS_AUTOHEIGHT,
|
WritingMode cbwm = cbrs->GetWritingMode();
|
||||||
"containing block height must be constrained");
|
NS_PRECONDITION(aCBSize.BSize(cbwm) != NS_AUTOHEIGHT,
|
||||||
|
"containing block bsize must be constrained");
|
||||||
|
|
||||||
NS_ASSERTION(aFrameType != nsGkAtoms::tableFrame,
|
NS_ASSERTION(aFrameType != nsGkAtoms::tableFrame,
|
||||||
"InitAbsoluteConstraints should not be called on table frames");
|
"InitAbsoluteConstraints should not be called on table frames");
|
||||||
|
@ -1454,143 +1448,151 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
|
||||||
(eStyleUnit_Auto == mStylePosition->mOffset.GetRightUnit())) ||
|
(eStyleUnit_Auto == mStylePosition->mOffset.GetRightUnit())) ||
|
||||||
((eStyleUnit_Auto == mStylePosition->mOffset.GetTopUnit()) &&
|
((eStyleUnit_Auto == mStylePosition->mOffset.GetTopUnit()) &&
|
||||||
(eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
|
(eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
|
||||||
// Find the nearest containing block frame to the placeholder frame,
|
CalculateHypotheticalBox(aPresContext, placeholderFrame, cbrs,
|
||||||
// and return its left edge and width.
|
hypotheticalBox, aFrameType);
|
||||||
nscoord cbIStartEdge, cbISize;
|
|
||||||
nsIFrame* cbFrame = GetHypotheticalBoxContainer(placeholderFrame,
|
|
||||||
cbIStartEdge,
|
|
||||||
cbISize);
|
|
||||||
|
|
||||||
CalculateHypotheticalBox(aPresContext, placeholderFrame, cbFrame,
|
|
||||||
cbIStartEdge, cbISize, cbrs, hypotheticalBox,
|
|
||||||
aFrameType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the 'left' and 'right' computed offsets
|
// Initialize the 'left' and 'right' computed offsets
|
||||||
// XXX Handle new 'static-position' value...
|
// XXX Handle new 'static-position' value...
|
||||||
bool leftIsAuto = false, rightIsAuto = false;
|
|
||||||
if (eStyleUnit_Auto == mStylePosition->mOffset.GetLeftUnit()) {
|
bool iStartIsAuto = false, iEndIsAuto = false;
|
||||||
ComputedPhysicalOffsets().left = 0;
|
bool bStartIsAuto = false, bEndIsAuto = false;
|
||||||
leftIsAuto = true;
|
|
||||||
|
// Size of the containing block in its writing mode
|
||||||
|
LogicalSize cbSize = aCBSize;
|
||||||
|
|
||||||
|
LogicalMargin offsets = ComputedLogicalOffsets().ConvertTo(cbwm, wm);
|
||||||
|
|
||||||
|
if (eStyleUnit_Auto == mStylePosition->mOffset.GetIStartUnit(cbwm)) {
|
||||||
|
offsets.IStart(cbwm) = 0;
|
||||||
|
iStartIsAuto = true;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().left = nsLayoutUtils::
|
offsets.IStart(cbwm) = nsLayoutUtils::
|
||||||
ComputeCBDependentValue(aCBSize.ISize(wm),
|
ComputeCBDependentValue(cbSize.ISize(cbwm),
|
||||||
mStylePosition->mOffset.GetLeft());
|
mStylePosition->mOffset.GetIStart(cbwm));
|
||||||
}
|
}
|
||||||
if (eStyleUnit_Auto == mStylePosition->mOffset.GetRightUnit()) {
|
if (eStyleUnit_Auto == mStylePosition->mOffset.GetIEndUnit(cbwm)) {
|
||||||
ComputedPhysicalOffsets().right = 0;
|
offsets.IEnd(cbwm) = 0;
|
||||||
rightIsAuto = true;
|
iEndIsAuto = true;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().right = nsLayoutUtils::
|
offsets.IEnd(cbwm) = nsLayoutUtils::
|
||||||
ComputeCBDependentValue(aCBSize.ISize(wm),
|
ComputeCBDependentValue(cbSize.ISize(cbwm),
|
||||||
mStylePosition->mOffset.GetRight());
|
mStylePosition->mOffset.GetIEnd(cbwm));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the horizontal component of the hypothetical box in the cases
|
if (iStartIsAuto && iEndIsAuto) {
|
||||||
// where it's needed.
|
NS_ASSERTION(hypotheticalBox.mIStartIsExact, "should always have "
|
||||||
if (leftIsAuto && rightIsAuto) {
|
"exact value on containing block's start side");
|
||||||
// Use the direction of the original ("static-position") containing block
|
if (cbwm.IsBidiLTR() != hypotheticalBox.mWritingMode.IsBidiLTR()) {
|
||||||
// to dictate whether 'left' or 'right' is treated like 'static-position'.
|
offsets.IEnd(cbwm) = hypotheticalBox.mIStart;
|
||||||
if (NS_STYLE_DIRECTION_LTR == placeholderFrame->GetContainingBlock()
|
iEndIsAuto = false;
|
||||||
->StyleVisibility()->mDirection) {
|
|
||||||
NS_ASSERTION(hypotheticalBox.mLeftIsExact, "should always have "
|
|
||||||
"exact value on containing block's start side");
|
|
||||||
ComputedPhysicalOffsets().left = hypotheticalBox.mLeft;
|
|
||||||
leftIsAuto = false;
|
|
||||||
} else {
|
} else {
|
||||||
NS_ASSERTION(hypotheticalBox.mRightIsExact, "should always have "
|
offsets.IStart(cbwm) = hypotheticalBox.mIStart;
|
||||||
"exact value on containing block's start side");
|
iStartIsAuto = false;
|
||||||
ComputedPhysicalOffsets().right = aCBSize.ISize(wm) -
|
|
||||||
hypotheticalBox.mRight;
|
|
||||||
rightIsAuto = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the 'top' and 'bottom' computed offsets
|
if (eStyleUnit_Auto == mStylePosition->mOffset.GetBStartUnit(cbwm)) {
|
||||||
bool topIsAuto = false, bottomIsAuto = false;
|
offsets.BStart(cbwm) = 0;
|
||||||
if (eStyleUnit_Auto == mStylePosition->mOffset.GetTopUnit()) {
|
bStartIsAuto = true;
|
||||||
ComputedPhysicalOffsets().top = 0;
|
|
||||||
topIsAuto = true;
|
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().top = nsLayoutUtils::
|
offsets.BStart(cbwm) = nsLayoutUtils::
|
||||||
ComputeBSizeDependentValue(aCBSize.BSize(wm),
|
ComputeBSizeDependentValue(cbSize.BSize(cbwm),
|
||||||
mStylePosition->mOffset.GetTop());
|
mStylePosition->mOffset.GetBStart(cbwm));
|
||||||
}
|
}
|
||||||
if (eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()) {
|
if (eStyleUnit_Auto == mStylePosition->mOffset.GetBEndUnit(cbwm)) {
|
||||||
ComputedPhysicalOffsets().bottom = 0;
|
offsets.BEnd(cbwm) = 0;
|
||||||
bottomIsAuto = true;
|
bEndIsAuto = true;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().bottom = nsLayoutUtils::
|
offsets.BEnd(cbwm) = nsLayoutUtils::
|
||||||
ComputeBSizeDependentValue(aCBSize.BSize(wm),
|
ComputeBSizeDependentValue(cbSize.BSize(cbwm),
|
||||||
mStylePosition->mOffset.GetBottom());
|
mStylePosition->mOffset.GetBEnd(cbwm));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topIsAuto && bottomIsAuto) {
|
if (bStartIsAuto && bEndIsAuto) {
|
||||||
// Treat 'top' like 'static-position'
|
// Treat 'top' like 'static-position'
|
||||||
ComputedPhysicalOffsets().top = hypotheticalBox.mTop;
|
NS_ASSERTION(hypotheticalBox.mWritingMode.GetBlockDir() == cbwm.GetBlockDir(),
|
||||||
topIsAuto = false;
|
"block direction mismatch");
|
||||||
|
offsets.BStart(cbwm) = hypotheticalBox.mBStart;
|
||||||
|
bStartIsAuto = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool widthIsAuto = eStyleUnit_Auto == mStylePosition->mWidth.GetUnit();
|
SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
|
||||||
bool heightIsAuto = eStyleUnit_Auto == mStylePosition->mHeight.GetUnit();
|
|
||||||
|
bool iSizeIsAuto = eStyleUnit_Auto == mStylePosition->ISize(cbwm).GetUnit();
|
||||||
|
bool bSizeIsAuto = eStyleUnit_Auto == mStylePosition->BSize(cbwm).GetUnit();
|
||||||
|
|
||||||
typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
|
typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
|
||||||
ComputeSizeFlags computeSizeFlags = ComputeSizeFlags::eDefault;
|
ComputeSizeFlags computeSizeFlags = ComputeSizeFlags::eDefault;
|
||||||
if (leftIsAuto || rightIsAuto) {
|
if (wm.IsOrthogonalTo(cbwm)) {
|
||||||
computeSizeFlags =
|
if (bStartIsAuto || bEndIsAuto) {
|
||||||
ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
|
computeSizeFlags =
|
||||||
|
ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (iStartIsAuto || iEndIsAuto) {
|
||||||
|
computeSizeFlags =
|
||||||
|
ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogicalSize computedSize(wm);
|
||||||
{
|
{
|
||||||
AutoMaybeDisableFontInflation an(frame);
|
AutoMaybeDisableFontInflation an(frame);
|
||||||
|
|
||||||
LogicalSize size =
|
computedSize =
|
||||||
frame->ComputeSize(rendContext, wm, aCBSize,
|
frame->ComputeSize(rendContext, wm, cbSize.ConvertTo(wm, cbwm),
|
||||||
aCBSize.ISize(wm), // XXX or AvailableISize()?
|
cbSize.ConvertTo(wm, cbwm).ISize(wm), // XXX or AvailableISize()?
|
||||||
ComputedLogicalMargin().Size(wm) +
|
ComputedLogicalMargin().Size(wm) +
|
||||||
ComputedLogicalOffsets().Size(wm),
|
ComputedLogicalOffsets().Size(wm),
|
||||||
ComputedLogicalBorderPadding().Size(wm) -
|
ComputedLogicalBorderPadding().Size(wm) -
|
||||||
ComputedLogicalPadding().Size(wm),
|
ComputedLogicalPadding().Size(wm),
|
||||||
ComputedLogicalPadding().Size(wm),
|
ComputedLogicalPadding().Size(wm),
|
||||||
computeSizeFlags);
|
computeSizeFlags);
|
||||||
ComputedISize() = size.ISize(wm);
|
ComputedISize() = computedSize.ISize(wm);
|
||||||
ComputedBSize() = size.BSize(wm);
|
ComputedBSize() = computedSize.BSize(wm);
|
||||||
|
NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
|
||||||
|
NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
|
||||||
|
ComputedBSize() >= 0, "Bogus block-size");
|
||||||
}
|
}
|
||||||
NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
|
computedSize = computedSize.ConvertTo(cbwm, wm);
|
||||||
NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
|
|
||||||
ComputedBSize() >= 0, "Bogus block-size");
|
|
||||||
|
|
||||||
// XXX Now that we have ComputeSize, can we condense many of the
|
// XXX Now that we have ComputeSize, can we condense many of the
|
||||||
// branches off of widthIsAuto?
|
// branches off of widthIsAuto?
|
||||||
|
|
||||||
if (leftIsAuto) {
|
LogicalMargin margin = ComputedLogicalMargin().ConvertTo(cbwm, wm);
|
||||||
|
const LogicalMargin borderPadding =
|
||||||
|
ComputedLogicalBorderPadding().ConvertTo(cbwm, wm);
|
||||||
|
|
||||||
|
if (iStartIsAuto) {
|
||||||
// We know 'right' is not 'auto' anymore thanks to the hypothetical
|
// We know 'right' is not 'auto' anymore thanks to the hypothetical
|
||||||
// box code above.
|
// box code above.
|
||||||
// Solve for 'left'.
|
// Solve for 'left'.
|
||||||
if (widthIsAuto) {
|
if (iSizeIsAuto) {
|
||||||
// XXXldb This, and the corresponding code in
|
// XXXldb This, and the corresponding code in
|
||||||
// nsAbsoluteContainingBlock.cpp, could probably go away now that
|
// nsAbsoluteContainingBlock.cpp, could probably go away now that
|
||||||
// we always compute widths.
|
// we always compute widths.
|
||||||
ComputedPhysicalOffsets().left = NS_AUTOOFFSET;
|
offsets.IStart(cbwm) = NS_AUTOOFFSET;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().left = aCBSize.Width(wm) - ComputedPhysicalMargin().left -
|
offsets.IStart(cbwm) =
|
||||||
ComputedPhysicalBorderPadding().left - ComputedWidth() - ComputedPhysicalBorderPadding().right -
|
cbSize.ISize(cbwm) - offsets.IEnd(cbwm) -
|
||||||
ComputedPhysicalMargin().right - ComputedPhysicalOffsets().right;
|
computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
|
||||||
|
borderPadding.IStartEnd(cbwm);
|
||||||
}
|
}
|
||||||
} else if (rightIsAuto) {
|
} else if (iEndIsAuto) {
|
||||||
// We know 'left' is not 'auto' anymore thanks to the hypothetical
|
// We know 'left' is not 'auto' anymore thanks to the hypothetical
|
||||||
// box code above.
|
// box code above.
|
||||||
// Solve for 'right'.
|
// Solve for 'right'.
|
||||||
if (widthIsAuto) {
|
if (iSizeIsAuto) {
|
||||||
// XXXldb This, and the corresponding code in
|
// XXXldb This, and the corresponding code in
|
||||||
// nsAbsoluteContainingBlock.cpp, could probably go away now that
|
// nsAbsoluteContainingBlock.cpp, could probably go away now that
|
||||||
// we always compute widths.
|
// we always compute widths.
|
||||||
ComputedPhysicalOffsets().right = NS_AUTOOFFSET;
|
offsets.IEnd(cbwm) = NS_AUTOOFFSET;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().right = aCBSize.Width(wm) - ComputedPhysicalOffsets().left -
|
offsets.IEnd(cbwm) =
|
||||||
ComputedPhysicalMargin().left - ComputedPhysicalBorderPadding().left - ComputedWidth() -
|
cbSize.ISize(cbwm) - offsets.IStart(cbwm) -
|
||||||
ComputedPhysicalBorderPadding().right - ComputedPhysicalMargin().right;
|
computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
|
||||||
|
borderPadding.IStartEnd(cbwm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Neither 'left' nor 'right' is 'auto'. However, the width might
|
// Neither 'left' nor 'right' is 'auto'. However, the width might
|
||||||
|
@ -1600,43 +1602,35 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
|
||||||
// * we're dealing with a replaced element
|
// * we're dealing with a replaced element
|
||||||
// * width was constrained by min-width or max-width.
|
// * width was constrained by min-width or max-width.
|
||||||
|
|
||||||
nscoord availMarginSpace = aCBSize.Width(wm) -
|
nscoord availMarginSpace =
|
||||||
ComputedPhysicalOffsets().LeftRight() -
|
aCBSize.ISize(cbwm) - offsets.IStartEnd(cbwm) - margin.IStartEnd(cbwm) -
|
||||||
ComputedPhysicalMargin().LeftRight() -
|
borderPadding.IStartEnd(cbwm) - computedSize.ISize(cbwm);
|
||||||
ComputedPhysicalBorderPadding().LeftRight() -
|
bool marginIStartIsAuto =
|
||||||
ComputedWidth();
|
eStyleUnit_Auto == mStyleMargin->mMargin.GetIStartUnit(cbwm);
|
||||||
bool marginLeftIsAuto =
|
bool marginIEndIsAuto =
|
||||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetLeftUnit();
|
eStyleUnit_Auto == mStyleMargin->mMargin.GetIEndUnit(cbwm);
|
||||||
bool marginRightIsAuto =
|
|
||||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetRightUnit();
|
|
||||||
|
|
||||||
if (marginLeftIsAuto) {
|
if (marginIStartIsAuto) {
|
||||||
if (marginRightIsAuto) {
|
if (marginIEndIsAuto) {
|
||||||
if (availMarginSpace < 0) {
|
if (availMarginSpace < 0) {
|
||||||
// Note that this case is different from the neither-'auto'
|
// Note that this case is different from the neither-'auto'
|
||||||
// case below, where the spec says to ignore 'left'/'right'.
|
// case below, where the spec says to ignore 'left'/'right'.
|
||||||
if (cbrs &&
|
// Ignore the specified value for 'margin-right'.
|
||||||
NS_STYLE_DIRECTION_RTL == cbrs->mStyleVisibility->mDirection) {
|
margin.IEnd(cbwm) = availMarginSpace;
|
||||||
// Ignore the specified value for 'margin-left'.
|
|
||||||
ComputedPhysicalMargin().left = availMarginSpace;
|
|
||||||
} else {
|
|
||||||
// Ignore the specified value for 'margin-right'.
|
|
||||||
ComputedPhysicalMargin().right = availMarginSpace;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Both 'margin-left' and 'margin-right' are 'auto', so they get
|
// Both 'margin-left' and 'margin-right' are 'auto', so they get
|
||||||
// equal values
|
// equal values
|
||||||
ComputedPhysicalMargin().left = availMarginSpace / 2;
|
margin.IStart(cbwm) = availMarginSpace / 2;
|
||||||
ComputedPhysicalMargin().right = availMarginSpace - ComputedPhysicalMargin().left;
|
margin.IEnd(cbwm) = availMarginSpace - margin.IStart(cbwm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just 'margin-left' is 'auto'
|
// Just 'margin-left' is 'auto'
|
||||||
ComputedPhysicalMargin().left = availMarginSpace;
|
margin.IStart(cbwm) = availMarginSpace;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (marginRightIsAuto) {
|
if (marginIEndIsAuto) {
|
||||||
// Just 'margin-right' is 'auto'
|
// Just 'margin-right' is 'auto'
|
||||||
ComputedPhysicalMargin().right = availMarginSpace;
|
margin.IEnd(cbwm) = availMarginSpace;
|
||||||
} else {
|
} else {
|
||||||
// We're over-constrained so use the direction of the containing
|
// We're over-constrained so use the direction of the containing
|
||||||
// block to dictate which value to ignore. (And note that the
|
// block to dictate which value to ignore. (And note that the
|
||||||
|
@ -1645,95 +1639,100 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
|
||||||
// Note that this case is different from the both-'auto' case
|
// Note that this case is different from the both-'auto' case
|
||||||
// above, where the spec says to ignore
|
// above, where the spec says to ignore
|
||||||
// 'margin-left'/'margin-right'.
|
// 'margin-left'/'margin-right'.
|
||||||
if (cbrs &&
|
// Ignore the specified value for 'right'.
|
||||||
NS_STYLE_DIRECTION_RTL == cbrs->mStyleVisibility->mDirection) {
|
offsets.IEnd(cbwm) += availMarginSpace;
|
||||||
// Ignore the specified value for 'left'.
|
|
||||||
ComputedPhysicalOffsets().left += availMarginSpace;
|
|
||||||
} else {
|
|
||||||
// Ignore the specified value for 'right'.
|
|
||||||
ComputedPhysicalOffsets().right += availMarginSpace;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topIsAuto) {
|
if (bStartIsAuto) {
|
||||||
// solve for 'top'
|
// solve for block-start
|
||||||
if (heightIsAuto) {
|
if (bSizeIsAuto) {
|
||||||
ComputedPhysicalOffsets().top = NS_AUTOOFFSET;
|
offsets.BStart(cbwm) = NS_AUTOOFFSET;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().top = aCBSize.Height(wm) - ComputedPhysicalMargin().top -
|
offsets.BStart(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
|
||||||
ComputedPhysicalBorderPadding().top - ComputedHeight() - ComputedPhysicalBorderPadding().bottom -
|
borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
|
||||||
ComputedPhysicalMargin().bottom - ComputedPhysicalOffsets().bottom;
|
offsets.BEnd(cbwm);
|
||||||
}
|
}
|
||||||
} else if (bottomIsAuto) {
|
} else if (bEndIsAuto) {
|
||||||
// solve for 'bottom'
|
// solve for block-end
|
||||||
if (heightIsAuto) {
|
if (bSizeIsAuto) {
|
||||||
ComputedPhysicalOffsets().bottom = NS_AUTOOFFSET;
|
offsets.BEnd(cbwm) = NS_AUTOOFFSET;
|
||||||
} else {
|
} else {
|
||||||
ComputedPhysicalOffsets().bottom = aCBSize.Height(wm) - ComputedPhysicalOffsets().top -
|
offsets.BEnd(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
|
||||||
ComputedPhysicalMargin().top - ComputedPhysicalBorderPadding().top - ComputedHeight() -
|
borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
|
||||||
ComputedPhysicalBorderPadding().bottom - ComputedPhysicalMargin().bottom;
|
offsets.BStart(cbwm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Neither 'top' nor 'bottom' is 'auto'.
|
// Neither block-start nor -end is 'auto'.
|
||||||
nscoord autoHeight = aCBSize.Height(wm) -
|
nscoord autoBSize = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
|
||||||
ComputedPhysicalOffsets().TopBottom() -
|
borderPadding.BStartEnd(cbwm) - offsets.BStartEnd(cbwm);
|
||||||
ComputedPhysicalMargin().TopBottom() -
|
if (autoBSize < 0) {
|
||||||
ComputedPhysicalBorderPadding().TopBottom();
|
autoBSize = 0;
|
||||||
if (autoHeight < 0) {
|
|
||||||
autoHeight = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
|
if (computedSize.BSize(cbwm) == NS_UNCONSTRAINEDSIZE) {
|
||||||
// For non-replaced elements with 'height' auto, the 'height'
|
// For non-replaced elements with block-size auto, the block-size
|
||||||
// fills the remaining space.
|
// fills the remaining space.
|
||||||
ComputedHeight() = autoHeight;
|
computedSize.BSize(cbwm) = autoBSize;
|
||||||
|
|
||||||
// XXX Do these need box-sizing adjustments?
|
// XXX Do these need box-sizing adjustments?
|
||||||
if (ComputedHeight() > ComputedMaxHeight())
|
LogicalSize maxSize =
|
||||||
ComputedHeight() = ComputedMaxHeight();
|
LogicalSize(wm, ComputedMaxISize(),
|
||||||
if (ComputedHeight() < ComputedMinHeight())
|
ComputedMaxBSize()).ConvertTo(cbwm, wm);
|
||||||
ComputedHeight() = ComputedMinHeight();
|
LogicalSize minSize =
|
||||||
|
LogicalSize(wm, ComputedMinISize(),
|
||||||
|
ComputedMinBSize()).ConvertTo(cbwm, wm);
|
||||||
|
if (computedSize.BSize(cbwm) > maxSize.BSize(cbwm)) {
|
||||||
|
computedSize.BSize(cbwm) = maxSize.BSize(cbwm);
|
||||||
|
}
|
||||||
|
if (computedSize.BSize(cbwm) < minSize.BSize(cbwm)) {
|
||||||
|
computedSize.BSize(cbwm) = minSize.BSize(cbwm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The height might still not fill all the available space in case:
|
// The block-size might still not fill all the available space in case:
|
||||||
// * height was specified
|
// * bsize was specified
|
||||||
// * we're dealing with a replaced element
|
// * we're dealing with a replaced element
|
||||||
// * height was constrained by min-height or max-height.
|
// * bsize was constrained by min- or max-bsize.
|
||||||
nscoord availMarginSpace = autoHeight - ComputedHeight();
|
nscoord availMarginSpace = autoBSize - computedSize.BSize(cbwm);
|
||||||
bool marginTopIsAuto =
|
bool marginBStartIsAuto =
|
||||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetTopUnit();
|
eStyleUnit_Auto == mStyleMargin->mMargin.GetBStartUnit(cbwm);
|
||||||
bool marginBottomIsAuto =
|
bool marginBEndIsAuto =
|
||||||
eStyleUnit_Auto == mStyleMargin->mMargin.GetBottomUnit();
|
eStyleUnit_Auto == mStyleMargin->mMargin.GetBEndUnit(cbwm);
|
||||||
|
|
||||||
if (marginTopIsAuto) {
|
if (marginBStartIsAuto) {
|
||||||
if (marginBottomIsAuto) {
|
if (marginBEndIsAuto) {
|
||||||
if (availMarginSpace < 0) {
|
if (availMarginSpace < 0) {
|
||||||
// FIXME: Note that the spec doesn't actually say we should do this!
|
// FIXME: Note that the spec doesn't actually say we should do this!
|
||||||
ComputedPhysicalMargin().bottom = availMarginSpace;
|
margin.BEnd(cbwm) = availMarginSpace;
|
||||||
} else {
|
} else {
|
||||||
// Both 'margin-top' and 'margin-bottom' are 'auto', so they get
|
// Both margin-block-start and -end are 'auto', so they get
|
||||||
// equal values
|
// equal values
|
||||||
ComputedPhysicalMargin().top = availMarginSpace / 2;
|
margin.BStart(cbwm) = availMarginSpace / 2;
|
||||||
ComputedPhysicalMargin().bottom = availMarginSpace - ComputedPhysicalMargin().top;
|
margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just 'margin-top' is 'auto'
|
// Just margin-block-start is 'auto'
|
||||||
ComputedPhysicalMargin().top = availMarginSpace;
|
margin.BStart(cbwm) = availMarginSpace;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (marginBottomIsAuto) {
|
if (marginBEndIsAuto) {
|
||||||
// Just 'margin-bottom' is 'auto'
|
// Just margin-block-end is 'auto'
|
||||||
ComputedPhysicalMargin().bottom = availMarginSpace;
|
margin.BEnd(cbwm) = availMarginSpace;
|
||||||
} else {
|
} else {
|
||||||
// We're over-constrained so ignore the specified value for
|
// We're over-constrained so ignore the specified value for
|
||||||
// 'bottom'. (And note that the spec says to ignore 'bottom'
|
// block-end. (And note that the spec says to ignore 'bottom'
|
||||||
// rather than 'margin-bottom'.)
|
// rather than 'margin-bottom'.)
|
||||||
ComputedPhysicalOffsets().bottom += availMarginSpace;
|
offsets.BEnd(cbwm) += availMarginSpace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ComputedBSize() = computedSize.ConvertTo(wm, cbwm).BSize(wm);
|
||||||
|
ComputedISize() = computedSize.ConvertTo(wm, cbwm).ISize(wm);
|
||||||
|
|
||||||
|
SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
|
||||||
|
SetComputedLogicalMargin(margin.ConvertTo(wm, cbwm));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will not be converted to abstract coordinates because it's only
|
// This will not be converted to abstract coordinates because it's only
|
||||||
|
@ -1764,7 +1763,8 @@ GetBlockMarginBorderPadding(const nsHTMLReflowState* aReflowState)
|
||||||
* until it finds the canvas frame, or it encounters a frame that is not a block,
|
* until it finds the canvas frame, or it encounters a frame that is not a block,
|
||||||
* area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
|
* area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
|
||||||
*
|
*
|
||||||
* When we encounter scrolledContent block frames, we skip over them, since they are guaranteed to not be useful for computing the containing block.
|
* When we encounter scrolledContent block frames, we skip over them,
|
||||||
|
* since they are guaranteed to not be useful for computing the containing block.
|
||||||
*
|
*
|
||||||
* See also IsQuirkContainingBlockHeight.
|
* See also IsQuirkContainingBlockHeight.
|
||||||
*/
|
*/
|
||||||
|
@ -1838,13 +1838,15 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState)
|
||||||
if (firstAncestorRS) {
|
if (firstAncestorRS) {
|
||||||
nsIContent* frameContent = firstAncestorRS->frame->GetContent();
|
nsIContent* frameContent = firstAncestorRS->frame->GetContent();
|
||||||
if (frameContent) {
|
if (frameContent) {
|
||||||
NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::html), "First ancestor is not HTML");
|
NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::html),
|
||||||
|
"First ancestor is not HTML");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (secondAncestorRS) {
|
if (secondAncestorRS) {
|
||||||
nsIContent* frameContent = secondAncestorRS->frame->GetContent();
|
nsIContent* frameContent = secondAncestorRS->frame->GetContent();
|
||||||
if (frameContent) {
|
if (frameContent) {
|
||||||
NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body), "Second ancestor is not BODY");
|
NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body),
|
||||||
|
"Second ancestor is not BODY");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2011,15 +2013,19 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
|
||||||
ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
|
ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
|
||||||
ComputedPhysicalOffsets().SizeTo(0, 0, 0, 0);
|
ComputedPhysicalOffsets().SizeTo(0, 0, 0, 0);
|
||||||
|
|
||||||
ComputedWidth() = AvailableWidth() - ComputedPhysicalBorderPadding().LeftRight();
|
ComputedISize() =
|
||||||
if (ComputedWidth() < 0)
|
AvailableISize() - ComputedLogicalBorderPadding().IStartEnd(wm);
|
||||||
ComputedWidth() = 0;
|
if (ComputedISize() < 0) {
|
||||||
if (AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
|
ComputedISize() = 0;
|
||||||
ComputedHeight() = AvailableHeight() - ComputedPhysicalBorderPadding().TopBottom();
|
}
|
||||||
if (ComputedHeight() < 0)
|
if (AvailableBSize() != NS_UNCONSTRAINEDSIZE) {
|
||||||
ComputedHeight() = 0;
|
ComputedBSize() =
|
||||||
|
AvailableBSize() - ComputedLogicalBorderPadding().BStartEnd(wm);
|
||||||
|
if (ComputedBSize() < 0) {
|
||||||
|
ComputedBSize() = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ComputedHeight() = NS_UNCONSTRAINEDSIZE;
|
ComputedBSize() = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputedMinWidth() = ComputedMinHeight() = 0;
|
ComputedMinWidth() = ComputedMinHeight() = 0;
|
||||||
|
@ -2185,7 +2191,7 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext,
|
||||||
|
|
||||||
} else if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
|
} else if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
|
||||||
// XXX not sure if this belongs here or somewhere else - cwk
|
// XXX not sure if this belongs here or somewhere else - cwk
|
||||||
InitAbsoluteConstraints(aPresContext, cbrs, cbSize, aFrameType);
|
InitAbsoluteConstraints(aPresContext, cbrs, cbSize.ConvertTo(cbrs->GetWritingMode(), wm), aFrameType);
|
||||||
} else {
|
} else {
|
||||||
AutoMaybeDisableFontInflation an(frame);
|
AutoMaybeDisableFontInflation an(frame);
|
||||||
|
|
||||||
|
|
|
@ -422,9 +422,12 @@ struct nsHTMLReflowState : public nsCSSOffsetState {
|
||||||
const nsMargin& ComputedPhysicalOffsets() const { return mComputedOffsets; }
|
const nsMargin& ComputedPhysicalOffsets() const { return mComputedOffsets; }
|
||||||
nsMargin& ComputedPhysicalOffsets() { return mComputedOffsets; }
|
nsMargin& ComputedPhysicalOffsets() { return mComputedOffsets; }
|
||||||
|
|
||||||
LogicalMargin ComputedLogicalOffsets() const
|
const LogicalMargin ComputedLogicalOffsets() const
|
||||||
{ return LogicalMargin(mWritingMode, mComputedOffsets); }
|
{ return LogicalMargin(mWritingMode, mComputedOffsets); }
|
||||||
|
|
||||||
|
void SetComputedLogicalOffsets(const LogicalMargin& aOffsets)
|
||||||
|
{ mComputedOffsets = aOffsets.GetPhysicalMargin(mWritingMode); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// the available width in which to reflow the frame. The space
|
// the available width in which to reflow the frame. The space
|
||||||
// represents the amount of room for the frame's margin, border,
|
// represents the amount of room for the frame's margin, border,
|
||||||
|
@ -881,9 +884,6 @@ protected:
|
||||||
|
|
||||||
void CalculateHypotheticalBox(nsPresContext* aPresContext,
|
void CalculateHypotheticalBox(nsPresContext* aPresContext,
|
||||||
nsIFrame* aPlaceholderFrame,
|
nsIFrame* aPlaceholderFrame,
|
||||||
nsIFrame* aContainingBlock,
|
|
||||||
nscoord aBlockIStartContentEdge,
|
|
||||||
nscoord aBlockContentISize,
|
|
||||||
const nsHTMLReflowState* cbrs,
|
const nsHTMLReflowState* cbrs,
|
||||||
nsHypotheticalBox& aHypotheticalBox,
|
nsHypotheticalBox& aHypotheticalBox,
|
||||||
nsIAtom* aFrameType);
|
nsIAtom* aFrameType);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче