Bug 1887465 - Use the containing block's writing mode to resolve logical values for CSS float and clear properties. r=layout-reviewers,emilio

And don't resolve them prematurely; the computed value should remain
logical, and only be mapped to physical sides at use time.

Differential Revision: https://phabricator.services.mozilla.com/D229998
This commit is contained in:
Jonathan Kew
2024-11-25 14:02:26 +00:00
parent 32d924bc93
commit 64fa9b6bb6
21 changed files with 165 additions and 245 deletions

View File

@@ -2467,6 +2467,10 @@ StyleClear nsLayoutUtils::CombineClearType(StyleClear aOrigClearType,
case StyleClear::Both:
// Do nothing.
break;
case StyleClear::InlineStart:
case StyleClear::InlineEnd:
MOZ_ASSERT_UNREACHABLE("should have resolved to physical values");
break;
}
return clearType;
}

View File

@@ -154,7 +154,8 @@ void BRFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
}
// Return our reflow status
aStatus.SetInlineLineBreakAfter(aReflowInput.mStyleDisplay->mClear);
aStatus.SetInlineLineBreakAfter(
aReflowInput.mStyleDisplay->UsedClear(aReflowInput.GetCBWritingMode()));
ll->SetLineEndsInBR(true);
}

View File

@@ -303,7 +303,7 @@ bool BlockReflowState::FloatAvoidingBlockFitsInAvailSpace(
}
nsFlowAreaRect BlockReflowState::GetFloatAvailableSpaceWithState(
nscoord aBCoord, ShapeType aShapeType,
WritingMode aCBWM, nscoord aBCoord, ShapeType aShapeType,
nsFloatManager::SavedState* aState) const {
WritingMode wm = mReflowInput.GetWritingMode();
#ifdef DEBUG
@@ -319,7 +319,7 @@ nsFlowAreaRect BlockReflowState::GetFloatAvailableSpaceWithState(
? nscoord_MAX
: std::max(mContentArea.BEnd(wm) - aBCoord, 0);
nsFlowAreaRect result = FloatManager()->GetFlowArea(
wm, aBCoord, blockSize, BandInfoType::BandFromPoint, aShapeType,
aCBWM, wm, aBCoord, blockSize, BandInfoType::BandFromPoint, aShapeType,
mContentArea, aState, ContainerSize());
// Keep the inline size >= 0 for compatibility with nsSpaceManager.
if (result.mRect.ISize(wm) < 0) {
@@ -338,7 +338,8 @@ nsFlowAreaRect BlockReflowState::GetFloatAvailableSpaceWithState(
}
nsFlowAreaRect BlockReflowState::GetFloatAvailableSpaceForBSize(
nscoord aBCoord, nscoord aBSize, nsFloatManager::SavedState* aState) const {
WritingMode aCBWM, nscoord aBCoord, nscoord aBSize,
nsFloatManager::SavedState* aState) const {
WritingMode wm = mReflowInput.GetWritingMode();
#ifdef DEBUG
// Verify that the caller setup the coordinate system properly
@@ -349,7 +350,7 @@ nsFlowAreaRect BlockReflowState::GetFloatAvailableSpaceForBSize(
"bad coord system");
#endif
nsFlowAreaRect result = FloatManager()->GetFlowArea(
wm, aBCoord, aBSize, BandInfoType::WidthWithinHeight,
aCBWM, wm, aBCoord, aBSize, BandInfoType::WidthWithinHeight,
ShapeType::ShapeOutside, mContentArea, aState, ContainerSize());
// Keep the width >= 0 for compatibility with nsSpaceManager.
if (result.mRect.ISize(wm) < 0) {
@@ -573,9 +574,10 @@ bool BlockReflowState::AddFloat(nsLineLayout* aLineLayout, nsIFrame* aFloat,
// LineReflowStatus::RedoMoreFloats. We should use mLineBSize to query the
// correct available space.
nsFlowAreaRect floatAvailSpace =
mLineBSize.isNothing() ? GetFloatAvailableSpace(mBCoord)
: GetFloatAvailableSpaceForBSize(
mBCoord, mLineBSize.value(), nullptr);
mLineBSize.isNothing()
? GetFloatAvailableSpace(wm, mBCoord)
: GetFloatAvailableSpaceForBSize(wm, mBCoord, mLineBSize.value(),
nullptr);
LogicalRect availSpace(wm, floatAvailSpace.mRect.IStart(wm), mBCoord,
floatAvailSpace.mRect.ISize(wm),
floatAvailSpace.mRect.BSize(wm));
@@ -710,7 +712,7 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
// when floats are inserted before it.
if (StyleClear::None != floatDisplay->mClear) {
// XXXldb Does this handle vertical margins correctly?
auto [bCoord, result] = ClearFloats(mBCoord, floatDisplay->mClear);
auto [bCoord, result] = ClearFloats(mBCoord, floatDisplay->UsedClear(wm));
if (result == ClearFloatsResult::FloatsPushedOrSplit) {
PushFloatPastBreak(aFloat);
return PlaceFloatResult::ShouldPlaceInNextContinuation;
@@ -755,7 +757,7 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
// Find a place to place the float. The CSS2 spec doesn't want
// floats overlapping each other or sticking out of the containing
// block if possible (CSS2 spec section 9.5.1, see the rule list).
StyleFloat floatStyle = floatDisplay->mFloat;
StyleFloat floatStyle = floatDisplay->UsedFloat(wm);
MOZ_ASSERT(StyleFloat::Left == floatStyle || StyleFloat::Right == floatStyle,
"Invalid float type!");
@@ -767,7 +769,7 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
// Get the band of available space with respect to margin box.
nsFlowAreaRect floatAvailableSpace =
GetFloatAvailableSpaceForPlacingFloat(mBCoord);
GetFloatAvailableSpaceForPlacingFloat(wm, mBCoord);
for (;;) {
if (mReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
@@ -784,7 +786,7 @@ BlockReflowState::PlaceFloatResult BlockReflowState::FlowAndPlaceFloat(
// Nope. try to advance to the next band.
mBCoord += floatAvailableSpace.mRect.BSize(wm);
floatAvailableSpace = GetFloatAvailableSpaceForPlacingFloat(mBCoord);
floatAvailableSpace = GetFloatAvailableSpaceForPlacingFloat(wm, mBCoord);
mustPlaceFloat = false;
}
@@ -974,7 +976,8 @@ void BlockReflowState::PushFloatPastBreak(nsIFrame* aFloat) {
// must have their tops below the top of this float)
// * don't waste much time trying to reflow this float again until
// after the break
StyleFloat floatStyle = aFloat->StyleDisplay()->mFloat;
WritingMode wm = mReflowInput.GetWritingMode();
StyleFloat floatStyle = aFloat->StyleDisplay()->UsedFloat(wm);
if (floatStyle == StyleFloat::Left) {
FloatManager()->SetPushedLeftFloatPastBreak();
} else {
@@ -1045,8 +1048,10 @@ BlockReflowState::ClearFloats(nscoord aBCoord, StyleClear aClearType,
}
if (aFloatAvoidingBlock) {
auto cbWM = aFloatAvoidingBlock->GetContainingBlock()->GetWritingMode();
for (;;) {
nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newBCoord);
nsFlowAreaRect floatAvailableSpace =
GetFloatAvailableSpace(cbWM, newBCoord);
if (FloatAvoidingBlockFitsInAvailSpace(aFloatAvoidingBlock,
floatAvailableSpace)) {
break;

View File

@@ -110,6 +110,9 @@ class BlockReflowState {
* our coordinate system, which is the content box, with (0, 0) in the
* upper left.
*
* The parameter aCBWM is the containing block's writing mode, which is
* NOT necessarily the mode currently being used by the float manager.
*
* Returns whether there are floats present at the given block-direction
* coordinate and within the inline size of the content rect.
*
@@ -121,21 +124,24 @@ class BlockReflowState {
* negative value (in which case a 0-ISize float-avoiding block *should not*
* be considered as fitting, because it would intersect some float).
*/
nsFlowAreaRect GetFloatAvailableSpace() const {
return GetFloatAvailableSpace(mBCoord);
nsFlowAreaRect GetFloatAvailableSpace(WritingMode aCBWM) const {
return GetFloatAvailableSpace(aCBWM, mBCoord);
}
nsFlowAreaRect GetFloatAvailableSpaceForPlacingFloat(nscoord aBCoord) const {
return GetFloatAvailableSpaceWithState(aBCoord, ShapeType::Margin, nullptr);
}
nsFlowAreaRect GetFloatAvailableSpace(nscoord aBCoord) const {
return GetFloatAvailableSpaceWithState(aBCoord, ShapeType::ShapeOutside,
nsFlowAreaRect GetFloatAvailableSpaceForPlacingFloat(WritingMode aCBWM,
nscoord aBCoord) const {
return GetFloatAvailableSpaceWithState(aCBWM, aBCoord, ShapeType::Margin,
nullptr);
}
nsFlowAreaRect GetFloatAvailableSpace(WritingMode aCBWM,
nscoord aBCoord) const {
return GetFloatAvailableSpaceWithState(aCBWM, aBCoord,
ShapeType::ShapeOutside, nullptr);
}
nsFlowAreaRect GetFloatAvailableSpaceWithState(
nscoord aBCoord, ShapeType aShapeType,
WritingMode aCBWM, nscoord aBCoord, ShapeType aShapeType,
nsFloatManager::SavedState* aState) const;
nsFlowAreaRect GetFloatAvailableSpaceForBSize(
nscoord aBCoord, nscoord aBSize,
WritingMode aCBWM, nscoord aBCoord, nscoord aBSize,
nsFloatManager::SavedState* aState) const;
// @return true if AddFloat was able to place the float; false if the float

View File

@@ -296,6 +296,11 @@ nscoord SizeComputationInput::ComputeBSizeValue(
return nsLayoutUtils::ComputeBSizeValue(aContainingBlockBSize, inside, aSize);
}
WritingMode ReflowInput::GetCBWritingMode() const {
return mCBReflowInput ? mCBReflowInput->GetWritingMode()
: mFrame->GetContainingBlock()->GetWritingMode();
}
nsSize ReflowInput::ComputedSizeAsContainerIfConstrained() const {
LogicalSize size = ComputedSize();
if (size.ISize(mWritingMode) == NS_UNCONSTRAINEDSIZE) {
@@ -2378,8 +2383,8 @@ void ReflowInput::InitConstraints(
// flag.
return true;
}
if (!alignCB->IsGridContainerFrame() && mCBReflowInput &&
mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) {
if (!alignCB->IsGridContainerFrame() &&
mWritingMode.IsOrthogonalTo(GetCBWritingMode())) {
// Shrink-wrap blocks that are orthogonal to their container (unless
// we're in a grid?)
return true;
@@ -2605,8 +2610,7 @@ void ReflowInput::CalculateBlockSideMargins() {
// case, "CalculateBlock*Side*Margins" will actually end up adjusting
// the BStart/BEnd margins; those are the "sides" of the block from its
// container's point of view.
WritingMode cbWM =
mCBReflowInput ? mCBReflowInput->GetWritingMode() : GetWritingMode();
WritingMode cbWM = GetCBWritingMode();
nscoord availISizeCBWM = AvailableSize(cbWM).ISize(cbWM);
nscoord computedISizeCBWM = ComputedSize(cbWM).ISize(cbWM);

View File

@@ -358,6 +358,10 @@ struct ReflowInput : public SizeComputationInput {
// unconstrained dimensions replaced by zero.
nsSize ComputedSizeAsContainerIfConstrained() const;
// Get the writing mode of the containing block, to resolve float/clear
// logical sides appropriately.
WritingMode GetCBWritingMode() const;
// Our saved containing block dimensions.
LogicalSize mContainingBlockSize{mWritingMode};

View File

@@ -2188,4 +2188,32 @@ inline mozilla::StyleContentDistribution nsStylePosition::UsedContentAlignment(
return aAxis == mozilla::LogicalAxis::Block ? mAlignContent : mJustifyContent;
}
inline mozilla::StyleFloat nsStyleDisplay::UsedFloat(
mozilla::WritingMode aCBWM) const {
switch (mFloat) {
case mozilla::StyleFloat::InlineStart:
return aCBWM.IsBidiLTR() ? mozilla::StyleFloat::Left
: mozilla::StyleFloat::Right;
case mozilla::StyleFloat::InlineEnd:
return aCBWM.IsBidiLTR() ? mozilla::StyleFloat::Right
: mozilla::StyleFloat::Left;
default:
return mFloat;
}
}
inline mozilla::StyleClear nsStyleDisplay::UsedClear(
mozilla::WritingMode aCBWM) const {
switch (mClear) {
case mozilla::StyleClear::InlineStart:
return aCBWM.IsBidiLTR() ? mozilla::StyleClear::Left
: mozilla::StyleClear::Right;
case mozilla::StyleClear::InlineEnd:
return aCBWM.IsBidiLTR() ? mozilla::StyleClear::Right
: mozilla::StyleClear::Left;
default:
return mClear;
}
}
#endif // WritingModes_h_

View File

@@ -940,7 +940,7 @@ nscoord nsBlockFrame::PrefISize(const IntrinsicSizeInput& aInput) {
if (!data.mLineIsEmpty || BlockCanIntersectFloats(kid)) {
clearType = StyleClear::Both;
} else {
clearType = kid->StyleDisplay()->mClear;
clearType = kid->StyleDisplay()->UsedClear(GetWritingMode());
}
data.ForceBreak(clearType);
const IntrinsicSizeInput kidInput(aInput, kid->GetWritingMode(),
@@ -2920,8 +2920,9 @@ void nsBlockFrame::PropagateFloatDamage(BlockReflowState& aState,
} else {
bool wasImpactedByFloat = aLine->IsImpactedByFloat();
nsFlowAreaRect floatAvailableSpace =
aState.GetFloatAvailableSpaceForBSize(aLine->BStart() + aDeltaBCoord,
aLine->BSize(), nullptr);
aState.GetFloatAvailableSpaceForBSize(
aState.mReflowInput.GetWritingMode(),
aLine->BStart() + aDeltaBCoord, aLine->BSize(), nullptr);
#ifdef REALLY_NOISY_REFLOW
printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n", this,
@@ -3829,7 +3830,7 @@ bool nsBlockFrame::ReflowLine(BlockReflowState& aState, LineIterator aLine,
if (aState.mFlags.mCanHaveOverflowMarkers) {
WritingMode wm = aLine->mWritingMode;
nsFlowAreaRect r = aState.GetFloatAvailableSpaceForBSize(
aLine->BStart(), aLine->BSize(), nullptr);
wm, aLine->BStart(), aLine->BSize(), nullptr);
if (r.HasFloats()) {
LogicalRect so = aLine->GetOverflowArea(OverflowType::Scrollable, wm,
aLine->mContainerSize);
@@ -4168,7 +4169,8 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState,
// Prepare the block reflow engine
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowInput);
StyleClear clearType = frame->StyleDisplay()->mClear;
WritingMode cbWM = frame->GetContainingBlock()->GetWritingMode();
StyleClear clearType = frame->StyleDisplay()->UsedClear(cbWM);
if (aState.mTrailingClearFromPIF != StyleClear::None) {
clearType = nsLayoutUtils::CombineClearType(clearType,
aState.mTrailingClearFromPIF);
@@ -4353,7 +4355,7 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState,
// Here aState.mBCoord is the block-start border-edge of the block.
// Compute the available space for the block
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace(cbWM);
WritingMode wm = aState.mReflowInput.GetWritingMode();
LogicalRect availSpace = aState.ComputeBlockAvailSpace(
frame, floatAvailableSpace, (floatAvoidingBlock));
@@ -4510,7 +4512,7 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState,
LogicalRect oldFloatAvailableSpaceRect(floatAvailableSpace.mRect);
floatAvailableSpace = aState.GetFloatAvailableSpaceForBSize(
aState.mBCoord + bStartMargin, brc.GetMetrics().BSize(wm),
cbWM, aState.mBCoord + bStartMargin, brc.GetMetrics().BSize(wm),
&floatManagerState);
NS_ASSERTION(floatAvailableSpace.mRect.BStart(wm) ==
oldFloatAvailableSpaceRect.BStart(wm),
@@ -4547,7 +4549,7 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState,
// Start over with a new available space rect at the new height.
floatAvailableSpace = aState.GetFloatAvailableSpaceWithState(
aState.mBCoord, ShapeType::ShapeOutside, &floatManagerState);
cbWM, aState.mBCoord, ShapeType::ShapeOutside, &floatManagerState);
}
const LogicalRect oldAvailSpace = availSpace;
@@ -4836,7 +4838,8 @@ bool nsBlockFrame::ReflowInlineFrames(BlockReflowState& aState,
if (ShouldApplyBStartMargin(aState, aLine)) {
aState.mBCoord += aState.mPrevBEndMargin.Get();
}
nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
nsFlowAreaRect floatAvailableSpace =
aState.GetFloatAvailableSpace(GetWritingMode());
LineReflowStatus lineReflowStatus;
do {
@@ -5119,7 +5122,7 @@ void nsBlockFrame::DoReflowInlineFrames(
aState.mBCoord += aState.mPresContext->DevPixelsToAppUnits(1);
}
aFloatAvailableSpace = aState.GetFloatAvailableSpace();
aFloatAvailableSpace = aState.GetFloatAvailableSpace(GetWritingMode());
} else {
// There's nowhere to retry placing the line, so we want to push
// it to the next page/column where its contents can fit not
@@ -5365,7 +5368,8 @@ void nsBlockFrame::SplitFloat(BlockReflowState& aState, nsIFrame* aFloat,
nextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
}
StyleFloat floatStyle = aFloat->StyleDisplay()->mFloat;
StyleFloat floatStyle =
aFloat->StyleDisplay()->UsedFloat(aState.mReflowInput.GetWritingMode());
if (floatStyle == StyleFloat::Left) {
aState.FloatManager()->SetSplitLeftFloatAcrossBreak();
} else {
@@ -5550,10 +5554,10 @@ bool nsBlockFrame::PlaceLine(BlockReflowState& aState,
// the old BSize, but including the floats that were added in this line.
LogicalRect floatAvailableSpaceWithOldLineBSize =
aState.mLineBSize.isNothing()
? aState.GetFloatAvailableSpace(aLine->BStart()).mRect
? aState.GetFloatAvailableSpace(wm, aLine->BStart()).mRect
: aState
.GetFloatAvailableSpaceForBSize(
aLine->BStart(), aState.mLineBSize.value(), nullptr)
wm, aLine->BStart(), aState.mLineBSize.value(), nullptr)
.mRect;
// As we redo for floats, we can't reduce the amount of BSize we're
@@ -5561,8 +5565,8 @@ bool nsBlockFrame::PlaceLine(BlockReflowState& aState,
aAvailableSpaceBSize = std::max(aAvailableSpaceBSize, aLine->BSize());
LogicalRect floatAvailableSpaceWithLineBSize =
aState
.GetFloatAvailableSpaceForBSize(aLine->BStart(), aAvailableSpaceBSize,
nullptr)
.GetFloatAvailableSpaceForBSize(wm, aLine->BStart(),
aAvailableSpaceBSize, nullptr)
.mRect;
// If the available space between the floats is smaller now that we
@@ -5580,7 +5584,7 @@ bool nsBlockFrame::PlaceLine(BlockReflowState& aState,
// line is placed.
LogicalRect oldFloatAvailableSpace(aFlowArea.mRect);
aFlowArea = aState.GetFloatAvailableSpaceForBSize(
aLine->BStart(), aAvailableSpaceBSize, aFloatStateBeforeLine);
wm, aLine->BStart(), aAvailableSpaceBSize, aFloatStateBeforeLine);
NS_ASSERTION(
aFlowArea.mRect.BStart(wm) == oldFloatAvailableSpace.BStart(wm),
@@ -8323,7 +8327,8 @@ void nsBlockFrame::ReflowOutsideMarker(nsIFrame* aMarkerFrame,
// they reposition the line.
LogicalRect floatAvailSpace =
aState
.GetFloatAvailableSpaceWithState(aLineTop, ShapeType::ShapeOutside,
.GetFloatAvailableSpaceWithState(ri.GetWritingMode(), aLineTop,
ShapeType::ShapeOutside,
&aState.mFloatManagerStateBefore)
.mRect;
// FIXME (bug 25888): need to check the entire region that the first

View File

@@ -108,7 +108,7 @@ void nsFloatManager::Shutdown() {
"incompatible writing modes")
nsFlowAreaRect nsFloatManager::GetFlowArea(
WritingMode aWM, nscoord aBCoord, nscoord aBSize,
WritingMode aCBWM, WritingMode aWM, nscoord aBCoord, nscoord aBSize,
BandInfoType aBandInfoType, ShapeType aShapeType, LogicalRect aContentArea,
SavedState* aState, const nsSize& aContainerSize) const {
CHECK_BLOCK_AND_LINE_DIR(aWM);
@@ -199,7 +199,7 @@ nsFlowAreaRect nsFloatManager::GetFlowArea(
// This float is in our band.
// Shrink our band's width if needed.
StyleFloat floatStyle = fi.mFrame->StyleDisplay()->mFloat;
StyleFloat floatStyle = fi.mFrame->StyleDisplay()->UsedFloat(aCBWM);
// When aBandInfoType is BandFromPoint, we're only intended to
// consider a point along the y axis rather than a band.
@@ -285,7 +285,8 @@ void nsFloatManager::AddFloat(nsIFrame* aFloatFrame,
info.mLeftBEnd = nscoord_MIN;
info.mRightBEnd = nscoord_MIN;
}
StyleFloat floatStyle = aFloatFrame->StyleDisplay()->mFloat;
WritingMode cbWM = aFloatFrame->GetParent()->GetWritingMode();
StyleFloat floatStyle = aFloatFrame->StyleDisplay()->UsedFloat(cbWM);
MOZ_ASSERT(floatStyle == StyleFloat::Left || floatStyle == StyleFloat::Right,
"Unexpected float style!");
nscoord& sideBEnd =
@@ -317,7 +318,8 @@ LogicalRect nsFloatManager::CalculateRegionFor(WritingMode aWM,
// Preserve the right margin-edge for left floats and the left
// margin-edge for right floats
const nsStyleDisplay* display = aFloat->StyleDisplay();
StyleFloat floatStyle = display->mFloat;
WritingMode cbWM = aFloat->GetParent()->GetWritingMode();
StyleFloat floatStyle = display->UsedFloat(cbWM);
if ((StyleFloat::Left == floatStyle) == aWM.IsBidiLTR()) {
region.IStart(aWM) = region.IEnd(aWM);
}

View File

@@ -218,7 +218,8 @@ class nsFloatManager {
*/
enum class BandInfoType { BandFromPoint, WidthWithinHeight };
enum class ShapeType { Margin, ShapeOutside };
nsFlowAreaRect GetFlowArea(mozilla::WritingMode aWM, nscoord aBCoord,
nsFlowAreaRect GetFlowArea(mozilla::WritingMode aCBWM,
mozilla::WritingMode aWM, nscoord aBCoord,
nscoord aBSize, BandInfoType aBandInfoType,
ShapeType aShapeType,
mozilla::LogicalRect aContentArea,

View File

@@ -6158,7 +6158,8 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aClearType) {
for (const FloatInfo& floatInfo : mFloats) {
const nsStyleDisplay* floatDisp = floatInfo.Frame()->StyleDisplay();
StyleClear clearType = floatDisp->mClear;
auto cbWM = floatInfo.Frame()->GetParent()->GetWritingMode();
StyleClear clearType = floatDisp->UsedClear(cbWM);
if (clearType == StyleClear::Left || clearType == StyleClear::Right ||
clearType == StyleClear::Both) {
nscoord floatsCur = NSCoordSaturatingAdd(floatsCurLeft, floatsCurRight);
@@ -6173,7 +6174,7 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aClearType) {
}
}
StyleFloat floatStyle = floatDisp->mFloat;
StyleFloat floatStyle = floatDisp->UsedFloat(cbWM);
nscoord& floatsCur =
floatStyle == StyleFloat::Left ? floatsCurLeft : floatsCurRight;
nscoord floatISize = floatInfo.ISize();
@@ -6207,7 +6208,8 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aClearType) {
// no longer any floats we need to keep. See below.
for (FloatInfo& floatInfo : Reversed(mFloats)) {
const nsStyleDisplay* floatDisp = floatInfo.Frame()->StyleDisplay();
if (floatDisp->mFloat != clearFloatType) {
auto cbWM = floatInfo.Frame()->GetParent()->GetWritingMode();
if (floatDisp->UsedFloat(cbWM) != clearFloatType) {
newFloats.AppendElement(floatInfo);
} else {
// This is a float on the side that this break directly clears
@@ -6217,7 +6219,7 @@ void nsIFrame::InlinePrefISizeData::ForceBreak(StyleClear aClearType) {
// (earlier) floats on that side would be indirectly cleared
// as well. Thus, we should break out of this loop and stop
// considering earlier floats to be kept in mFloats.
StyleClear clearType = floatDisp->mClear;
StyleClear clearType = floatDisp->UsedClear(cbWM);
if (clearType != aClearType && clearType != StyleClear::None) {
break;
}

View File

@@ -194,6 +194,10 @@ static void ListFloats(FILE* out, const char* aPrefix,
return "right";
case StyleClear::Both:
return "both";
case StyleClear::InlineStart:
return "inline-start";
case StyleClear::InlineEnd:
return "inline-end";
}
return "unknown";
}

View File

@@ -1329,6 +1329,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
return mContainerType != mozilla::StyleContainerType::Normal;
}
// See WritingModes.h for the implementations.
inline mozilla::StyleFloat UsedFloat(mozilla::WritingMode aWM) const;
inline mozilla::StyleClear UsedClear(mozilla::WritingMode aWM) const;
private:
mozilla::StyleAppearance mAppearance;
mozilla::StyleContain mContain;

View File

@@ -92,11 +92,9 @@ ${helpers.predefined_type(
"Float",
"computed::Float::None",
engines="gecko servo",
initial_specified_value="specified::Float::None",
spec="https://drafts.csswg.org/css-box/#propdef-float",
animation_type="discrete",
spec="https://drafts.csswg.org/css-box/#propdef-float",
servo_restyle_damage="rebuild_and_reflow",
gecko_ffi_name="mFloat",
affects="layout",
)}

View File

@@ -16,8 +16,8 @@ use std::fmt;
use style_traits::{CssWriter, ToCss};
pub use crate::values::specified::box_::{
Appearance, BaselineSource, BreakBetween, BreakWithin, Clear as SpecifiedClear, Contain,
ContainerName, ContainerType, ContentVisibility, Display, Float as SpecifiedFloat, Overflow,
Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain,
ContainerName, ContainerType, ContentVisibility, Display, Float, Overflow,
OverflowAnchor, OverflowClipBox, OverscrollBehavior, ScrollSnapAlign, ScrollSnapAxis,
ScrollSnapStop, ScrollSnapStrictness, ScrollSnapType, ScrollbarGutter, TouchAction, WillChange,
};
@@ -58,156 +58,6 @@ impl Animate for LineClamp {
/// A computed value for the `perspective` property.
pub type Perspective = GenericPerspective<NonNegativeLength>;
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
FromPrimitive,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToCss,
ToResolvedValue,
)]
#[repr(u8)]
/// A computed value for the `float` property.
pub enum Float {
Left,
Right,
None,
}
impl Float {
/// Returns true if `self` is not `None`.
pub fn is_floating(self) -> bool {
self != Self::None
}
}
impl ToComputedValue for SpecifiedFloat {
type ComputedValue = Float;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
let ltr = context.style().writing_mode.is_bidi_ltr();
// https://drafts.csswg.org/css-logical-props/#float-clear
match *self {
SpecifiedFloat::InlineStart => {
context
.rule_cache_conditions
.borrow_mut()
.set_writing_mode_dependency(context.builder.writing_mode);
if ltr {
Float::Left
} else {
Float::Right
}
},
SpecifiedFloat::InlineEnd => {
context
.rule_cache_conditions
.borrow_mut()
.set_writing_mode_dependency(context.builder.writing_mode);
if ltr {
Float::Right
} else {
Float::Left
}
},
SpecifiedFloat::Left => Float::Left,
SpecifiedFloat::Right => Float::Right,
SpecifiedFloat::None => Float::None,
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> SpecifiedFloat {
match *computed {
Float::Left => SpecifiedFloat::Left,
Float::Right => SpecifiedFloat::Right,
Float::None => SpecifiedFloat::None,
}
}
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
FromPrimitive,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToCss,
ToResolvedValue,
)]
/// A computed value for the `clear` property.
#[repr(u8)]
pub enum Clear {
None,
Left,
Right,
Both,
}
impl ToComputedValue for SpecifiedClear {
type ComputedValue = Clear;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
let ltr = context.style().writing_mode.is_bidi_ltr();
// https://drafts.csswg.org/css-logical-props/#float-clear
match *self {
SpecifiedClear::InlineStart => {
context
.rule_cache_conditions
.borrow_mut()
.set_writing_mode_dependency(context.builder.writing_mode);
if ltr {
Clear::Left
} else {
Clear::Right
}
},
SpecifiedClear::InlineEnd => {
context
.rule_cache_conditions
.borrow_mut()
.set_writing_mode_dependency(context.builder.writing_mode);
if ltr {
Clear::Right
} else {
Clear::Left
}
},
SpecifiedClear::None => Clear::None,
SpecifiedClear::Left => Clear::Left,
SpecifiedClear::Right => Clear::Right,
SpecifiedClear::Both => Clear::Both,
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> SpecifiedClear {
match *computed {
Clear::None => SpecifiedClear::None,
Clear::Left => SpecifiedClear::Left,
Clear::Right => SpecifiedClear::Right,
Clear::Both => SpecifiedClear::Both,
}
}
}
/// A computed value for the `resize` property.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]

View File

@@ -1381,12 +1381,26 @@ impl Parse for ContainerName {
/// A specified value for the `perspective` property.
pub type Perspective = GenericPerspective<NonNegativeLength>;
/// https://drafts.csswg.org/css-box/#propdef-float
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
Clone,
Copy,
Debug,
Eq,
FromPrimitive,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
/// https://drafts.csswg.org/css-box/#propdef-float
#[repr(u8)]
pub enum Float {
Left,
Right,
@@ -1396,12 +1410,33 @@ pub enum Float {
InlineEnd,
}
impl Float {
/// Returns true if `self` is not `None`.
pub fn is_floating(self) -> bool {
self != Self::None
}
}
/// https://drafts.csswg.org/css2/#propdef-clear
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
Clone,
Copy,
Debug,
Eq,
FromPrimitive,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
/// https://drafts.csswg.org/css2/#propdef-clear
#[repr(u8)]
pub enum Clear {
None,
Left,

View File

@@ -1,7 +0,0 @@
[clear-computed.html]
[Property clear value 'inline-start']
expected: FAIL
[Property clear value 'inline-end']
expected: FAIL

View File

@@ -1,7 +0,0 @@
[float-computed.html]
[Property float value 'inline-start']
expected: FAIL
[Property float value 'inline-end']
expected: FAIL

View File

@@ -1,3 +0,0 @@
[float-valid.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]

View File

@@ -1,2 +0,0 @@
[logical-values-float-clear-reftest.html]
expected: FAIL

View File

@@ -1,14 +0,0 @@
[logical-values-float-clear.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test that 'clear: inline-start' is supported.]
expected: FAIL
[Test that 'clear: inline-end' is supported.]
expected: FAIL
[Test that 'float: inline-start' is supported.]
expected: FAIL
[Test that 'float: inline-end' is supported.]
expected: FAIL