diff options
Diffstat (limited to 'layout/generic')
75 files changed, 1780 insertions, 2007 deletions
diff --git a/layout/generic/AspectRatio.cpp b/layout/generic/AspectRatio.cpp index 2fe51fed5e..0a8ef181e4 100644 --- a/layout/generic/AspectRatio.cpp +++ b/layout/generic/AspectRatio.cpp @@ -20,7 +20,7 @@ nscoord AspectRatio::ComputeRatioDependentSize( const LogicalSize& boxSizingAdjust = mUseBoxSizing == UseBoxSizing::No ? LogicalSize(aWM) : aContentBoxSizeToBoxSizingAdjust; - return aRatioDependentAxis == LogicalAxis::eLogicalAxisInline + return aRatioDependentAxis == LogicalAxis::Inline ? ConvertToWritingMode(aWM).ApplyTo(aRatioDeterminingSize + boxSizingAdjust.BSize(aWM)) - boxSizingAdjust.ISize(aWM) diff --git a/layout/generic/AspectRatio.h b/layout/generic/AspectRatio.h index 6f48a07da3..daafd06ba8 100644 --- a/layout/generic/AspectRatio.h +++ b/layout/generic/AspectRatio.h @@ -22,7 +22,7 @@ struct ParamTraits; namespace mozilla { -enum LogicalAxis : uint8_t; +enum class LogicalAxis : uint8_t; class LogicalSize; class WritingMode; diff --git a/layout/generic/BRFrame.cpp b/layout/generic/BRFrame.cpp index 52cc3a0b46..13b3fbb9a4 100644 --- a/layout/generic/BRFrame.cpp +++ b/layout/generic/BRFrame.cpp @@ -98,7 +98,6 @@ void BRFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, const ReflowInput& aReflowInput, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("BRFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); WritingMode wm = aReflowInput.GetWritingMode(); @@ -186,18 +185,10 @@ void BRFrame::AddInlinePrefISize(gfxContext* aRenderingContext, } /* virtual */ -nscoord BRFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result = 0; - DISPLAY_MIN_INLINE_SIZE(this, result); - return result; -} +nscoord BRFrame::GetMinISize(gfxContext* aRenderingContext) { return 0; } /* virtual */ -nscoord BRFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result = 0; - DISPLAY_PREF_INLINE_SIZE(this, result); - return result; -} +nscoord BRFrame::GetPrefISize(gfxContext* aRenderingContext) { return 0; } Maybe<nscoord> BRFrame::GetNaturalBaselineBOffset( WritingMode aWM, BaselineSharingGroup aBaselineGroup, diff --git a/layout/generic/CSSAlignUtils.cpp b/layout/generic/CSSAlignUtils.cpp index b88ec8bfa4..7dd8999563 100644 --- a/layout/generic/CSSAlignUtils.cpp +++ b/layout/generic/CSSAlignUtils.cpp @@ -68,10 +68,10 @@ nscoord CSSAlignUtils::AlignJustifySelf(const StyleAlignFlags& aAlignment, // (Note: ReflowInput will have treated "auto" margins as 0, so we // don't need to do anything special to avoid expanding them.) hasAutoMarginStart = hasAutoMarginEnd = false; - } else if (aAxis == eLogicalAxisBlock) { + } else if (aAxis == LogicalAxis::Block) { hasAutoMarginStart = styleMargin.GetBStart(wm).IsAuto(); hasAutoMarginEnd = styleMargin.GetBEnd(wm).IsAuto(); - } else { /* aAxis == eLogicalAxisInline */ + } else { /* aAxis == LogicalAxis::Inline */ hasAutoMarginStart = styleMargin.GetIStart(wm).IsAuto(); hasAutoMarginEnd = styleMargin.GetIEnd(wm).IsAuto(); } diff --git a/layout/generic/ColumnSetWrapperFrame.cpp b/layout/generic/ColumnSetWrapperFrame.cpp index 7717f14df8..9f22222925 100644 --- a/layout/generic/ColumnSetWrapperFrame.cpp +++ b/layout/generic/ColumnSetWrapperFrame.cpp @@ -151,7 +151,6 @@ void ColumnSetWrapperFrame::MarkIntrinsicISizesDirty() { nscoord ColumnSetWrapperFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord iSize = 0; - DISPLAY_MIN_INLINE_SIZE(this, iSize); if (Maybe<nscoord> containISize = ContainIntrinsicISize(NS_UNCONSTRAINEDSIZE)) { @@ -193,7 +192,6 @@ nscoord ColumnSetWrapperFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord ColumnSetWrapperFrame::GetPrefISize(gfxContext* aRenderingContext) { nscoord iSize = 0; - DISPLAY_PREF_INLINE_SIZE(this, iSize); if (Maybe<nscoord> containISize = ContainIntrinsicISize(NS_UNCONSTRAINEDSIZE)) { diff --git a/layout/generic/MiddleCroppingBlockFrame.cpp b/layout/generic/MiddleCroppingBlockFrame.cpp index 4cbbb684aa..75dc205a4f 100644 --- a/layout/generic/MiddleCroppingBlockFrame.cpp +++ b/layout/generic/MiddleCroppingBlockFrame.cpp @@ -57,18 +57,11 @@ void MiddleCroppingBlockFrame::UpdateDisplayedValueToUncroppedValue( } nscoord MiddleCroppingBlockFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_MIN_INLINE_SIZE(this, result); - // Our min inline size is our pref inline size - result = GetPrefISize(aRenderingContext); - return result; + return GetPrefISize(aRenderingContext); } nscoord MiddleCroppingBlockFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_PREF_INLINE_SIZE(this, result); - nsAutoString prevValue; bool restoreOldValue = false; @@ -79,7 +72,7 @@ nscoord MiddleCroppingBlockFrame::GetPrefISize(gfxContext* aRenderingContext) { UpdateDisplayedValueToUncroppedValue(false); } - result = nsBlockFrame::GetPrefISize(aRenderingContext); + nscoord result = nsBlockFrame::GetPrefISize(aRenderingContext); if (restoreOldValue) { UpdateDisplayedValue(prevValue, /* aIsCropped = */ true, false); diff --git a/layout/generic/PrintedSheetFrame.cpp b/layout/generic/PrintedSheetFrame.cpp index 5b8151bbd0..384e63e361 100644 --- a/layout/generic/PrintedSheetFrame.cpp +++ b/layout/generic/PrintedSheetFrame.cpp @@ -86,7 +86,6 @@ void PrintedSheetFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("PrintedSheetFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); // If we have a prev-in-flow, take its overflowing content: diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index ed7dbd2656..c642c77b2c 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -13,10 +13,8 @@ #include "CounterStyleManager.h" #include "LayoutLogging.h" #include "mozilla/dom/HTMLInputElement.h" -#include "mozilla/StaticPrefs_layout.h" #include "mozilla/WritingModes.h" #include "nsBlockFrame.h" -#include "nsCSSAnonBoxes.h" #include "nsFlexContainerFrame.h" #include "nsFontInflationData.h" #include "nsFontMetrics.h" @@ -31,7 +29,6 @@ #include "nsLineBox.h" #include "nsPresContext.h" #include "nsStyleConsts.h" -#include "nsTableCellFrame.h" #include "nsTableFrame.h" #include "StickyScrollContainer.h" @@ -1238,11 +1235,11 @@ static bool AxisPolarityFlipped(LogicalAxis aThisAxis, WritingMode aThisWm, } static bool InlinePolarityFlipped(WritingMode aThisWm, WritingMode aOtherWm) { - return AxisPolarityFlipped(eLogicalAxisInline, aThisWm, aOtherWm); + return AxisPolarityFlipped(LogicalAxis::Inline, aThisWm, aOtherWm); } static bool BlockPolarityFlipped(WritingMode aThisWm, WritingMode aOtherWm) { - return AxisPolarityFlipped(eLogicalAxisBlock, aThisWm, aOtherWm); + return AxisPolarityFlipped(LogicalAxis::Block, aThisWm, aOtherWm); } // Calculate the position of the hypothetical box that the element would have @@ -1292,7 +1289,6 @@ void ReflowInput::CalculateHypotheticalPosition( // For non-replaced inline-level elements the 'inline size' property // doesn't apply, so we don't know what the inline size would have // been without reflowing it - } else { // It's either a replaced inline-level element or a block-level element @@ -1301,17 +1297,17 @@ void ReflowInput::CalculateHypotheticalPosition( // been in the flow. Note that we ignore any 'auto' and 'inherit' // values nscoord insideBoxISizing, outsideBoxISizing; - CalculateBorderPaddingMargin(eLogicalAxisInline, blockContentSize.ISize(wm), - &insideBoxISizing, &outsideBoxISizing); + CalculateBorderPaddingMargin(LogicalAxis::Inline, + blockContentSize.ISize(wm), &insideBoxISizing, + &outsideBoxISizing); if (mFlags.mIsReplaced && isAutoISize) { - // It's a replaced element with an 'auto' inline size so the box - // inline size is its intrinsic size plus any border/padding/margin + // It's a replaced element with an 'auto' inline size so the box inline + // size is its intrinsic size plus any border/padding/margin if (intrinsicSize) { boxISize.emplace(LogicalSize(wm, *intrinsicSize).ISize(wm) + outsideBoxISizing + insideBoxISizing); } - } else if (isAutoISize) { // The box inline size is the containing block inline size boxISize.emplace(blockContentSize.ISize(wm)); @@ -1320,7 +1316,7 @@ void ReflowInput::CalculateHypotheticalPosition( // percentage based this computed value may be different from the computed // value calculated using the absolute containing block width nscoord insideBoxBSizing, dummy; - CalculateBorderPaddingMargin(eLogicalAxisBlock, + CalculateBorderPaddingMargin(LogicalAxis::Block, blockContentSize.ISize(wm), &insideBoxBSizing, &dummy); boxISize.emplace( @@ -1500,7 +1496,7 @@ void ReflowInput::CalculateHypotheticalPosition( // been in the flow. Note that we ignore any 'auto' and 'inherit' // values. nscoord insideBoxSizing, outsideBoxSizing; - CalculateBorderPaddingMargin(eLogicalAxisBlock, blockContentSize.BSize(wm), + CalculateBorderPaddingMargin(LogicalAxis::Block, blockContentSize.BSize(wm), &insideBoxSizing, &outsideBoxSizing); nscoord boxBSize; @@ -1627,7 +1623,7 @@ LogicalSize ReflowInput::CalculateAbsoluteSizeWithResolvedAutoBlockSize( : LogicalSize(wm); auto transferredISize = mStylePosition->mAspectRatio.ToLayoutRatio().ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, wm, aAutoBSize, boxSizingAdjust); + LogicalAxis::Inline, wm, aAutoBSize, boxSizingAdjust); resultSize.ISize(wm) = ApplyMinMaxISize(transferredISize); MOZ_ASSERT(mFlags.mIsBSizeSetByAspectRatio, @@ -2167,8 +2163,6 @@ void ReflowInput::InitConstraints( WritingMode wm = GetWritingMode(); LogicalSize cbSize = aContainingBlockSize.valueOr( LogicalSize(mWritingMode, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)); - DISPLAY_INIT_CONSTRAINTS(mFrame, this, cbSize.ISize(wm), cbSize.BSize(wm), - aBorder, aPadding); // If this is a reflow root, then set the computed width and // height equal to the available space @@ -2239,7 +2233,7 @@ void ReflowInput::InitConstraints( // eStyleUnit_Auto;" used to be called exclusively. if (mFlags.mIsReplaced && mStyleDisplay->IsInlineOutsideStyle()) { // Get the containing block's reflow input - NS_ASSERTION(nullptr != cbri, "no containing block"); + NS_ASSERTION(cbri, "no containing block"); // in quirks mode, get the cb height using the special quirk method if (!wm.IsVertical() && eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) { @@ -2359,46 +2353,79 @@ void ReflowInput::InitConstraints( } else { AutoMaybeDisableFontInflation an(mFrame); - const bool isBlockLevel = - ((!mStyleDisplay->IsInlineOutsideStyle() && - // internal table values on replaced elements behaves as inline - // https://drafts.csswg.org/css-tables-3/#table-structure - // "... it is handled instead as though the author had declared - // either 'block' (for 'table' display) or 'inline' (for all - // other values)" - !(mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() || - mStyleDisplay->DisplayOutside() == - StyleDisplayOutside::TableCaption))) || - // The inner table frame always fills its outer wrapper table frame, - // even for 'inline-table'. - mFrame->IsTableFrame()) && - // XXX abs.pos. continuations treated like blocks, see comment in - // the else-if condition above. - (!mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) || - mStyleDisplay->IsAbsolutelyPositionedStyle()); - - if (!isBlockLevel) { - mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; - } + nsIFrame* const alignCB = [&] { + nsIFrame* cb = mFrame->GetParent(); + if (cb->IsTableWrapperFrame()) { + nsIFrame* alignCBParent = cb->GetParent(); + if (alignCBParent && alignCBParent->IsGridContainerFrame()) { + return alignCBParent; + } + } + return cb; + }(); - nsIFrame* alignCB = mFrame->GetParent(); - if (alignCB->IsTableWrapperFrame()) { - nsIFrame* alignCBParent = alignCB->GetParent(); - if (alignCBParent && alignCBParent->IsGridContainerFrame()) { - alignCB = alignCBParent; + const bool isInlineLevel = [&] { + if (mFrame->IsTableFrame()) { + // An inner table frame is not inline-level, even if it happens to + // have 'display:inline-table'. (That makes its table-wrapper frame be + // inline-level, but not the inner table frame) + return false; } - } - if (!alignCB->IsGridContainerFrame()) { - // Shrink-wrap blocks that are orthogonal to their container. - if (isBlockLevel && mCBReflowInput && + if (mStyleDisplay->IsInlineOutsideStyle()) { + return true; + } + if (mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() || + mStyleDisplay->DisplayOutside() == + StyleDisplayOutside::TableCaption)) { + // Internal table values on replaced elements behave as inline + // https://drafts.csswg.org/css-tables-3/#table-structure + // + // ... it is handled instead as though the author had declared + // either 'block' (for 'table' display) or 'inline' (for all + // other values)" + // + // FIXME(emilio): The only test that covers this is + // table-anonymous-objects-211.xht, which fails on other browsers (but + // differently to us, if you just remove this condition). + return true; + } + if (mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && + !mStyleDisplay->IsAbsolutelyPositionedStyle()) { + // Floats are treated as inline-level and also shrink-wrap. + return true; + } + return false; + }(); + + const bool shouldShrinkWrap = [&] { + if (isInlineLevel) { + return true; + } + if (mFlags.mIsReplaced && !alignCB->IsFlexOrGridContainer()) { + // Shrink-wrap replaced elements when in-flow (out of flows are + // handled above). We exclude replaced elements in grid or flex + // contexts, where we don't want to shrink-wrap unconditionally (so + // that stretching can happen). When grid/flex explicitly want + // shrink-wrapping, they can request it directly using the relevant + // flag. + return true; + } + if (!alignCB->IsGridContainerFrame() && mCBReflowInput && mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) { - mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; + // Shrink-wrap blocks that are orthogonal to their container (unless + // we're in a grid?) + return true; } + return false; + }(); + + if (shouldShrinkWrap) { + mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap; } if (cbSize.ISize(wm) == NS_UNCONSTRAINEDSIZE) { - // For orthogonal flows, where we found a parent orthogonal-limit - // for AvailableISize() in Init(), we'll use the same here as well. + // For orthogonal flows, where we found a parent orthogonal-limit for + // AvailableISize() in Init(), we'll use the same here as well. cbSize.ISize(wm) = AvailableISize(); } @@ -2418,10 +2445,7 @@ void ReflowInput::InitConstraints( size.mAspectRatioUsage == nsIFrame::AspectRatioUsage::ToComputeBSize; const bool shouldCalculateBlockSideMargins = [&]() { - if (!isBlockLevel) { - return false; - } - if (mStyleDisplay->mDisplay == StyleDisplay::InlineTable) { + if (isInlineLevel) { return false; } if (mFrame->IsTableFrame()) { @@ -2475,7 +2499,6 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, const Maybe<LogicalMargin>& aBorder, const Maybe<LogicalMargin>& aPadding, const nsStyleDisplay* aDisplay) { - DISPLAY_INIT_OFFSETS(mFrame, this, aPercentBasis, aCBWM, aBorder, aPadding); nsPresContext* presContext = mFrame->PresContext(); // Compute margins from the specified margin style information. These @@ -2533,7 +2556,7 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, } mComputedPadding.Side(side, wm) += val; needPaddingProp = true; - if (aAxis == eLogicalAxisBlock && val > 0) { + if (aAxis == LogicalAxis::Block && val > 0) { // We have a baseline-adjusted block-axis start padding, so // we need this to mark lines dirty when mIsBResize is true: this->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE); @@ -2541,10 +2564,10 @@ void SizeComputationInput::InitOffsets(WritingMode aCBWM, nscoord aPercentBasis, } }; if (!aFlags.contains(ComputeSizeFlag::IsGridMeasuringReflow)) { - ApplyBaselinePadding(eLogicalAxisBlock, nsIFrame::BBaselinePadProperty()); + ApplyBaselinePadding(LogicalAxis::Block, nsIFrame::BBaselinePadProperty()); } if (!aFlags.contains(ComputeSizeFlag::ShrinkWrap)) { - ApplyBaselinePadding(eLogicalAxisInline, nsIFrame::IBaselinePadProperty()); + ApplyBaselinePadding(LogicalAxis::Inline, nsIFrame::IBaselinePadProperty()); } LogicalMargin border(wm); diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h index 620ad0f413..ba49edcaf6 100644 --- a/layout/generic/ReflowInput.h +++ b/layout/generic/ReflowInput.h @@ -178,20 +178,6 @@ struct SizeComputationInput { const mozilla::Maybe<mozilla::LogicalMargin>& aPadding = mozilla::Nothing()); -#ifdef DEBUG - // Reflow trace methods. Defined in nsFrame.cpp so they have access - // to the display-reflow infrastructure. - static void* DisplayInitOffsetsEnter(nsIFrame* aFrame, - SizeComputationInput* aState, - nscoord aPercentBasis, - mozilla::WritingMode aCBWritingMode, - const nsMargin* aBorder, - const nsMargin* aPadding); - static void DisplayInitOffsetsExit(nsIFrame* aFrame, - SizeComputationInput* aState, - void* aValue); -#endif - private: /** * Computes margin values from the specified margin style information, and @@ -367,6 +353,16 @@ struct ReflowInput : public SizeComputationInput { mozilla::LogicalSize AvailableSize() const { return mAvailableSize; } mozilla::LogicalSize ComputedSize() const { return mComputedSize; } + + template <typename F> + mozilla::LogicalSize ComputedSizeWithBSizeFallback(F&& aFallback) const { + auto size = mComputedSize; + if (size.BSize(mWritingMode) == NS_UNCONSTRAINEDSIZE) { + size.BSize(mWritingMode) = ApplyMinMaxBSize(aFallback()); + } + return size; + } + mozilla::LogicalSize ComputedMinSize() const { return mComputedMinSize; } mozilla::LogicalSize ComputedMaxSize() const { return mComputedMaxSize; } @@ -888,21 +884,6 @@ struct ReflowInput : public SizeComputationInput { LogicalMargin& aMargin, LogicalMargin& aOffsets); -#ifdef DEBUG - // Reflow trace methods. Defined in nsFrame.cpp so they have access - // to the display-reflow infrastructure. - static void* DisplayInitConstraintsEnter(nsIFrame* aFrame, - ReflowInput* aState, - nscoord aCBISize, nscoord aCBBSize, - const nsMargin* aBorder, - const nsMargin* aPadding); - static void DisplayInitConstraintsExit(nsIFrame* aFrame, ReflowInput* aState, - void* aValue); - static void* DisplayInitFrameTypeEnter(nsIFrame* aFrame, ReflowInput* aState); - static void DisplayInitFrameTypeExit(nsIFrame* aFrame, ReflowInput* aState, - void* aValue); -#endif - protected: void InitCBReflowInput(); void InitResizeFlags(nsPresContext* aPresContext, diff --git a/layout/generic/ScrollGeneration.h b/layout/generic/ScrollGeneration.h index 90eb243e9e..5f14844e33 100644 --- a/layout/generic/ScrollGeneration.h +++ b/layout/generic/ScrollGeneration.h @@ -7,6 +7,7 @@ #include <cstdint> #include <iosfwd> +#include <tuple> namespace mozilla { @@ -23,7 +24,7 @@ std::ostream& operator<<(std::ostream& aStream, const ScrollGeneration<Tag>& aGen); template <typename Tag> -struct ScrollGeneration { +struct ScrollGeneration final { friend struct ScrollGenerationCounter; private: @@ -43,6 +44,8 @@ struct ScrollGeneration { friend std::ostream& operator<< <>(std::ostream& aStream, const ScrollGeneration<Tag>& aGen); + auto MutTiedFields() { return std::tie(mValue); } + private: uint64_t mValue; }; diff --git a/layout/generic/ScrollSnapTargetId.h b/layout/generic/ScrollSnapTargetId.h index f53e736fa1..a4a281f5e7 100644 --- a/layout/generic/ScrollSnapTargetId.h +++ b/layout/generic/ScrollSnapTargetId.h @@ -17,6 +17,7 @@ namespace mozilla { enum class ScrollSnapTargetId : uintptr_t { None = 0, }; +inline constexpr bool IsEnumCase(ScrollSnapTargetId) { return true; } struct ScrollSnapTargetIds { CopyableTArray<ScrollSnapTargetId> mIdsOnX; diff --git a/layout/generic/ViewportFrame.cpp b/layout/generic/ViewportFrame.cpp index 812aaa8e33..d71842d013 100644 --- a/layout/generic/ViewportFrame.cpp +++ b/layout/generic/ViewportFrame.cpp @@ -271,26 +271,16 @@ void ViewportFrame::RemoveFrame(DestroyContext& aContext, ChildListID aListID, /* virtual */ nscoord ViewportFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_MIN_INLINE_SIZE(this, result); - if (mFrames.IsEmpty()) - result = 0; - else - result = mFrames.FirstChild()->GetMinISize(aRenderingContext); - - return result; + return mFrames.IsEmpty() + ? 0 + : mFrames.FirstChild()->GetMinISize(aRenderingContext); } /* virtual */ nscoord ViewportFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_PREF_INLINE_SIZE(this, result); - if (mFrames.IsEmpty()) - result = 0; - else - result = mFrames.FirstChild()->GetPrefISize(aRenderingContext); - - return result; + return mFrames.IsEmpty() + ? 0 + : mFrames.FirstChild()->GetPrefISize(aRenderingContext); } nsPoint ViewportFrame::AdjustReflowInputForScrollbars( @@ -330,7 +320,6 @@ void ViewportFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("ViewportFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow"); diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index e84c5e276d..0fcf47f1d0 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -46,20 +46,22 @@ struct IMENotification; } // namespace widget // Logical axis, edge, side and corner constants for use in various places. -enum LogicalAxis : uint8_t { - eLogicalAxisBlock = 0x0, - eLogicalAxisInline = 0x1 +enum class LogicalAxis : uint8_t { + Block, + Inline, }; enum LogicalEdge { eLogicalEdgeStart = 0x0, eLogicalEdgeEnd = 0x1 }; -enum LogicalSide : uint8_t { - eLogicalSideBStart = (eLogicalAxisBlock << 1) | eLogicalEdgeStart, // 0x0 - eLogicalSideBEnd = (eLogicalAxisBlock << 1) | eLogicalEdgeEnd, // 0x1 - eLogicalSideIStart = (eLogicalAxisInline << 1) | eLogicalEdgeStart, // 0x2 - eLogicalSideIEnd = (eLogicalAxisInline << 1) | eLogicalEdgeEnd // 0x3 + +enum class LogicalSide : uint8_t { + BStart, + BEnd, + IStart, + IEnd, }; + constexpr auto AllLogicalSides() { - return mozilla::MakeInclusiveEnumeratedRange(eLogicalSideBStart, - eLogicalSideIEnd); + return mozilla::MakeInclusiveEnumeratedRange(LogicalSide::BStart, + LogicalSide::IEnd); } enum class LogicalCorner : uint8_t { @@ -82,16 +84,23 @@ enum class PhysicalAxes : uint8_t { MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PhysicalAxes) inline LogicalAxis GetOrthogonalAxis(LogicalAxis aAxis) { - return aAxis == eLogicalAxisBlock ? eLogicalAxisInline : eLogicalAxisBlock; + return aAxis == LogicalAxis::Block ? LogicalAxis::Inline : LogicalAxis::Block; +} + +inline bool IsInline(LogicalSide aSide) { + return (aSide == LogicalSide::IStart) || (aSide == LogicalSide::IEnd); } -inline bool IsInline(LogicalSide aSide) { return aSide & 0x2; } inline bool IsBlock(LogicalSide aSide) { return !IsInline(aSide); } -inline bool IsEnd(LogicalSide aSide) { return aSide & 0x1; } + +inline bool IsEnd(LogicalSide aSide) { + return (aSide == LogicalSide::BEnd) || (aSide == LogicalSide::IEnd); +} + inline bool IsStart(LogicalSide aSide) { return !IsEnd(aSide); } inline LogicalAxis GetAxis(LogicalSide aSide) { - return IsInline(aSide) ? eLogicalAxisInline : eLogicalAxisBlock; + return IsInline(aSide) ? LogicalAxis::Inline : LogicalAxis::Block; } inline LogicalEdge GetEdge(LogicalSide aSide) { @@ -104,7 +113,7 @@ inline LogicalEdge GetOppositeEdge(LogicalEdge aEdge) { } inline LogicalSide MakeLogicalSide(LogicalAxis aAxis, LogicalEdge aEdge) { - return LogicalSide((aAxis << 1) | aEdge); + return LogicalSide((uint8_t(aAxis) << 1) | aEdge); } inline LogicalSide GetOppositeSide(LogicalSide aSide) { @@ -113,20 +122,20 @@ inline LogicalSide GetOppositeSide(LogicalSide aSide) { enum LogicalSideBits { eLogicalSideBitsNone = 0, - eLogicalSideBitsBStart = 1 << eLogicalSideBStart, - eLogicalSideBitsBEnd = 1 << eLogicalSideBEnd, - eLogicalSideBitsIEnd = 1 << eLogicalSideIEnd, - eLogicalSideBitsIStart = 1 << eLogicalSideIStart, + eLogicalSideBitsBStart = 1 << static_cast<uint8_t>(LogicalSide::BStart), + eLogicalSideBitsBEnd = 1 << static_cast<uint8_t>(LogicalSide::BEnd), + eLogicalSideBitsIEnd = 1 << static_cast<uint8_t>(LogicalSide::IEnd), + eLogicalSideBitsIStart = 1 << static_cast<uint8_t>(LogicalSide::IStart), eLogicalSideBitsBBoth = eLogicalSideBitsBStart | eLogicalSideBitsBEnd, eLogicalSideBitsIBoth = eLogicalSideBitsIStart | eLogicalSideBitsIEnd, eLogicalSideBitsAll = eLogicalSideBitsBBoth | eLogicalSideBitsIBoth }; enum LineRelativeDir { - eLineRelativeDirOver = eLogicalSideBStart, - eLineRelativeDirUnder = eLogicalSideBEnd, - eLineRelativeDirLeft = eLogicalSideIStart, - eLineRelativeDirRight = eLogicalSideIEnd + eLineRelativeDirOver = static_cast<uint8_t>(LogicalSide::BStart), + eLineRelativeDirUnder = static_cast<uint8_t>(LogicalSide::BEnd), + eLineRelativeDirLeft = static_cast<uint8_t>(LogicalSide::IStart), + eLineRelativeDirRight = static_cast<uint8_t>(LogicalSide::IEnd) }; /** @@ -329,11 +338,12 @@ class WritingMode { static_assert(uint8_t(StyleWritingModeProperty::HorizontalTb) == 0 && uint8_t(StyleWritingModeProperty::VerticalRl) == 1 && uint8_t(StyleWritingModeProperty::VerticalLr) == 3 && - eLogicalAxisBlock == 0 && eLogicalAxisInline == 1 && - eAxisVertical == 0 && eAxisHorizontal == 1, + uint8_t(LogicalAxis::Block) == 0 && + uint8_t(LogicalAxis::Inline) == 1 && eAxisVertical == 0 && + eAxisHorizontal == 1, "unexpected writing-mode, logical axis or physical axis " "constant values"); - return mozilla::PhysicalAxis((aWritingModeValue ^ aAxis) & 0x1); + return mozilla::PhysicalAxis((aWritingModeValue ^ uint8_t(aAxis)) & 0x1); } mozilla::PhysicalAxis PhysicalAxis(LogicalAxis aAxis) const { @@ -445,38 +455,38 @@ class WritingMode { static const LogicalSide kPhysicalToLogicalSides[][4] = { // top right // bottom left - { eLogicalSideBStart, eLogicalSideIEnd, - eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb ltr - { eLogicalSideIStart, eLogicalSideBStart, - eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl ltr - { eLogicalSideBStart, eLogicalSideIStart, - eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb rtl - { eLogicalSideIEnd, eLogicalSideBStart, - eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl rtl - { eLogicalSideBEnd, eLogicalSideIStart, - eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) (inv) ltr - { eLogicalSideIStart, eLogicalSideBEnd, - eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr sw-left rtl - { eLogicalSideBEnd, eLogicalSideIEnd, - eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) (inv) rtl - { eLogicalSideIEnd, eLogicalSideBEnd, - eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr sw-left ltr - { eLogicalSideBStart, eLogicalSideIEnd, - eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb (inv) rtl - { eLogicalSideIStart, eLogicalSideBStart, - eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl sw-left rtl - { eLogicalSideBStart, eLogicalSideIStart, - eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb (inv) ltr - { eLogicalSideIEnd, eLogicalSideBStart, - eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl sw-left ltr - { eLogicalSideBEnd, eLogicalSideIEnd, - eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) ltr - { eLogicalSideIStart, eLogicalSideBEnd, - eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr ltr - { eLogicalSideBEnd, eLogicalSideIStart, - eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) rtl - { eLogicalSideIEnd, eLogicalSideBEnd, - eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr rtl + { LogicalSide::BStart, LogicalSide::IEnd, + LogicalSide::BEnd, LogicalSide::IStart }, // horizontal-tb ltr + { LogicalSide::IStart, LogicalSide::BStart, + LogicalSide::IEnd, LogicalSide::BEnd }, // vertical-rl ltr + { LogicalSide::BStart, LogicalSide::IStart, + LogicalSide::BEnd, LogicalSide::IEnd }, // horizontal-tb rtl + { LogicalSide::IEnd, LogicalSide::BStart, + LogicalSide::IStart, LogicalSide::BEnd }, // vertical-rl rtl + { LogicalSide::BEnd, LogicalSide::IStart, + LogicalSide::BStart, LogicalSide::IEnd }, // (horizontal-bt) (inv) ltr + { LogicalSide::IStart, LogicalSide::BEnd, + LogicalSide::IEnd, LogicalSide::BStart }, // vertical-lr sw-left rtl + { LogicalSide::BEnd, LogicalSide::IEnd, + LogicalSide::BStart, LogicalSide::IStart }, // (horizontal-bt) (inv) rtl + { LogicalSide::IEnd, LogicalSide::BEnd, + LogicalSide::IStart, LogicalSide::BStart }, // vertical-lr sw-left ltr + { LogicalSide::BStart, LogicalSide::IEnd, + LogicalSide::BEnd, LogicalSide::IStart }, // horizontal-tb (inv) rtl + { LogicalSide::IStart, LogicalSide::BStart, + LogicalSide::IEnd, LogicalSide::BEnd }, // vertical-rl sw-left rtl + { LogicalSide::BStart, LogicalSide::IStart, + LogicalSide::BEnd, LogicalSide::IEnd }, // horizontal-tb (inv) ltr + { LogicalSide::IEnd, LogicalSide::BStart, + LogicalSide::IStart, LogicalSide::BEnd }, // vertical-rl sw-left ltr + { LogicalSide::BEnd, LogicalSide::IEnd, + LogicalSide::BStart, LogicalSide::IStart }, // (horizontal-bt) ltr + { LogicalSide::IStart, LogicalSide::BEnd, + LogicalSide::IEnd, LogicalSide::BStart }, // vertical-lr ltr + { LogicalSide::BEnd, LogicalSide::IStart, + LogicalSide::BStart, LogicalSide::IEnd }, // (horizontal-bt) rtl + { LogicalSide::IEnd, LogicalSide::BEnd, + LogicalSide::IStart, LogicalSide::BStart }, // vertical-lr rtl }; // clang-format on @@ -732,7 +742,7 @@ class LogicalPoint { return mPoint.y; } nscoord Pos(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? I(aWM) : B(aWM); + return aAxis == LogicalAxis::Inline ? I(aWM) : B(aWM); } nscoord LineRelative(WritingMode aWritingMode, const nsSize& aContainerSize) const // line-axis @@ -761,7 +771,7 @@ class LogicalPoint { return mPoint.y; } nscoord& Pos(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? I(aWM) : B(aWM); + return aAxis == LogicalAxis::Inline ? I(aWM) : B(aWM); } /** @@ -952,7 +962,7 @@ class LogicalSize { return mSize.height; } nscoord Size(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); + return aAxis == LogicalAxis::Inline ? ISize(aWM) : BSize(aWM); } nscoord Width(WritingMode aWritingMode) const { @@ -978,7 +988,7 @@ class LogicalSize { return mSize.height; } nscoord& Size(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); + return aAxis == LogicalAxis::Inline ? ISize(aWM) : BSize(aWM); } /** @@ -1234,10 +1244,10 @@ class LogicalMargin { return mMargin.bottom; } nscoord Start(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); + return aAxis == LogicalAxis::Inline ? IStart(aWM) : BStart(aWM); } nscoord End(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); + return aAxis == LogicalAxis::Inline ? IEnd(aWM) : BEnd(aWM); } nscoord& IStart(WritingMode aWritingMode) // inline-start margin @@ -1261,10 +1271,10 @@ class LogicalMargin { return mMargin.bottom; } nscoord& Start(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); + return aAxis == LogicalAxis::Inline ? IStart(aWM) : BStart(aWM); } nscoord& End(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); + return aAxis == LogicalAxis::Inline ? IEnd(aWM) : BEnd(aWM); } nscoord IStartEnd(WritingMode aWritingMode) const // inline margins @@ -1278,18 +1288,18 @@ class LogicalMargin { return mMargin.TopBottom(); } nscoord StartEnd(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? IStartEnd(aWM) : BStartEnd(aWM); + return aAxis == LogicalAxis::Inline ? IStartEnd(aWM) : BStartEnd(aWM); } nscoord Side(LogicalSide aSide, WritingMode aWM) const { switch (aSide) { - case eLogicalSideBStart: + case LogicalSide::BStart: return BStart(aWM); - case eLogicalSideBEnd: + case LogicalSide::BEnd: return BEnd(aWM); - case eLogicalSideIStart: + case LogicalSide::IStart: return IStart(aWM); - case eLogicalSideIEnd: + case LogicalSide::IEnd: return IEnd(aWM); } @@ -1298,13 +1308,13 @@ class LogicalMargin { } nscoord& Side(LogicalSide aSide, WritingMode aWM) { switch (aSide) { - case eLogicalSideBStart: + case LogicalSide::BStart: return BStart(aWM); - case eLogicalSideBEnd: + case LogicalSide::BEnd: return BEnd(aWM); - case eLogicalSideIStart: + case LogicalSide::IStart: return IStart(aWM); - case eLogicalSideIEnd: + case LogicalSide::IEnd: return IEnd(aWM); } @@ -1646,13 +1656,13 @@ class LogicalRect { } nscoord Start(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); + return aAxis == LogicalAxis::Inline ? IStart(aWM) : BStart(aWM); } nscoord End(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); + return aAxis == LogicalAxis::Inline ? IEnd(aWM) : BEnd(aWM); } nscoord Size(LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); + return aAxis == LogicalAxis::Inline ? ISize(aWM) : BSize(aWM); } /** @@ -1680,10 +1690,10 @@ class LogicalRect { return mBSize; } nscoord& Start(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); + return aAxis == LogicalAxis::Inline ? IStart(aWM) : BStart(aWM); } nscoord& Size(LogicalAxis aAxis, WritingMode aWM) { - return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); + return aAxis == LogicalAxis::Inline ? ISize(aWM) : BSize(aWM); } /** @@ -2055,22 +2065,22 @@ const T& StyleRect<T>::Get(WritingMode aWM, LogicalSide aSide) const { template <typename T> const T& StyleRect<T>::GetIStart(WritingMode aWM) const { - return Get(aWM, eLogicalSideIStart); + return Get(aWM, LogicalSide::IStart); } template <typename T> const T& StyleRect<T>::GetBStart(WritingMode aWM) const { - return Get(aWM, eLogicalSideBStart); + return Get(aWM, LogicalSide::BStart); } template <typename T> const T& StyleRect<T>::GetIEnd(WritingMode aWM) const { - return Get(aWM, eLogicalSideIEnd); + return Get(aWM, LogicalSide::IEnd); } template <typename T> const T& StyleRect<T>::GetBEnd(WritingMode aWM) const { - return Get(aWM, eLogicalSideBEnd); + return Get(aWM, LogicalSide::BEnd); } template <typename T> @@ -2080,38 +2090,38 @@ T& StyleRect<T>::Get(WritingMode aWM, LogicalSide aSide) { template <typename T> T& StyleRect<T>::GetIStart(WritingMode aWM) { - return Get(aWM, eLogicalSideIStart); + return Get(aWM, LogicalSide::IStart); } template <typename T> T& StyleRect<T>::GetBStart(WritingMode aWM) { - return Get(aWM, eLogicalSideBStart); + return Get(aWM, LogicalSide::BStart); } template <typename T> T& StyleRect<T>::GetIEnd(WritingMode aWM) { - return Get(aWM, eLogicalSideIEnd); + return Get(aWM, LogicalSide::IEnd); } template <typename T> T& StyleRect<T>::GetBEnd(WritingMode aWM) { - return Get(aWM, eLogicalSideBEnd); + return Get(aWM, LogicalSide::BEnd); } template <typename T> const T& StyleRect<T>::Start(mozilla::LogicalAxis aAxis, mozilla::WritingMode aWM) const { - return Get(aWM, aAxis == mozilla::eLogicalAxisInline - ? mozilla::eLogicalSideIStart - : mozilla::eLogicalSideBStart); + return Get(aWM, aAxis == mozilla::LogicalAxis::Inline + ? mozilla::LogicalSide::IStart + : mozilla::LogicalSide::BStart); } template <typename T> const T& StyleRect<T>::End(mozilla::LogicalAxis aAxis, mozilla::WritingMode aWM) const { - return Get(aWM, aAxis == mozilla::eLogicalAxisInline - ? mozilla::eLogicalSideIEnd - : mozilla::eLogicalSideBEnd); + return Get(aWM, aAxis == mozilla::LogicalAxis::Inline + ? mozilla::LogicalSide::IEnd + : mozilla::LogicalSide::BEnd); } inline AspectRatio AspectRatio::ConvertToWritingMode( @@ -2147,15 +2157,15 @@ inline const mozilla::StyleMaxSize& nsStylePosition::MaxBSize( } inline const mozilla::StyleSize& nsStylePosition::Size( mozilla::LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == mozilla::eLogicalAxisInline ? ISize(aWM) : BSize(aWM); + return aAxis == mozilla::LogicalAxis::Inline ? ISize(aWM) : BSize(aWM); } inline const mozilla::StyleSize& nsStylePosition::MinSize( mozilla::LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == mozilla::eLogicalAxisInline ? MinISize(aWM) : MinBSize(aWM); + return aAxis == mozilla::LogicalAxis::Inline ? MinISize(aWM) : MinBSize(aWM); } inline const mozilla::StyleMaxSize& nsStylePosition::MaxSize( mozilla::LogicalAxis aAxis, WritingMode aWM) const { - return aAxis == mozilla::eLogicalAxisInline ? MaxISize(aWM) : MaxBSize(aWM); + return aAxis == mozilla::LogicalAxis::Inline ? MaxISize(aWM) : MaxBSize(aWM); } inline bool nsStylePosition::ISizeDependsOnContainer(WritingMode aWM) const { @@ -2205,26 +2215,26 @@ inline bool nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const { } inline bool nsStyleMargin::HasAuto(mozilla::LogicalAxis aAxis, mozilla::WritingMode aWM) const { - return aAxis == mozilla::eLogicalAxisInline ? HasInlineAxisAuto(aWM) - : HasBlockAxisAuto(aWM); + return aAxis == mozilla::LogicalAxis::Inline ? HasInlineAxisAuto(aWM) + : HasBlockAxisAuto(aWM); } inline mozilla::StyleAlignFlags nsStylePosition::UsedSelfAlignment( mozilla::LogicalAxis aAxis, const mozilla::ComputedStyle* aParent) const { - return aAxis == mozilla::eLogicalAxisBlock ? UsedAlignSelf(aParent)._0 - : UsedJustifySelf(aParent)._0; + return aAxis == mozilla::LogicalAxis::Block ? UsedAlignSelf(aParent)._0 + : UsedJustifySelf(aParent)._0; } inline mozilla::StyleContentDistribution nsStylePosition::UsedContentAlignment( mozilla::LogicalAxis aAxis) const { - return aAxis == mozilla::eLogicalAxisBlock ? mAlignContent : mJustifyContent; + return aAxis == mozilla::LogicalAxis::Block ? mAlignContent : mJustifyContent; } inline mozilla::StyleContentDistribution nsStylePosition::UsedTracksAlignment( mozilla::LogicalAxis aAxis, uint32_t aIndex) const { using T = mozilla::StyleAlignFlags; const auto& tracksAlignment = - aAxis == mozilla::eLogicalAxisBlock ? mAlignTracks : mJustifyTracks; + aAxis == mozilla::LogicalAxis::Block ? mAlignTracks : mJustifyTracks; if (MOZ_LIKELY(tracksAlignment.IsEmpty())) { // An empty array encodes the initial value, 'normal', which behaves as // 'start' for Grid containers. diff --git a/layout/generic/crashtests/1410243-1.html b/layout/generic/crashtests/1410243-1.html new file mode 100644 index 0000000000..42a005e85b --- /dev/null +++ b/layout/generic/crashtests/1410243-1.html @@ -0,0 +1,26 @@ +<!-- //DDBEGIN --> +<style> +* { margin-bottom: -1em; font-size: xx-large; } +.cl1 { Max-height: 93; column-width: 0; position: fixed; } +</style> +<script> +function eventhandler1() { +try { htmlvar0002.style.setProperty("display", "grid"); } catch(e) { } +try { svgvar0001.clientWidth; } catch(e) { } +try { htmlvar0002.style.setProperty("grid-template", "0px/0px"); } catch(e) { } +} +</script> +<details class="cl1" open="" ontoggle="eventhandler1()"> +<summary id="svgvar0001"/></summary> +<a> +<ol id="htmlvar0002"> +<keygen> +> +A +AA +A +A +A +A +<a> +<!-- //DDEND --> diff --git a/layout/generic/crashtests/1741488-1.html b/layout/generic/crashtests/1741488-1.html new file mode 100644 index 0000000000..74d7c49feb --- /dev/null +++ b/layout/generic/crashtests/1741488-1.html @@ -0,0 +1,23 @@ +<html class="reftest-wait"> +<style> +#b { + writing-mode: vertical-rl; + content: url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=); +} +</style> +<script> +let pp; +document.addEventListener("MozReftestInvalidate", () => { + a.after("1") + a.insertAdjacentHTML("afterEnd", b.outerHTML); + pp = SpecialPowers.wrap(self).printPreview(); + setTimeout(function() { + pp.close(); + document.documentElement.className = ""; + }, 400); +}) +</script> +<math> +<munder> +<mn id="a">2</mn> +<dl id="b"></dl> diff --git a/layout/generic/crashtests/1881375-1-helper.html b/layout/generic/crashtests/1881375-1-helper.html new file mode 100644 index 0000000000..5c79e4981f --- /dev/null +++ b/layout/generic/crashtests/1881375-1-helper.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<script> +// Notify our parent and reload ourselves. +function notifyAndReload() { + if (window.parent) { + window.parent.postMessage("reloaded", "*"); + } + window.location.reload(true) +} +</script> +<style> +*:nth-child(even) { + height: 16em; + list-style-image: url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=); +} +#a { + display: inline-grid; + grid-auto-flow: column dense; +} +#b { + padding-top: 8192vmax; +} +* { + align-content: center; + column-width: 1em; + float: inline-end; +} +</style> +<body onload="setTimeout(notifyAndReload, 0)"> +<picture></picture> +<iframe></iframe> +<isindex> +<svg></svg> +<samp id="a"> +<q> +<a id="b"> +</q> +<li> diff --git a/layout/generic/crashtests/1881375-1.html b/layout/generic/crashtests/1881375-1.html new file mode 100644 index 0000000000..8cef260433 --- /dev/null +++ b/layout/generic/crashtests/1881375-1.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<script> +// Loop count for the handler below. This value seems to be enough for the +// crashtest to be likely to trigger the crash. +const MAX_LOADS = 3; +let loadCount = 0; + +// Handler which gets invoked by the iframe whenever it completes a load +// (and dynamically reloads itself). This lets us allow the testcase to +// reload over and over (as seems to be required to trigger the crash), +// while also keeping the test duration reasonably bounded. +window.addEventListener( + "message", + (event) => { + if (loadCount++ == MAX_LOADS) { + // After MAX_LOADS reloads of the iframe, call ourselves done. + myIframe.remove(); + document.documentElement.className = ""; + } + } +); + +</script> +<iframe id="myIframe" src="1881375-1-helper.html"></iframe> diff --git a/layout/generic/crashtests/481921.ogg b/layout/generic/crashtests/481921.ogg Binary files differdeleted file mode 100644 index 0c41c3cd6b..0000000000 --- a/layout/generic/crashtests/481921.ogg +++ /dev/null diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index 1c184739d7..2aea090a6f 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -678,6 +678,7 @@ load 1405443.html load 1405813.html load 1405896.html load 1406252-1.html +asserts(2) load 1410243-1.html # assertion is bug 574889 load 1415185.html load 1416544.html load 1427824.html @@ -804,6 +805,7 @@ load 1728319.html asserts(2-8) load 1730506.html # asserts from integer overflow & bogus sizes asserts(1-4) load 1730570.html # asserts from integer overflow & bogus sizes load 1734015.html +skip-if(Android) load 1741488-1.html # printPreview doesn't work on android load 1776079.html asserts(0-2) load 1791606.html load 1799749.html @@ -812,3 +814,4 @@ load 1816574.html load 1821603.html load 1822118.html load 1825434.html +asserts(0-85) load 1881375-1.html # bug 1890687 - assertions about fragmentation invariants, failing many times because the test runs in a loop diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 3cfe7b5b2d..4f561688bf 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -522,7 +522,7 @@ static nscoord OffsetToAlignedStaticPos(const ReflowInput& aKidReflowInput, return 0; // (leave the child at the start of its alignment container) } - nscoord alignAreaSizeInAxis = (pcAxis == eLogicalAxisInline) + nscoord alignAreaSizeInAxis = (pcAxis == LogicalAxis::Inline) ? alignAreaSize.ISize(pcWM) : alignAreaSize.BSize(pcWM); @@ -619,7 +619,7 @@ void nsAbsoluteContainingBlock::ResolveSizeDependentOffsets( placeholderContainer = GetPlaceholderContainer(aKidReflowInput.mFrame); nscoord offset = OffsetToAlignedStaticPos( aKidReflowInput, aKidSize, logicalCBSizeOuterWM, placeholderContainer, - outerWM, eLogicalAxisInline); + outerWM, LogicalAxis::Inline); // Shift IStart from its current position (at start corner of the // alignment container) by the returned offset. And set IEnd to the // distance between the kid's end edge to containing block's end edge. @@ -639,7 +639,7 @@ void nsAbsoluteContainingBlock::ResolveSizeDependentOffsets( } nscoord offset = OffsetToAlignedStaticPos( aKidReflowInput, aKidSize, logicalCBSizeOuterWM, placeholderContainer, - outerWM, eLogicalAxisBlock); + outerWM, LogicalAxis::Block); // Shift BStart from its current position (at start corner of the // alignment container) by the returned offset. And set BEnd to the // distance between the kid's end edge to containing block's end edge. diff --git a/layout/generic/nsBackdropFrame.cpp b/layout/generic/nsBackdropFrame.cpp index 20d3fcd368..178caa3e0c 100644 --- a/layout/generic/nsBackdropFrame.cpp +++ b/layout/generic/nsBackdropFrame.cpp @@ -70,7 +70,6 @@ void nsBackdropFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsBackdropFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); // Note that this frame is a child of the viewport frame. diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a25e4e996e..4582c29e0b 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -813,8 +813,6 @@ nscoord nsBlockFrame::GetMinISize(gfxContext* aRenderingContext) { return firstInFlow->GetMinISize(aRenderingContext); } - DISPLAY_MIN_INLINE_SIZE(this, mCachedMinISize); - CheckIntrinsicCacheAgainstShrinkWrapState(); if (mCachedMinISize != NS_INTRINSIC_ISIZE_UNKNOWN) { @@ -902,8 +900,6 @@ nscoord nsBlockFrame::GetPrefISize(gfxContext* aRenderingContext) { return firstInFlow->GetPrefISize(aRenderingContext); } - DISPLAY_PREF_INLINE_SIZE(this, mCachedPrefISize); - CheckIntrinsicCacheAgainstShrinkWrapState(); if (mCachedPrefISize != NS_INTRINSIC_ISIZE_UNKNOWN) { @@ -1348,7 +1344,6 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsBlockFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); #ifdef DEBUG @@ -1453,14 +1448,18 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, // maintain when doing text-wrap: balance. struct BalanceTarget { // If line-clamp is in effect, mContent and mOffset indicate the starting - // position of the first line after the clamp limit. If line-clamp is not - // in use, mContent is null and mOffset is the total number of lines that - // the block must contain. + // position of the first line after the clamp limit, and mBlockCoord is the + // block-axis offset of its position. + // If line-clamp is not in use, mContent is null, mOffset is the total + // number of lines that the block must contain, and mBlockCoord is its end + // edge in the block direction. nsIContent* mContent = nullptr; int32_t mOffset = -1; + nscoord mBlockCoord = 0; bool operator==(const BalanceTarget& aOther) const { - return mContent == aOther.mContent && mOffset == aOther.mOffset; + return mContent == aOther.mContent && mOffset == aOther.mOffset && + mBlockCoord == aOther.mBlockCoord; } bool operator!=(const BalanceTarget& aOther) const { return !(*this == aOther); @@ -1506,7 +1505,7 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, auto* textFrame = static_cast<nsTextFrame*>(firstChild); offset = textFrame->GetContentOffset(); } - return BalanceTarget{content, offset}; + return BalanceTarget{content, offset, iter.get()->BStart()}; }; // "balancing" is implemented by shortening the effective inline-size of the @@ -1545,6 +1544,7 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, // no balancing is needed; just break from the balance loop. break; } + balanceTarget.mBlockCoord = mLines.back()->BEnd(); // Initialize the amount of inset to try, and the iteration step size. balanceStep = aReflowInput.ComputedISize() / balanceTarget.mOffset; trialState.ResetForBalance(balanceStep); @@ -1581,7 +1581,8 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, } int32_t numLines = countLinesUpTo(StaticPrefs::layout_css_text_wrap_balance_limit()); - return numLines == balanceTarget.mOffset; + return numLines == balanceTarget.mOffset && + mLines.back()->BEnd() == balanceTarget.mBlockCoord; }; // If we're in the process of a balance operation, check whether we've @@ -2817,7 +2818,7 @@ void nsBlockFrame::PropagateFloatDamage(BlockReflowState& aState, static bool LineHasClear(nsLineBox* aLine) { return aLine->IsBlock() - ? (aLine->HasForcedLineBreakBefore() || + ? (aLine->HasFloatClearTypeBefore() || aLine->mFirstChild->HasAnyStateBits( NS_BLOCK_HAS_CLEAR_CHILDREN) || !nsBlockFrame::BlockCanIntersectFloats(aLine->mFirstChild)) @@ -2984,7 +2985,7 @@ bool nsBlockFrame::ReflowDirtyLines(BlockReflowState& aState) { // We have to reflow the line if it's a block whose clearance // might have changed, so detect that. if (!line->IsDirty() && - (line->HasForcedLineBreakBefore() || floatAvoidingBlock)) { + (line->HasFloatClearTypeBefore() || floatAvoidingBlock)) { nscoord curBCoord = aState.mBCoord; // See where we would be after applying any clearance due to // BRs. @@ -3934,9 +3935,9 @@ bool nsBlockFrame::IsSelfEmpty() { const nsStyleBorder* border = StyleBorder(); const nsStylePadding* padding = StylePadding(); - if (border->GetComputedBorderWidth(wm.PhysicalSide(eLogicalSideBStart)) != + if (border->GetComputedBorderWidth(wm.PhysicalSide(LogicalSide::BStart)) != 0 || - border->GetComputedBorderWidth(wm.PhysicalSide(eLogicalSideBEnd)) != 0 || + border->GetComputedBorderWidth(wm.PhysicalSide(LogicalSide::BEnd)) != 0 || !nsLayoutUtils::IsPaddingZero(padding->mPadding.GetBStart(wm)) || !nsLayoutUtils::IsPaddingZero(padding->mPadding.GetBEnd(wm))) { return false; @@ -4051,7 +4052,7 @@ void nsBlockFrame::ReflowBlockFrame(BlockReflowState& aState, // Clear past floats before the block if the clear style is not none aLine->ClearForcedLineBreak(); if (clearType != StyleClear::None) { - aLine->SetForcedLineBreakBefore(clearType); + aLine->SetFloatClearTypeBefore(clearType); } // See if we should apply the block-start margin. If the block frame being diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 64c56b1c00..b4b108905f 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -606,24 +606,16 @@ void nsCanvasFrame::PaintFocus(DrawTarget* aDrawTarget, nsPoint aPt) { /* virtual */ nscoord nsCanvasFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_MIN_INLINE_SIZE(this, result); - if (mFrames.IsEmpty()) - result = 0; - else - result = mFrames.FirstChild()->GetMinISize(aRenderingContext); - return result; + return mFrames.IsEmpty() + ? 0 + : mFrames.FirstChild()->GetMinISize(aRenderingContext); } /* virtual */ nscoord nsCanvasFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_PREF_INLINE_SIZE(this, result); - if (mFrames.IsEmpty()) - result = 0; - else - result = mFrames.FirstChild()->GetPrefISize(aRenderingContext); - return result; + return mFrames.IsEmpty() + ? 0 + : mFrames.FirstChild()->GetPrefISize(aRenderingContext); } void nsCanvasFrame::Reflow(nsPresContext* aPresContext, @@ -632,7 +624,6 @@ void nsCanvasFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow"); diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index cd97519a98..a9d3e28138 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -408,7 +408,6 @@ static void MoveChildTo(nsIFrame* aChild, LogicalPoint aOrigin, WritingMode aWM, nscoord nsColumnSetFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord iSize = 0; - DISPLAY_MIN_INLINE_SIZE(this, iSize); if (mFrames.FirstChild()) { // We want to ignore this in the case that we're size contained @@ -443,8 +442,6 @@ nscoord nsColumnSetFrame::GetPrefISize(gfxContext* aRenderingContext) { // the child's preferred width, times the number of columns, plus the width // of any required column gaps // XXX what about forced column breaks here? - nscoord result = 0; - DISPLAY_PREF_INLINE_SIZE(this, result); const nsStyleColumn* colStyle = StyleColumn(); nscoord colISize; @@ -466,8 +463,7 @@ nscoord nsColumnSetFrame::GetPrefISize(gfxContext* aRenderingContext) { ? 1 : colStyle->mColumnCount; nscoord colGap = ColumnUtils::GetColumnGap(this, NS_UNCONSTRAINEDSIZE); - result = ColumnUtils::IntrinsicISize(numColumns, colGap, colISize); - return result; + return ColumnUtils::IntrinsicISize(numColumns, colGap, colISize); } nsColumnSetFrame::ColumnBalanceData nsColumnSetFrame::ReflowColumns( @@ -1202,7 +1198,6 @@ void nsColumnSetFrame::Reflow(nsPresContext* aPresContext, nsPresContext::InterruptPreventer noInterrupts(aPresContext); DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); MOZ_ASSERT(aReflowInput.mCBReflowInput->mFrame->StyleColumn() diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 2577a7a00d..2c9e707830 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -814,8 +814,7 @@ LogicalSize nsContainerFrame::ComputeAutoSize( LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE); nscoord availBased = aAvailableISize - aMargin.ISize(aWM) - aBorderPadding.ISize(aWM); - // replaced elements always shrink-wrap - if (aFlags.contains(ComputeSizeFlag::ShrinkWrap) || IsReplaced()) { + if (aFlags.contains(ComputeSizeFlag::ShrinkWrap)) { // Only bother computing our 'auto' ISize if the result will be used. const auto& styleISize = aSizeOverrides.mStyleISize ? *aSizeOverrides.mStyleISize @@ -2201,9 +2200,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( // This variable only gets meaningfully set if isFlexItem is true. It // indicates which axis (in this frame's own WM) corresponds to its // flex container's main axis. - LogicalAxis flexMainAxis = eLogicalAxisBlock; + LogicalAxis flexMainAxis = LogicalAxis::Block; if (isFlexItem && nsFlexContainerFrame::IsItemInlineAxisMainAxis(this)) { - flexMainAxis = eLogicalAxisInline; + flexMainAxis = LogicalAxis::Inline; } // Handle intrinsic sizes and their interaction with @@ -2263,8 +2262,8 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( aSizeOverrides, aFlags) .mISize; } else if (MOZ_UNLIKELY(isGridItem) && - !parentFrame->IsMasonry(isOrthogonal ? eLogicalAxisBlock - : eLogicalAxisInline)) { + !parentFrame->IsMasonry(isOrthogonal ? LogicalAxis::Block + : LogicalAxis::Inline)) { MOZ_ASSERT(!IsTrueOverflowContainer()); // 'auto' inline-size for grid-level box - apply 'stretch' as needed: auto cbSize = aCBSize.ISize(aWM); @@ -2291,7 +2290,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& maxISizeCoord = stylePos->MaxISize(aWM); if (!maxISizeCoord.IsNone() && - !(isFlexItem && flexMainAxis == eLogicalAxisInline)) { + !(isFlexItem && flexMainAxis == LogicalAxis::Inline)) { maxISize = ComputeISizeValue(aRenderingContext, aWM, aCBSize, boxSizingAdjust, boxSizingToMarginEdgeISize, maxISizeCoord, aSizeOverrides, aFlags) @@ -2307,7 +2306,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& minISizeCoord = stylePos->MinISize(aWM); if (!minISizeCoord.IsAuto() && - !(isFlexItem && flexMainAxis == eLogicalAxisInline)) { + !(isFlexItem && flexMainAxis == LogicalAxis::Inline)) { minISize = ComputeISizeValue(aRenderingContext, aWM, aCBSize, boxSizingAdjust, boxSizingToMarginEdgeISize, minISizeCoord, aSizeOverrides, aFlags) @@ -2326,8 +2325,8 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( boxSizingAdjust.BSize(aWM), styleBSize.AsLengthPercentage()); } else if (MOZ_UNLIKELY(isGridItem) && - !parentFrame->IsMasonry(isOrthogonal ? eLogicalAxisInline - : eLogicalAxisBlock)) { + !parentFrame->IsMasonry(isOrthogonal ? LogicalAxis::Inline + : LogicalAxis::Block)) { MOZ_ASSERT(!IsTrueOverflowContainer()); // 'auto' block-size for grid-level box - apply 'stretch' as needed: auto cbSize = aCBSize.BSize(aWM); @@ -2354,7 +2353,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& maxBSizeCoord = stylePos->MaxBSize(aWM); if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) && - !(isFlexItem && flexMainAxis == eLogicalAxisBlock)) { + !(isFlexItem && flexMainAxis == LogicalAxis::Block)) { maxBSize = nsLayoutUtils::ComputeBSizeValue( aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), maxBSizeCoord.AsLengthPercentage()); @@ -2365,7 +2364,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& minBSizeCoord = stylePos->MinBSize(aWM); if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) && - !(isFlexItem && flexMainAxis == eLogicalAxisBlock)) { + !(isFlexItem && flexMainAxis == LogicalAxis::Block)) { minBSize = nsLayoutUtils::ComputeBSizeValue( aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), minBSizeCoord.AsLengthPercentage()); @@ -2389,8 +2388,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( tentISize = intrinsicISize; } else if (hasIntrinsicBSize && aspectRatio) { tentISize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, intrinsicBSize, - boxSizingAdjust); + LogicalAxis::Inline, aWM, intrinsicBSize, boxSizingAdjust); } else if (aspectRatio) { tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar? @@ -2413,7 +2411,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( tentBSize = intrinsicBSize; } else if (aspectRatio) { tentBSize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, tentISize, boxSizingAdjust); + LogicalAxis::Block, aWM, tentISize, boxSizingAdjust); } else { tentBSize = fallbackIntrinsicSize.BSize(aWM); } @@ -2431,29 +2429,29 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( } else if (stretchB == eStretchPreservingRatio && aspectRatio) { // 'normal' / 'stretch' tentBSize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust); + LogicalAxis::Block, aWM, iSize, boxSizingAdjust); } } else if (stretchB == eStretch) { tentBSize = bSize; // 'stretch' / * (except 'stretch') if (stretchI == eStretchPreservingRatio && aspectRatio) { // 'stretch' / 'normal' tentISize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); } } else if (stretchI == eStretchPreservingRatio && aspectRatio) { tentISize = iSize; // * (except 'stretch') / 'normal' tentBSize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust); + LogicalAxis::Block, aWM, iSize, boxSizingAdjust); if (stretchB == eStretchPreservingRatio && tentBSize > bSize) { // Stretch within the CB size with preserved intrinsic ratio. tentBSize = bSize; // 'normal' / 'normal' tentISize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); } } else if (stretchB == eStretchPreservingRatio && aspectRatio) { tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch') tentISize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); } // ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when @@ -2480,7 +2478,7 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( if (stretchI != eStretch) { if (aspectRatio) { iSize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); } else if (hasIntrinsicISize) { if (!(aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize) && intrinsicISize > iSize)) { @@ -2498,8 +2496,8 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( iSize = NS_CSS_MINMAX(iSize, minISize, maxISize); if (stretchB != eStretch) { if (aspectRatio) { - bSize = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, iSize, boxSizingAdjust); + bSize = aspectRatio.ComputeRatioDependentSize(LogicalAxis::Block, aWM, + iSize, boxSizingAdjust); } else if (hasIntrinsicBSize) { if (!(aFlags.contains(ComputeSizeFlag::BClampMarginBoxMinSize) && intrinsicBSize > bSize)) { diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 09f6cf76f5..cb0a09db20 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -1076,126 +1076,4 @@ class nsOverflowContinuationTracker { bool mWalkOOFFrames; }; -// Start Display Reflow Debugging -#ifdef DEBUG - -struct DR_cookie { - DR_cookie(nsPresContext* aPresContext, nsIFrame* aFrame, - const mozilla::ReflowInput& aReflowInput, - mozilla::ReflowOutput& aMetrics, nsReflowStatus& aStatus); - ~DR_cookie(); - void Change() const; - - nsPresContext* mPresContext; - nsIFrame* mFrame; - const mozilla::ReflowInput& mReflowInput; - mozilla::ReflowOutput& mMetrics; - nsReflowStatus& mStatus; - void* mValue; -}; - -struct DR_layout_cookie { - explicit DR_layout_cookie(nsIFrame* aFrame); - ~DR_layout_cookie(); - - nsIFrame* mFrame; - void* mValue; -}; - -struct DR_intrinsic_inline_size_cookie { - DR_intrinsic_inline_size_cookie(nsIFrame* aFrame, const char* aType, - nscoord& aResult); - ~DR_intrinsic_inline_size_cookie(); - - nsIFrame* mFrame; - const char* mType; - nscoord& mResult; - void* mValue; -}; - -struct DR_intrinsic_size_cookie { - DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType, - nsSize& aResult); - ~DR_intrinsic_size_cookie(); - - nsIFrame* mFrame; - const char* mType; - nsSize& mResult; - void* mValue; -}; - -struct DR_init_constraints_cookie { - DR_init_constraints_cookie( - nsIFrame* aFrame, mozilla::ReflowInput* aState, nscoord aCBWidth, - nscoord aCBHeight, const mozilla::Maybe<mozilla::LogicalMargin> aBorder, - const mozilla::Maybe<mozilla::LogicalMargin> aPadding); - ~DR_init_constraints_cookie(); - - nsIFrame* mFrame; - mozilla::ReflowInput* mState; - void* mValue; -}; - -struct DR_init_offsets_cookie { - DR_init_offsets_cookie(nsIFrame* aFrame, - mozilla::SizeComputationInput* aState, - nscoord aPercentBasis, - mozilla::WritingMode aCBWritingMode, - const mozilla::Maybe<mozilla::LogicalMargin> aBorder, - const mozilla::Maybe<mozilla::LogicalMargin> aPadding); - ~DR_init_offsets_cookie(); - - nsIFrame* mFrame; - mozilla::SizeComputationInput* mState; - void* mValue; -}; - -# define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \ - dr_rf_metrics, dr_rf_status) \ - DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, \ - dr_rf_status); -# define DISPLAY_REFLOW_CHANGE() dr_cookie.Change(); -# define DISPLAY_LAYOUT(dr_frame) DR_layout_cookie dr_cookie(dr_frame); -# define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \ - DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Min", dr_result) -# define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \ - DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Pref", dr_result) -# define DISPLAY_PREF_SIZE(dr_frame, dr_result) \ - DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result) -# define DISPLAY_MIN_SIZE(dr_frame, dr_result) \ - DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result) -# define DISPLAY_MAX_SIZE(dr_frame, dr_result) \ - DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result) -# define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \ - dr_pad) \ - DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \ - dr_bdr, dr_pad) -# define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \ - dr_pad) \ - DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm, \ - dr_bdr, dr_pad) - -#else - -# define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \ - dr_rf_metrics, dr_rf_status) -# define DISPLAY_REFLOW_CHANGE() -# define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \ - PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \ - PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \ - dr_pad) \ - PR_BEGIN_MACRO PR_END_MACRO -# define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \ - dr_pad) \ - PR_BEGIN_MACRO PR_END_MACRO - -#endif -// End Display Reflow Debugging - #endif /* nsContainerFrame_h___ */ diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index fe294652c7..28d1b08a30 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -197,7 +197,6 @@ void nsFirstLetterFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aReflowStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aReflowStatus); MOZ_ASSERT(aReflowStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index e5a719fee2..66f1e79609 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -14,14 +14,12 @@ #include "mozilla/Baseline.h" #include "mozilla/ComputedStyle.h" #include "mozilla/CSSOrderAwareFrameIterator.h" -#include "mozilla/FloatingPoint.h" #include "mozilla/Logging.h" #include "mozilla/PresShell.h" #include "mozilla/StaticPrefs_layout.h" #include "mozilla/WritingModes.h" #include "nsBlockFrame.h" #include "nsContentUtils.h" -#include "nsCSSAnonBoxes.h" #include "nsDebug.h" #include "nsDisplayList.h" #include "nsFieldSetFrame.h" @@ -43,10 +41,25 @@ using CachedBAxisMeasurement = nsFlexContainerFrame::CachedBAxisMeasurement; using CachedFlexItemData = nsFlexContainerFrame::CachedFlexItemData; static mozilla::LazyLogModule gFlexContainerLog("FlexContainer"); -#define FLEX_LOG(...) \ - MOZ_LOG(gFlexContainerLog, LogLevel::Debug, (__VA_ARGS__)); -#define FLEX_LOGV(...) \ - MOZ_LOG(gFlexContainerLog, LogLevel::Verbose, (__VA_ARGS__)); + +// FLEX_LOG is a top-level general log print. +#define FLEX_LOG(message, ...) \ + MOZ_LOG(gFlexContainerLog, LogLevel::Debug, (message, ##__VA_ARGS__)); + +// FLEX_ITEM_LOG is a top-level log print for flex item. +#define FLEX_ITEM_LOG(item_frame, message, ...) \ + MOZ_LOG(gFlexContainerLog, LogLevel::Debug, \ + ("Flex item %p: " message, item_frame, ##__VA_ARGS__)); + +// FLEX_LOGV is a verbose log print with built-in two spaces indentation. The +// convention to use FLEX_LOGV is that FLEX_LOGV statements should generally be +// preceded by one FLEX_LOG or FLEX_ITEM_LOG so that there's no need to repeat +// information presented in the preceding LOG statement. If you want extra level +// of indentation, just add two extra spaces at the start of the message string. +#define FLEX_LOGV(message, ...) \ + MOZ_LOG(gFlexContainerLog, LogLevel::Verbose, (" " message, ##__VA_ARGS__)); + +static const char* BoolToYesNo(bool aArg) { return aArg ? "yes" : "no"; } // Returns true if aFlexContainer is a frame for some element that has // display:-webkit-{inline-}box (or -moz-{inline-}box). aFlexContainer is @@ -143,10 +156,10 @@ class MOZ_STACK_CLASS nsFlexContainerFrame::FlexboxAxisTracker { // Accessors: LogicalAxis MainAxis() const { - return IsRowOriented() ? eLogicalAxisInline : eLogicalAxisBlock; + return IsRowOriented() ? LogicalAxis::Inline : LogicalAxis::Block; } LogicalAxis CrossAxis() const { - return IsRowOriented() ? eLogicalAxisBlock : eLogicalAxisInline; + return IsRowOriented() ? LogicalAxis::Block : LogicalAxis::Inline; } LogicalSide MainAxisStartSide() const; @@ -308,7 +321,7 @@ class MOZ_STACK_CLASS nsFlexContainerFrame::FlexboxAxisTracker { : StyleAlignFlags::END; } - MOZ_ASSERT(MainAxis() == eLogicalAxisInline, + MOZ_ASSERT(MainAxis() == LogicalAxis::Inline, "Row-oriented flex container's main axis should be parallel to " "line-left <-> line-right axis!"); @@ -682,9 +695,8 @@ class nsFlexContainerFrame::FlexItem final { // to the [min,max] range: mMainSize = NS_CSS_MINMAX(mFlexBaseSize, mMainMinSize, mMainMaxSize); - FLEX_LOGV( - "Set flex base size: %d, hypothetical main size: %d for flex item %p", - mFlexBaseSize, mMainSize, mFrame); + FLEX_ITEM_LOG(mFrame, "Set flex base size: %d, hypothetical main size: %d", + mFlexBaseSize, mMainSize); } // Setters used while we're resolving flexible lengths @@ -1305,7 +1317,7 @@ StyleAlignFlags nsFlexContainerFrame::CSSAlignmentForAbsPosChild( // block axis), then the caller is really asking about our *main* axis. // Otherwise, the caller is asking about our cross axis. const bool isMainAxis = - (axisTracker.IsRowOriented() == (aLogicalAxis == eLogicalAxisInline)); + (axisTracker.IsRowOriented() == (aLogicalAxis == LogicalAxis::Inline)); const nsStylePosition* containerStylePos = StylePosition(); const bool isAxisReversed = isMainAxis ? axisTracker.IsMainAxisReversed() : axisTracker.IsCrossAxisReversed(); @@ -1592,7 +1604,7 @@ static nscoord PartiallyResolveAutoMinSize( if (specifiedSizeSuggestion != nscoord_MAX) { // We have the specified size suggestion. Return it now since we don't need // to consider transferred size suggestion. - FLEX_LOGV(" Specified size suggestion: %d", specifiedSizeSuggestion); + FLEX_LOGV("Specified size suggestion: %d", specifiedSizeSuggestion); return specifiedSizeSuggestion; } @@ -1611,7 +1623,7 @@ static nscoord PartiallyResolveAutoMinSize( transferredSizeSuggestion = aFlexItem.ClampMainSizeViaCrossAxisConstraints( transferredSizeSuggestion, aItemReflowInput); - FLEX_LOGV(" Transferred size suggestion: %d", transferredSizeSuggestion); + FLEX_LOGV("Transferred size suggestion: %d", transferredSizeSuggestion); return transferredSizeSuggestion; } @@ -1638,8 +1650,10 @@ void nsFlexContainerFrame::ResolveAutoFlexBasisAndMinSize( return; } - FLEX_LOGV("Resolving auto main size or auto min main size for flex item %p", - aFlexItem.Frame()); + FLEX_ITEM_LOG( + aFlexItem.Frame(), + "Resolving auto main size? %s; resolving auto min main size? %s", + BoolToYesNo(isMainSizeAuto), BoolToYesNo(isMainMinSizeAuto)); nscoord resolvedMinSize; // (only set/used if isMainMinSizeAuto==true) bool minSizeNeedsToMeasureContent = false; // assume the best @@ -1725,7 +1739,7 @@ void nsFlexContainerFrame::ResolveAutoFlexBasisAndMinSize( contentSizeSuggestion, aItemReflowInput); } - FLEX_LOGV(" Content size suggestion: %d", contentSizeSuggestion); + FLEX_LOGV("Content size suggestion: %d", contentSizeSuggestion); resolvedMinSize = std::min(resolvedMinSize, contentSizeSuggestion); // Clamp the resolved min main size by the max main size if it's definite. @@ -1739,7 +1753,7 @@ void nsFlexContainerFrame::ResolveAutoFlexBasisAndMinSize( // nscoord_MAX sentinel value if we reach this point). resolvedMinSize = nscoord_MAX; } - FLEX_LOGV(" Resolved auto min main size: %d", resolvedMinSize); + FLEX_LOGV("Resolved auto min main size: %d", resolvedMinSize); if (resolvedMinSize == contentSizeSuggestion) { // When we are here, we've measured the item's content-based size, and @@ -1992,12 +2006,16 @@ const CachedBAxisMeasurement& nsFlexContainerFrame::MeasureBSizeForFlexItem( if (cachedData && cachedData->mBAxisMeasurement) { if (!aItem.Frame()->IsSubtreeDirty() && cachedData->mBAxisMeasurement->IsValidFor(aChildReflowInput)) { - FLEX_LOG("[perf] MeasureBSizeForFlexItem accepted cached value"); + FLEX_ITEM_LOG(aItem.Frame(), + "[perf] Accepted cached measurement: block-size %d", + cachedData->mBAxisMeasurement->BSize()); return *(cachedData->mBAxisMeasurement); } - FLEX_LOG("[perf] MeasureBSizeForFlexItem rejected cached value"); + FLEX_ITEM_LOG(aItem.Frame(), + "[perf] Rejected cached measurement: block-size %d", + cachedData->mBAxisMeasurement->BSize()); } else { - FLEX_LOG("[perf] MeasureBSizeForFlexItem didn't have a cached value"); + FLEX_ITEM_LOG(aItem.Frame(), "[perf] No cached measurement"); } // CachedFlexItemData is stored in item's writing mode, so we pass @@ -2055,7 +2073,7 @@ void nsFlexContainerFrame::MarkIntrinsicISizesDirty() { nscoord nsFlexContainerFrame::MeasureFlexItemContentBSize( FlexItem& aFlexItem, bool aForceBResizeForMeasuringReflow, const ReflowInput& aParentReflowInput) { - FLEX_LOG("Measuring flex item's content block-size"); + FLEX_ITEM_LOG(aFlexItem.Frame(), "Measuring item's content block-size"); // Set up a reflow input for measuring the flex item's content block-size: WritingMode wm = aFlexItem.Frame()->GetWritingMode(); @@ -2070,7 +2088,7 @@ nscoord nsFlexContainerFrame::MeasureFlexItemContentBSize( // block-size, because that would prevent us from measuring the content // block-size. sizeOverrides.mAspectRatio.emplace(AspectRatio()); - FLEX_LOGV(" Cross size override: %d", aFlexItem.CrossSize()); + FLEX_LOGV("Cross size override: %d", aFlexItem.CrossSize()); } sizeOverrides.mStyleBSize.emplace(StyleSize::Auto()); @@ -2234,7 +2252,7 @@ FlexItem::FlexItem(ReflowInput& aFlexItemReflowInput, float aFlexGrow, // getting the physical side that corresponds to these axes' "logical // start" sides, and we compare those physical sides to find out if // they're the same vs. opposite. - mozilla::Side itemBlockStartSide = mWM.PhysicalSide(eLogicalSideBStart); + mozilla::Side itemBlockStartSide = mWM.PhysicalSide(LogicalSide::BStart); // (Note: this is *not* the "flex-start" side; rather, it's the *logical* // i.e. WM-relative block-start or inline-start side.) @@ -2363,7 +2381,7 @@ nscoord FlexItem::BaselineOffsetFromOuterCrossEdge( "Only expecting to be doing baseline computations when the " "cross axis is the block axis"); - mozilla::Side itemBlockStartSide = mWM.PhysicalSide(eLogicalSideBStart); + mozilla::Side itemBlockStartSide = mWM.PhysicalSide(LogicalSide::BStart); nscoord marginBStartToBaseline = ResolvedAscent(aUseFirstLineBaseline) + PhysicalMargin().Side(itemBlockStartSide); @@ -2537,18 +2555,17 @@ static bool FrameHasRelativeBSizeDependency(nsIFrame* aFrame) { bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { if (!StaticPrefs::layout_flexbox_item_final_reflow_optimization_enabled()) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to optimization being " - "disabled via the preference", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed a final reflow due to optimization being " + "disabled via the preference"); return true; } // NOTE: We can have continuations from an earlier constrained reflow. if (mFrame->GetPrevInFlow() || mFrame->GetNextInFlow()) { // This is an item has continuation(s). Reflow it. - FLEX_LOG("[frag] Flex item %p needed a final reflow due to continuation(s)", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[frag] Item needed a final reflow due to continuation(s)"); return true; } @@ -2560,10 +2577,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // prevent triggering O(n^2) behavior when printing a deeply-nested flex // container. if (aParentReflowInput.IsInFragmentedContext()) { - FLEX_LOG( - "[frag] Flex item %p needed both a measuring reflow and a final " - "reflow due to being in a fragmented context.", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[frag] Item needed both a measuring reflow and a final " + "reflow due to being in a fragmented context"); return true; } @@ -2579,10 +2595,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { if (finalSize != mFrame->ContentSize(mWM)) { // The measuring reflow left the item with a different size than its // final flexed size. So, we need to reflow to give it the correct size. - FLEX_LOG( - "[perf] Flex item %p needed both a measuring reflow and a final " - "reflow due to measured size disagreeing with final size", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed both a measuring reflow and a final " + "reflow due to measured size disagreeing with final size"); return true; } @@ -2590,10 +2605,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // This item has descendants with relative BSizes who may care that its // size may now be considered "definite" in the final reflow (whereas it // was indefinite during the measuring reflow). - FLEX_LOG( - "[perf] Flex item %p needed both a measuring reflow and a final " - "reflow due to BSize potentially becoming definite", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed both a measuring reflow and a final " + "reflow due to BSize potentially becoming definite"); return true; } @@ -2621,10 +2635,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // definiteness. // Let's check for each condition that would still require us to reflow: if (mFrame->IsSubtreeDirty()) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to its subtree " - "being dirty", - mFrame); + FLEX_ITEM_LOG( + mFrame, + "[perf] Item needed a final reflow due to its subtree being dirty"); return true; } @@ -2634,19 +2647,17 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // Did we cache the metrics from its most recent "final reflow"? auto* cache = mFrame->GetProperty(CachedFlexItemData::Prop()); if (!cache || !cache->mFinalReflowMetrics) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to lacking a " - "cached mFinalReflowMetrics (maybe cache was cleared)", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed a final reflow due to lacking a cached " + "mFinalReflowMetrics (maybe cache was cleared)"); return true; } // Does the cached size match our current size? if (cache->mFinalReflowMetrics->Size() != finalSize) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to having a " - "different content box size vs. its most recent final reflow", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed a final reflow due to having a different " + "content box size vs. its most recent final reflow"); return true; } @@ -2659,10 +2670,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // reflow. if (cache->mFinalReflowMetrics->BorderPadding() != BorderPadding().ConvertTo(mWM, mCBWM)) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to having a " - "different border and padding vs. its most recent final reflow", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed a final reflow due to having a different " + "border and padding vs. its most recent final reflow"); return true; } @@ -2672,10 +2682,9 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { if (cache->mFinalReflowMetrics->TreatBSizeAsIndefinite() != mTreatBSizeAsIndefinite && FrameHasRelativeBSizeDependency(mFrame)) { - FLEX_LOG( - "[perf] Flex item %p needed a final reflow due to having " - "its BSize change definiteness & having a rel-BSize child", - mFrame); + FLEX_ITEM_LOG(mFrame, + "[perf] Item needed a final reflow due to having its BSize " + "change definiteness & having a rel-BSize child"); return true; } @@ -2683,7 +2692,7 @@ bool FlexItem::NeedsFinalReflow(const ReflowInput& aParentReflowInput) const { // dirty, and our current conditions are sufficiently similar to the most // recent "final reflow" that it should have left our subtree in the correct // state.) - FLEX_LOG("[perf] Flex item %p didn't need a final reflow", mFrame); + FLEX_ITEM_LOG(mFrame, "[perf] Item didn't need a final reflow"); return false; } @@ -2757,7 +2766,7 @@ class MOZ_STACK_CLASS PositionTracker { const WritingMode mWM; // The axis along which we're moving. - const LogicalAxis mAxis = eLogicalAxisInline; + const LogicalAxis mAxis = LogicalAxis::Inline; // Is the axis along which we're moving reversed (e.g. LTR vs RTL) with // respect to the corresponding axis on the flex container's WM? @@ -3150,8 +3159,8 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, availableFreeSpace -= item.MainSize(); } - FLEX_LOG(" available free space: %" PRId64 "; flex items should \"%s\"", - availableFreeSpace.value, isUsingFlexGrow ? "grow" : "shrink"); + FLEX_LOGV("Available free space: %" PRId64 "; flex items should \"%s\"", + availableFreeSpace.value, isUsingFlexGrow ? "grow" : "shrink"); // The sign of our free space should agree with the type of flexing // (grow/shrink) that we're doing. Any disagreement should've made us use @@ -3276,7 +3285,7 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, } } - FLEX_LOG(" Distributing available space:"); + FLEX_LOGV("Distributing available space:"); // Since this loop only operates on unfrozen flex items, we can break as // soon as we have seen all of them. numUnfrozenItemsToBeSeen = NumItems() - mNumFrozenItems; @@ -3323,8 +3332,8 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, item.SetMainSize(item.MainSize() + nscoord(sizeDelta.ToMinMaxClamped())); - FLEX_LOG(" flex item %p receives %" PRId64 ", for a total of %d", - item.Frame(), sizeDelta.value, item.MainSize()); + FLEX_LOGV(" Flex item %p receives %" PRId64 ", for a total of %d", + item.Frame(), sizeDelta.value, item.MainSize()); } } @@ -3360,7 +3369,7 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, // Fix min/max violations: nscoord totalViolation = 0; // keeps track of adjustments for min/max - FLEX_LOG(" Checking for violations:"); + FLEX_LOGV("Checking for violations:"); // Since this loop only operates on unfrozen flex items, we can break as // soon as we have seen all of them. @@ -3392,7 +3401,7 @@ void FlexLine::ResolveFlexibleLengths(nscoord aFlexContainerMainSize, FreezeOrRestoreEachFlexibleSize(totalViolation, iterationCounter + 1 == NumItems()); - FLEX_LOG(" Total violation: %d", totalViolation); + FLEX_LOGV("Total violation: %d", totalViolation); if (mNumFrozenItems == NumItems()) { break; @@ -3952,7 +3961,7 @@ void SingleLineCrossAxisPositionTracker::EnterAlignPackingSpace( if (alignSelf == StyleAlignFlags::SELF_START || alignSelf == StyleAlignFlags::SELF_END) { const LogicalAxis logCrossAxis = - aAxisTracker.IsRowOriented() ? eLogicalAxisBlock : eLogicalAxisInline; + aAxisTracker.IsRowOriented() ? LogicalAxis::Block : LogicalAxis::Inline; const WritingMode cWM = aAxisTracker.GetWritingMode(); const bool sameStart = cWM.ParallelAxisStartsOnSameSide(logCrossAxis, aItem.GetWritingMode()); @@ -4560,7 +4569,6 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext, MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsFlexContainerFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); MOZ_ASSERT(aPresContext == PresContext()); NS_WARNING_ASSERTION( @@ -4568,7 +4576,7 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext, "Unconstrained inline size; this should only result from huge sizes " "(not intrinsic sizing w/ orthogonal flows)"); - FLEX_LOG("Reflow() for nsFlexContainerFrame %p", this); + FLEX_LOG("Reflowing flex container frame %p ...", this); if (IsFrameTreeTooDeep(aReflowInput, aReflowOutput, aStatus)) { return; @@ -5276,8 +5284,8 @@ nsFlexContainerFrame::FlexLayoutResult nsFlexContainerFrame::DoFlexLayout( } else { sizeOverrides.mStyleBSize.emplace(item.StyleMainSize()); } - FLEX_LOG("Sizing flex item %p in cross axis", item.Frame()); - FLEX_LOGV(" Main size override: %d", item.MainSize()); + FLEX_ITEM_LOG(item.Frame(), "Sizing item in cross axis"); + FLEX_LOGV("Main size override: %d", item.MainSize()); const WritingMode wm = item.GetWritingMode(); LogicalSize availSize = aReflowInput.ComputedSize(wm); @@ -5640,10 +5648,10 @@ std::tuple<nscoord, nsReflowStatus> nsFlexContainerFrame::ReflowChildren( // block-size and add it to // PerFragmentFlexData::mCumulativeContentBoxBSize even if we are not // laying out any child. - FLEX_LOG( - "[frag] Flex item %p needed to be pushed to container's " - "next-in-flow due to position below available space's block-end", - item.Frame()); + FLEX_ITEM_LOG( + item.Frame(), + "[frag] Item needed to be pushed to container's next-in-flow due " + "to being positioned beyond block-end edge of available space"); pushedItems.Insert(item.Frame()); itemInPushedItems = true; } else if (item.NeedsFinalReflow(aReflowInput)) { @@ -5680,11 +5688,10 @@ std::tuple<nscoord, nsReflowStatus> nsFlexContainerFrame::ReflowChildren( return true; }(); if (shouldPushItem) { - FLEX_LOG( - "[frag] Flex item %p needed to be pushed to container's " - "next-in-flow because its block-size is larger than the " - "available space", - item.Frame()); + FLEX_ITEM_LOG( + item.Frame(), + "[frag] Item needed to be pushed to container's next-in-flow " + "because its block-size is larger than the available space"); pushedItems.Insert(item.Frame()); itemInPushedItems = true; } else if (childReflowStatus.IsIncomplete()) { @@ -6050,8 +6057,8 @@ void nsFlexContainerFrame::MoveFlexItemToFinalPosition( logicalOffsets, &pos, aContainerSize); } - FLEX_LOG("Moving flex item %p to its desired position %s", aItem.Frame(), - ToString(pos).c_str()); + FLEX_ITEM_LOG(aItem.Frame(), "Moving item to its desired position %s", + ToString(pos).c_str()); aItem.Frame()->SetPosition(outerWM, pos, aContainerSize); PositionFrameView(aItem.Frame()); PositionChildViews(aItem.Frame()); @@ -6061,7 +6068,7 @@ nsReflowStatus nsFlexContainerFrame::ReflowFlexItem( const FlexboxAxisTracker& aAxisTracker, const ReflowInput& aReflowInput, const FlexItem& aItem, const LogicalPoint& aFramePos, const LogicalSize& aAvailableSize, const nsSize& aContainerSize) { - FLEX_LOG("Doing final reflow for flex item %p", aItem.Frame()); + FLEX_ITEM_LOG(aItem.Frame(), "Doing final reflow"); // Returns true if we should use 'auto' in block axis's StyleSizeOverrides to // allow fragmentation-imposed block-size growth. @@ -6131,15 +6138,15 @@ nsReflowStatus nsFlexContainerFrame::ReflowFlexItem( // Override flex item's main size. if (aItem.IsInlineAxisMainAxis()) { sizeOverrides.mStyleISize.emplace(aItem.StyleMainSize()); - FLEX_LOGV(" Main size (inline-size) override: %d", aItem.MainSize()); + FLEX_LOGV("Main size (inline-size) override: %d", aItem.MainSize()); } else { overrideBSizeWithAuto = ComputeBSizeOverrideWithAuto(); if (overrideBSizeWithAuto) { sizeOverrides.mStyleBSize.emplace(StyleSize::Auto()); - FLEX_LOGV(" Main size (block-size) override: Auto"); + FLEX_LOGV("Main size (block-size) override: Auto"); } else { sizeOverrides.mStyleBSize.emplace(aItem.StyleMainSize()); - FLEX_LOGV(" Main size (block-size) override: %d", aItem.MainSize()); + FLEX_LOGV("Main size (block-size) override: %d", aItem.MainSize()); } } @@ -6148,15 +6155,15 @@ nsReflowStatus nsFlexContainerFrame::ReflowFlexItem( if (aItem.IsStretched()) { if (aItem.IsInlineAxisCrossAxis()) { sizeOverrides.mStyleISize.emplace(aItem.StyleCrossSize()); - FLEX_LOGV(" Cross size (inline-size) override: %d", aItem.CrossSize()); + FLEX_LOGV("Cross size (inline-size) override: %d", aItem.CrossSize()); } else { overrideBSizeWithAuto = ComputeBSizeOverrideWithAuto(); if (overrideBSizeWithAuto) { sizeOverrides.mStyleBSize.emplace(StyleSize::Auto()); - FLEX_LOGV(" Cross size (block-size) override: Auto"); + FLEX_LOGV("Cross size (block-size) override: Auto"); } else { sizeOverrides.mStyleBSize.emplace(aItem.StyleCrossSize()); - FLEX_LOGV(" Cross size (block-size) override: %d", aItem.CrossSize()); + FLEX_LOGV("Cross size (block-size) override: %d", aItem.CrossSize()); } } } @@ -6203,8 +6210,8 @@ nsReflowStatus nsFlexContainerFrame::ReflowFlexItem( // after this point, because some of its methods (e.g. SetComputedWidth) // internally call InitResizeFlags and stomp on mVResize & mHResize. - FLEX_LOG("Reflowing flex item %p at its desired position %s", aItem.Frame(), - ToString(aFramePos).c_str()); + FLEX_ITEM_LOG(aItem.Frame(), "Reflowing item at its desired position %s", + ToString(aFramePos).c_str()); // CachedFlexItemData is stored in item's writing mode, so we pass // aChildReflowInput into ReflowOutput's constructor. @@ -6332,7 +6339,6 @@ nscoord nsFlexContainerFrame::IntrinsicISize(gfxContext* aRenderingContext, /* virtual */ nscoord nsFlexContainerFrame::GetMinISize(gfxContext* aRenderingContext) { - DISPLAY_MIN_INLINE_SIZE(this, mCachedMinISize); if (mCachedMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) { if (Maybe<nscoord> containISize = ContainIntrinsicISize()) { mCachedMinISize = *containISize; @@ -6347,7 +6353,6 @@ nscoord nsFlexContainerFrame::GetMinISize(gfxContext* aRenderingContext) { /* virtual */ nscoord nsFlexContainerFrame::GetPrefISize(gfxContext* aRenderingContext) { - DISPLAY_PREF_INLINE_SIZE(this, mCachedPrefISize); if (mCachedPrefISize == NS_INTRINSIC_ISIZE_UNKNOWN) { if (Maybe<nscoord> containISize = ContainIntrinsicISize()) { mCachedPrefISize = *containISize; diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index 30e440b401..14f91ae064 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -12,15 +12,9 @@ #include <tuple> #include "mozilla/dom/FlexBinding.h" -#include "mozilla/UniquePtr.h" #include "nsContainerFrame.h" #include "nsILineIterator.h" -namespace mozilla { -class LogicalPoint; -class PresShell; -} // namespace mozilla - nsContainerFrame* NS_NewFlexContainerFrame(mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle); diff --git a/layout/generic/nsFloatManager.cpp b/layout/generic/nsFloatManager.cpp index b6612ca6f5..e1866b35c1 100644 --- a/layout/generic/nsFloatManager.cpp +++ b/layout/generic/nsFloatManager.cpp @@ -2507,7 +2507,7 @@ nsFloatManager::ShapeInfo::CreateBasicShape(const StyleBasicShape& aBasicShape, case StyleBasicShape::Tag::Rect: return CreateInset(aBasicShape, aShapeMargin, aFrame, aShapeBoxRect, aWM, aContainerSize); - case StyleBasicShape::Tag::Path: + case StyleBasicShape::Tag::PathOrShape: MOZ_ASSERT_UNREACHABLE("Unsupported basic shape"); } return nullptr; diff --git a/layout/generic/nsFrameSelection.cpp b/layout/generic/nsFrameSelection.cpp index f1a8c7e27c..ca4e3d647e 100644 --- a/layout/generic/nsFrameSelection.cpp +++ b/layout/generic/nsFrameSelection.cpp @@ -156,9 +156,10 @@ PeekOffsetStruct::PeekOffsetStruct(nsSelectionAmount aAmount, } // namespace mozilla -// Array which contains index of each SelecionType in Selection::mDOMSelections. -// For avoiding using if nor switch to retrieve the index, this needs to have -// -1 for SelectionTypes which won't be created its Selection instance. +// Array which contains index of each SelectionType in +// Selection::mDOMSelections. For avoiding using if nor switch to retrieve the +// index, this needs to have -1 for SelectionTypes which won't be created its +// Selection instance. static const int8_t kIndexOfSelections[] = { -1, // SelectionType::eInvalid -1, // SelectionType::eNone @@ -172,6 +173,7 @@ static const int8_t kIndexOfSelections[] = { 7, // SelectionType::eFind 8, // SelectionType::eURLSecondary 9, // SelectionType::eURLStrikeout + 10, // SelectionType::eTargetText -1, // SelectionType::eHighlight }; @@ -539,7 +541,11 @@ nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree( NS_ENSURE_STATE(mPresShell); RefPtr<PresShell> presShell = mPresShell; - nsIContent* anchorRoot = anchorContent->GetSelectionRootContent(presShell); + nsIContent* anchorRoot = + anchorContent + ->GetSelectionRootContent( + presShell, + StaticPrefs::dom_shadowdom_selection_across_boundary_enabled() /* aAllowCrossShadowBoundary */); NS_ENSURE_TRUE(anchorRoot, NS_ERROR_UNEXPECTED); // @@ -549,7 +555,10 @@ nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree( nsCOMPtr<nsIContent> content = aFrame->GetContent(); if (content) { - nsIContent* contentRoot = content->GetSelectionRootContent(presShell); + nsIContent* contentRoot = + content->GetSelectionRootContent( + presShell, StaticPrefs:: + dom_shadowdom_selection_across_boundary_enabled() /* aAllowCrossShadowBoundary */); NS_ENSURE_TRUE(contentRoot, NS_ERROR_UNEXPECTED); if (anchorRoot == contentRoot) { @@ -573,8 +582,9 @@ nsresult nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree( if (cursorFrame && cursorFrame->PresShell() == presShell) { nsCOMPtr<nsIContent> cursorContent = cursorFrame->GetContent(); NS_ENSURE_TRUE(cursorContent, NS_ERROR_FAILURE); - nsIContent* cursorContentRoot = - cursorContent->GetSelectionRootContent(presShell); + nsIContent* cursorContentRoot = cursorContent->GetSelectionRootContent( + presShell, StaticPrefs:: + dom_shadowdom_selection_across_boundary_enabled() /* aAllowCrossShadowBoundary */); NS_ENSURE_TRUE(cursorContentRoot, NS_ERROR_UNEXPECTED); if (cursorContentRoot == anchorRoot) { *aRetFrame = cursorFrame; @@ -1493,11 +1503,11 @@ void nsFrameSelection::SetDragState(bool aState) { // Notify that reason is mouse up. SetChangeReasons(nsISelectionListener::MOUSEUP_REASON); - // flag is set to false in `NotifySelectionListeners`. + // flag is set to NotApplicable in `Selection::NotifySelectionListeners`. // since this function call is part of click event, this would immediately // reset the flag, rendering it useless. - AutoRestore<bool> restoreIsDoubleClickSelectionFlag( - mIsDoubleClickSelection); + AutoRestore<ClickSelectionType> restoreClickSelectionType( + mClickSelectionType); // Be aware, the Selection instance may be destroyed after this call. NotifySelectionListeners(SelectionType::eNormal); } diff --git a/layout/generic/nsFrameSelection.h b/layout/generic/nsFrameSelection.h index e8c55d53b5..3ba6fa72ca 100644 --- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -200,6 +200,7 @@ class SelectionChangeEventDispatcher; namespace dom { class Highlight; class Selection; +enum class ClickSelectionType { NotApplicable, Double, Triple }; } // namespace dom /** @@ -259,14 +260,17 @@ class nsFrameSelection final { public: /** - * Sets flag to true if a selection is created by doubleclick or - * long tapping a word. + * Sets the type of the selection based on whether a selection is created + * by doubleclick, long tapping a word or tripleclick. * - * @param aIsDoubleClickSelection True if the selection is created by - * doubleclick or long tap over a word. + * @param aClickSelectionType ClickSelectionType::Double if the selection + * is created by doubleclick, + * ClickSelectionType::Triple if the selection + * is created by tripleclick. */ - void SetIsDoubleClickSelection(bool aIsDoubleClickSelection) { - mIsDoubleClickSelection = aIsDoubleClickSelection; + void SetClickSelectionType( + mozilla::dom::ClickSelectionType aClickSelectionType) { + mClickSelectionType = aClickSelectionType; } /** @@ -274,7 +278,14 @@ class nsFrameSelection final { * long tap over a word. */ [[nodiscard]] bool IsDoubleClickSelection() const { - return mIsDoubleClickSelection; + return mClickSelectionType == mozilla::dom::ClickSelectionType::Double; + } + + /** + * Returns true if the selection was created by triple click + */ + [[nodiscard]] bool IsTripleClickSelection() const { + return mClickSelectionType == mozilla::dom::ClickSelectionType::Triple; } /** @@ -1102,11 +1113,12 @@ class nsFrameSelection final { bool mDragState = false; // for drag purposes bool mAccessibleCaretEnabled = false; - // Records if a selection was created by doubleclicking a word. - // This information is needed later on to determine if a leading + // Records if a selection was created by doubleclicking or tripleclicking + // a word. This information is needed later on to determine if a leading // or trailing whitespace needs to be removed as well to achieve // native behaviour on macOS. - bool mIsDoubleClickSelection{false}; + mozilla::dom::ClickSelectionType mClickSelectionType = + mozilla::dom::ClickSelectionType::NotApplicable; }; /** diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index f292988c55..be561a6c32 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -760,7 +760,6 @@ void nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); mozilla::PresShell* presShell = aPresContext->PresShell(); @@ -1312,7 +1311,6 @@ void nsHTMLFramesetBorderFrame::Reflow(nsPresContext* aPresContext, const ReflowInput& aReflowInput, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); // Override Reflow(), since we don't want to deal with what our diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 361847b753..2b0c53efe1 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -170,7 +170,7 @@ class nsHTMLScrollFrame::ScrollEvent : public Runnable { class nsHTMLScrollFrame::ScrollEndEvent : public Runnable { public: NS_DECL_NSIRUNNABLE - explicit ScrollEndEvent(nsHTMLScrollFrame* aHelper); + explicit ScrollEndEvent(nsHTMLScrollFrame* aHelper, bool aDelayed); void Revoke() { mHelper = nullptr; } private: @@ -1265,17 +1265,7 @@ nsMargin nsHTMLScrollFrame::ComputeStableScrollbarGutter( // Legacy, this sucks! static bool IsMarqueeScrollbox(const nsIFrame& aScrollFrame) { - if (!aScrollFrame.GetContent()) { - return false; - } - if (MOZ_LIKELY(!aScrollFrame.GetContent()->HasBeenInUAWidget())) { - return false; - } - MOZ_ASSERT(aScrollFrame.GetParent() && - aScrollFrame.GetParent()->GetContent()); - return aScrollFrame.GetParent() && - HTMLMarqueeElement::FromNodeOrNull( - aScrollFrame.GetParent()->GetContent()); + return HTMLMarqueeElement::FromNodeOrNull(aScrollFrame.GetContent()); } /* virtual */ @@ -1290,7 +1280,6 @@ nscoord nsHTMLScrollFrame::GetMinISize(gfxContext* aRenderingContext) { return mScrolledFrame->GetMinISize(aRenderingContext); }(); - DISPLAY_MIN_INLINE_SIZE(this, result); return result + IntrinsicScrollbarGutterSizeAtInlineEdges(); } @@ -1300,7 +1289,6 @@ nscoord nsHTMLScrollFrame::GetPrefISize(gfxContext* aRenderingContext) { nscoord result = containISize ? *containISize : mScrolledFrame->GetPrefISize(aRenderingContext); - DISPLAY_PREF_INLINE_SIZE(this, result); return NSCoordSaturatingAdd(result, IntrinsicScrollbarGutterSizeAtInlineEdges()); } @@ -1497,7 +1485,6 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsHTMLScrollFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); HandleScrollbarStyleSwitching(); @@ -5429,23 +5416,31 @@ nsresult nsHTMLScrollFrame::FireScrollPortEvent() { return EventDispatcher::Dispatch(content, presContext, &event); } -void nsHTMLScrollFrame::PostScrollEndEvent() { +void nsHTMLScrollFrame::PostScrollEndEvent(bool aDelayed) { if (mScrollEndEvent) { return; } // The ScrollEndEvent constructor registers itself with the refresh driver. - mScrollEndEvent = new ScrollEndEvent(this); + mScrollEndEvent = new ScrollEndEvent(this, aDelayed); } void nsHTMLScrollFrame::FireScrollEndEvent() { - MOZ_ASSERT(GetContent()); - MOZ_ASSERT(mScrollEndEvent); + RefPtr<nsIContent> content = GetContent(); + MOZ_ASSERT(content); - RefPtr<nsPresContext> presContext = PresContext(); + MOZ_ASSERT(mScrollEndEvent); mScrollEndEvent->Revoke(); mScrollEndEvent = nullptr; + if (content->GetComposedDoc() && + content->GetComposedDoc()->EventHandlingSuppressed()) { + content->GetComposedDoc()->SetHasDelayedRefreshEvent(); + PostScrollEndEvent(/* aDelayed = */ true); + return; + } + + RefPtr<nsPresContext> presContext = PresContext(); nsEventStatus status = nsEventStatus_eIgnore; WidgetGUIEvent event(true, eScrollend, nullptr); event.mFlags.mBubbles = mIsRoot; @@ -5895,9 +5890,10 @@ nsHTMLScrollFrame::ScrollEvent::Run() { return NS_OK; } -nsHTMLScrollFrame::ScrollEndEvent::ScrollEndEvent(nsHTMLScrollFrame* aHelper) +nsHTMLScrollFrame::ScrollEndEvent::ScrollEndEvent(nsHTMLScrollFrame* aHelper, + bool aDelayed) : Runnable("nsHTMLScrollFrame::ScrollEndEvent"), mHelper(aHelper) { - mHelper->PresContext()->RefreshDriver()->PostScrollEvent(this); + mHelper->PresContext()->RefreshDriver()->PostScrollEvent(this, aDelayed); } MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index ce2a75a3df..9d619de4e5 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -500,7 +500,7 @@ class nsHTMLScrollFrame : public nsContainerFrame, OverflowState GetOverflowState() const; MOZ_CAN_RUN_SCRIPT nsresult FireScrollPortEvent(); - void PostScrollEndEvent(); + void PostScrollEndEvent(bool aDelayed = false); MOZ_CAN_RUN_SCRIPT void FireScrollEndEvent(); void PostOverflowEvent(); diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp index 5eb9cde7da..bb6e2150ce 100644 --- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -28,6 +28,7 @@ #include "nsCSSFrameConstructor.h" #include "nsDisplayList.h" #include "nsFieldSetFrame.h" +#include "nsHTMLButtonControlFrame.h" #include "nsGfxScrollFrame.h" #include "nsHashKeys.h" #include "nsIFrameInlines.h" // for nsIFrame::GetLogicalNormalPosition (don't remove) @@ -168,7 +169,7 @@ static nscoord ResolveToDefiniteSize(const StyleTrackBreadth& aBreadth, // block axis; e.g. for English horizontal-tb text, a traditional baseline // would be a y-axis measurement. But in some cases (e.g. orthogonal WMs), we // may need to synthesize a baseline in a child's inline axis, which is when -// this function might receive an aAxis of eLogicalAxisInline. In that case, we +// this function might receive an aAxis of LogicalAxis::Inline. In that case, we // assume that the writing mode's preference for central vs. alphabetic // baselines is irrelevant, since that's a choice about its block-axis // baselines, and we just unconditionally use the alphabetic baseline @@ -178,7 +179,7 @@ static nscoord SynthesizeBaselineFromBorderBox(BaselineSharingGroup aGroup, LogicalAxis aAxis, nscoord aBorderBoxSize) { const bool useAlphabeticBaseline = - (aAxis == eLogicalAxisInline) ? true : aWM.IsAlphabeticalBaseline(); + (aAxis == LogicalAxis::Inline) ? true : aWM.IsAlphabeticalBaseline(); if (aGroup == BaselineSharingGroup::First) { return useAlphabeticBaseline ? aBorderBoxSize : aBorderBoxSize / 2; @@ -218,7 +219,7 @@ struct RepeatTrackSizingInput { // We can use zero percentage basis since this is only called from // intrinsic sizing code. const nscoord percentageBasis = 0; - if (aAxis == eLogicalAxisInline) { + if (aAxis == LogicalAxis::Inline) { bp = std::max(padding.GetIStart(aWM).Resolve(percentageBasis), 0) + std::max(padding.GetIEnd(aWM).Resolve(percentageBasis), 0) + border.IStartEnd(aWM); @@ -234,17 +235,17 @@ struct RepeatTrackSizingInput { nscoord& size = mSize.Size(aAxis, aWM); nscoord& max = mMax.Size(aAxis, aWM); const auto& minCoord = - aAxis == eLogicalAxisInline ? pos->MinISize(aWM) : pos->MinBSize(aWM); + aAxis == LogicalAxis::Inline ? pos->MinISize(aWM) : pos->MinBSize(aWM); if (minCoord.ConvertsToLength()) { min = adjustForBoxSizing(minCoord.ToLength()); } const auto& maxCoord = - aAxis == eLogicalAxisInline ? pos->MaxISize(aWM) : pos->MaxBSize(aWM); + aAxis == LogicalAxis::Inline ? pos->MaxISize(aWM) : pos->MaxBSize(aWM); if (maxCoord.ConvertsToLength()) { max = std::max(min, adjustForBoxSizing(maxCoord.ToLength())); } const auto& sizeCoord = - aAxis == eLogicalAxisInline ? pos->ISize(aWM) : pos->BSize(aWM); + aAxis == LogicalAxis::Inline ? pos->ISize(aWM) : pos->BSize(aWM); if (sizeCoord.ConvertsToLength()) { size = Clamp(adjustForBoxSizing(sizeCoord.ToLength()), min, max); } @@ -576,10 +577,10 @@ struct nsGridContainerFrame::GridArea { : mCols(aCols), mRows(aRows) {} bool IsDefinite() const { return mCols.IsDefinite() && mRows.IsDefinite(); } LineRange& LineRangeForAxis(LogicalAxis aAxis) { - return aAxis == eLogicalAxisInline ? mCols : mRows; + return aAxis == LogicalAxis::Inline ? mCols : mRows; } const LineRange& LineRangeForAxis(LogicalAxis aAxis) const { - return aAxis == eLogicalAxisInline ? mCols : mRows; + return aAxis == LogicalAxis::Inline ? mCols : mRows; } LineRange mCols; LineRange mRows; @@ -665,12 +666,12 @@ struct nsGridContainerFrame::GridItemInfo { */ GridItemInfo Transpose() const { GridItemInfo info(mFrame, GridArea(mArea.mRows, mArea.mCols)); - info.mState[eLogicalAxisBlock] = mState[eLogicalAxisInline]; - info.mState[eLogicalAxisInline] = mState[eLogicalAxisBlock]; - info.mBaselineOffset[eLogicalAxisBlock] = - mBaselineOffset[eLogicalAxisInline]; - info.mBaselineOffset[eLogicalAxisInline] = - mBaselineOffset[eLogicalAxisBlock]; + info.mState[LogicalAxis::Block] = mState[LogicalAxis::Inline]; + info.mState[LogicalAxis::Inline] = mState[LogicalAxis::Block]; + info.mBaselineOffset[LogicalAxis::Block] = + mBaselineOffset[LogicalAxis::Inline]; + info.mBaselineOffset[LogicalAxis::Inline] = + mBaselineOffset[LogicalAxis::Block]; return info; } @@ -684,7 +685,7 @@ struct nsGridContainerFrame::GridItemInfo { // Is this item a subgrid in either axis? bool IsSubgrid() const { - return IsSubgrid(eLogicalAxisInline) || IsSubgrid(eLogicalAxisBlock); + return IsSubgrid(LogicalAxis::Inline) || IsSubgrid(LogicalAxis::Block); } // Return the (inner) grid container frame associated with this subgrid item. @@ -725,7 +726,7 @@ struct nsGridContainerFrame::GridItemInfo { bool ShouldApplyAutoMinSize(WritingMode aContainerWM, LogicalAxis aContainerAxis, nscoord aPercentageBasis) const { - const bool isInlineAxis = aContainerAxis == eLogicalAxisInline; + const bool isInlineAxis = aContainerAxis == LogicalAxis::Inline; const auto* pos = mFrame->IsTableWrapperFrame() ? mFrame->PrincipalChildList().FirstChild()->StylePosition() @@ -793,9 +794,9 @@ struct nsGridContainerFrame::GridItemInfo { return isContinuationA; } auto masonryA = a->mArea.mRows.mStart; - auto gridA = a->mState[eLogicalAxisInline] & StateBits::eAutoPlacement; + auto gridA = a->mState[LogicalAxis::Inline] & StateBits::eAutoPlacement; auto masonryB = b->mArea.mRows.mStart; - auto gridB = b->mState[eLogicalAxisInline] & StateBits::eAutoPlacement; + auto gridB = b->mState[LogicalAxis::Inline] & StateBits::eAutoPlacement; return (masonryA == 0 ? masonryB != 0 : (masonryB != 0 && gridA < gridB)) && !a->mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW); } @@ -804,9 +805,9 @@ struct nsGridContainerFrame::GridItemInfo { MOZ_ASSERT(!a->mFrame->GetPrevInFlow() && !b->mFrame->GetPrevInFlow(), "fragmentation not supported in inline axis"); auto masonryA = a->mArea.mCols.mStart; - auto gridA = a->mState[eLogicalAxisBlock] & StateBits::eAutoPlacement; + auto gridA = a->mState[LogicalAxis::Block] & StateBits::eAutoPlacement; auto masonryB = b->mArea.mCols.mStart; - auto gridB = b->mState[eLogicalAxisBlock] & StateBits::eAutoPlacement; + auto gridB = b->mState[LogicalAxis::Block] & StateBits::eAutoPlacement; return (masonryA == 0 ? masonryB != 0 : (masonryB != 0 && gridA < gridB)) && !a->mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW); } @@ -847,20 +848,20 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ItemState) GridItemInfo::GridItemInfo(nsIFrame* aFrame, const GridArea& aArea) : mFrame(aFrame), mArea(aArea), mBaselineOffset{0, 0} { - mState[eLogicalAxisBlock] = + mState[LogicalAxis::Block] = StateBits(mArea.mRows.mStart == kAutoLine ? eAutoPlacement : 0); - mState[eLogicalAxisInline] = + mState[LogicalAxis::Inline] = StateBits(mArea.mCols.mStart == kAutoLine ? eAutoPlacement : 0); if (auto* gridFrame = GetGridContainerFrame(mFrame)) { auto parentWM = aFrame->GetParent()->GetWritingMode(); bool isOrthogonal = parentWM.IsOrthogonalTo(gridFrame->GetWritingMode()); if (gridFrame->IsColSubgrid()) { - mState[isOrthogonal ? eLogicalAxisBlock : eLogicalAxisInline] |= + mState[isOrthogonal ? LogicalAxis::Block : LogicalAxis::Inline] |= StateBits::eIsSubgrid; } if (gridFrame->IsRowSubgrid()) { - mState[isOrthogonal ? eLogicalAxisInline : eLogicalAxisBlock] |= + mState[isOrthogonal ? LogicalAxis::Inline : LogicalAxis::Block] |= StateBits::eIsSubgrid; } } @@ -884,7 +885,7 @@ void GridItemInfo::InhibitSubgrid(nsGridContainerFrame* aParent, MOZ_ASSERT(IsSubgrid(aAxis)); auto bit = NS_STATE_GRID_IS_COL_SUBGRID; if (aParent->GetWritingMode().IsOrthogonalTo(mFrame->GetWritingMode()) != - (aAxis == eLogicalAxisBlock)) { + (aAxis == LogicalAxis::Block)) { bit = NS_STATE_GRID_IS_ROW_SUBGRID; } MOZ_ASSERT(SubgridFrame()->HasAnyStateBits(bit)); @@ -894,16 +895,18 @@ void GridItemInfo::InhibitSubgrid(nsGridContainerFrame* aParent, void GridItemInfo::MaybeInhibitSubgridInMasonry(nsGridContainerFrame* aParent, uint32_t aGridAxisTrackCount) { - if (IsSubgrid(eLogicalAxisInline) && aParent->IsMasonry(eLogicalAxisBlock) && - mArea.mRows.mStart != 0 && mArea.mCols.Extent() != aGridAxisTrackCount && - (mState[eLogicalAxisInline] & eAutoPlacement)) { - InhibitSubgrid(aParent, eLogicalAxisInline); + if (IsSubgrid(LogicalAxis::Inline) && + aParent->IsMasonry(LogicalAxis::Block) && mArea.mRows.mStart != 0 && + mArea.mCols.Extent() != aGridAxisTrackCount && + (mState[LogicalAxis::Inline] & eAutoPlacement)) { + InhibitSubgrid(aParent, LogicalAxis::Inline); return; } - if (IsSubgrid(eLogicalAxisBlock) && aParent->IsMasonry(eLogicalAxisInline) && - mArea.mCols.mStart != 0 && mArea.mRows.Extent() != aGridAxisTrackCount && - (mState[eLogicalAxisBlock] & eAutoPlacement)) { - InhibitSubgrid(aParent, eLogicalAxisBlock); + if (IsSubgrid(LogicalAxis::Block) && + aParent->IsMasonry(LogicalAxis::Inline) && mArea.mCols.mStart != 0 && + mArea.mRows.Extent() != aGridAxisTrackCount && + (mState[LogicalAxis::Block] & eAutoPlacement)) { + InhibitSubgrid(aParent, LogicalAxis::Block); } } @@ -1061,9 +1064,9 @@ void nsGridContainerFrame::GridItemInfo::Dump() const { printf("\n"); }; printf("grid-row: %d %d\n", mArea.mRows.mStart, mArea.mRows.mEnd); - Dump1(" grid block-axis: ", eLogicalAxisBlock); + Dump1(" grid block-axis: ", LogicalAxis::Block); printf("grid-column: %d %d\n", mArea.mCols.mStart, mArea.mCols.mEnd); - Dump1(" grid inline-axis: ", eLogicalAxisInline); + Dump1(" grid inline-axis: ", LogicalAxis::Inline); } #endif @@ -1150,8 +1153,9 @@ struct nsGridContainerFrame::TrackSizingFunctions { parent->GetWritingMode().ParallelAxisStartsOnSameSide(parentAxis, grandParentWM); if (MOZ_UNLIKELY(!isSameDirInAxis)) { - auto end = parentAxis == eLogicalAxisBlock ? parentSubgrid->mGridRowEnd - : parentSubgrid->mGridColEnd; + auto end = parentAxis == LogicalAxis::Block + ? parentSubgrid->mGridRowEnd + : parentSubgrid->mGridColEnd; range.ReverseDirection(end); // range is now in the same direction as the grand-parent's axis } @@ -1166,7 +1170,7 @@ struct nsGridContainerFrame::TrackSizingFunctions { parent = grandParent; } const auto* pos = parent->StylePosition(); - const auto isInlineAxis = parentAxis == eLogicalAxisInline; + const auto isInlineAxis = parentAxis == LogicalAxis::Inline; const auto& szf = isInlineAxis ? pos->mGridTemplateRows : pos->mGridTemplateColumns; const auto& autoSizing = @@ -2707,7 +2711,7 @@ struct nsGridContainerFrame::Tracks { * gap before aRow to zero (and shift all rows after it by the removed gap). */ void BreakBeforeRow(uint32_t aRow) { - MOZ_ASSERT(mAxis == eLogicalAxisBlock, + MOZ_ASSERT(mAxis == LogicalAxis::Block, "Should only be fragmenting in the block axis (between rows)"); nscoord prevRowEndPos = 0; if (aRow != 0) { @@ -2728,7 +2732,7 @@ struct nsGridContainerFrame::Tracks { * Set the size of aRow to aSize and adjust the position of all rows after it. */ void ResizeRow(uint32_t aRow, nscoord aNewSize) { - MOZ_ASSERT(mAxis == eLogicalAxisBlock, + MOZ_ASSERT(mAxis == LogicalAxis::Block, "Should only be fragmenting in the block axis (between rows)"); MOZ_ASSERT(aNewSize >= 0); auto& sz = mSizes[aRow]; @@ -2775,7 +2779,7 @@ struct nsGridContainerFrame::Tracks { #ifdef DEBUG void nsGridContainerFrame::Tracks::Dump() const { printf("%zu %s %s ", mSizes.Length(), mIsMasonry ? "masonry" : "grid", - mAxis == eLogicalAxisBlock ? "rows" : "columns"); + mAxis == LogicalAxis::Block ? "rows" : "columns"); TrackSize::DumpStateBits(mStateUnion); printf("\n"); for (uint32_t i = 0, len = mSizes.Length(); i < len; ++i) { @@ -2805,8 +2809,8 @@ void nsGridContainerFrame::Tracks::Dump() const { */ struct nsGridContainerFrame::SharedGridData { SharedGridData() - : mCols(eLogicalAxisInline), - mRows(eLogicalAxisBlock), + : mCols(LogicalAxis::Inline), + mRows(LogicalAxis::Block), mGenerateComputedGridInfo(false) {} Tracks mCols; Tracks mRows; @@ -2884,7 +2888,7 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { } } if (mStartRow == numRows || - aGridContainerFrame->IsMasonry(eLogicalAxisBlock)) { + aGridContainerFrame->IsMasonry(LogicalAxis::Block)) { // All of the grid's rows fit inside of previous grid-container fragments, // or it's a masonry axis. mFragBStart = aConsumedBSize; @@ -2904,8 +2908,8 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { aGridContainerFrame->SetProperty(UsedTrackSizes::Prop(), prop); } prop->mCanResolveLineRangeSize = {true, true}; - prop->mSizes[eLogicalAxisInline].Assign(mCols.mSizes); - prop->mSizes[eLogicalAxisBlock].Assign(mRows.mSizes); + prop->mSizes[LogicalAxis::Inline].Assign(mCols.mSizes); + prop->mSizes[LogicalAxis::Block].Assign(mRows.mSizes); } // Copy item data from each child's first-in-flow data in mSharedGridData. @@ -2921,18 +2925,19 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { mGridItems.AppendElement(GridItemInfo(child, itemInfo.mArea)); // Copy the item's baseline data so that the item's last fragment can // do 'last baseline' alignment if necessary. - item->mState[eLogicalAxisBlock] |= - itemInfo.mState[eLogicalAxisBlock] & ItemState::eAllBaselineBits; - item->mState[eLogicalAxisInline] |= - itemInfo.mState[eLogicalAxisInline] & ItemState::eAllBaselineBits; - item->mBaselineOffset[eLogicalAxisBlock] = - itemInfo.mBaselineOffset[eLogicalAxisBlock]; - item->mBaselineOffset[eLogicalAxisInline] = - itemInfo.mBaselineOffset[eLogicalAxisInline]; - item->mState[eLogicalAxisBlock] |= - itemInfo.mState[eLogicalAxisBlock] & ItemState::eAutoPlacement; - item->mState[eLogicalAxisInline] |= - itemInfo.mState[eLogicalAxisInline] & ItemState::eAutoPlacement; + item->mState[LogicalAxis::Block] |= + itemInfo.mState[LogicalAxis::Block] & ItemState::eAllBaselineBits; + item->mState[LogicalAxis::Inline] |= + itemInfo.mState[LogicalAxis::Inline] & + ItemState::eAllBaselineBits; + item->mBaselineOffset[LogicalAxis::Block] = + itemInfo.mBaselineOffset[LogicalAxis::Block]; + item->mBaselineOffset[LogicalAxis::Inline] = + itemInfo.mBaselineOffset[LogicalAxis::Inline]; + item->mState[LogicalAxis::Block] |= + itemInfo.mState[LogicalAxis::Block] & ItemState::eAutoPlacement; + item->mState[LogicalAxis::Inline] |= + itemInfo.mState[LogicalAxis::Inline] & ItemState::eAutoPlacement; break; } } @@ -2975,7 +2980,7 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { /** * Return the percentage basis for a grid item in its writing-mode. - * If aAxis is eLogicalAxisInline then we return NS_UNCONSTRAINEDSIZE in + * If aAxis is LogicalAxis::Inline then we return NS_UNCONSTRAINEDSIZE in * both axes since we know all track sizes are indefinite at this point * (we calculate column sizes before row sizes). Otherwise, assert that * column sizes are known and calculate the size for aGridItem.mArea.mCols @@ -3218,10 +3223,10 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { } Tracks& TracksFor(LogicalAxis aAxis) { - return aAxis == eLogicalAxisBlock ? mRows : mCols; + return aAxis == LogicalAxis::Block ? mRows : mCols; } const Tracks& TracksFor(LogicalAxis aAxis) const { - return aAxis == eLogicalAxisBlock ? mRows : mCols; + return aAxis == LogicalAxis::Block ? mRows : mCols; } CSSOrderAwareFrameIterator mIter; @@ -3275,13 +3280,13 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { const nsStylePosition* aGridStyle, const WritingMode& aWM) : mIter(aFrame, FrameChildListID::Principal), mGridStyle(aGridStyle), - mCols(eLogicalAxisInline), - mRows(eLogicalAxisBlock), + mCols(LogicalAxis::Inline), + mRows(LogicalAxis::Block), mColFunctions(mGridStyle->mGridTemplateColumns, mGridStyle->mGridAutoColumns, - aFrame->IsSubgrid(eLogicalAxisInline)), + aFrame->IsSubgrid(LogicalAxis::Inline)), mRowFunctions(mGridStyle->mGridTemplateRows, mGridStyle->mGridAutoRows, - aFrame->IsSubgrid(eLogicalAxisBlock)), + aFrame->IsSubgrid(LogicalAxis::Block)), mReflowInput(aReflowInput), mRenderingContext(aRenderingContext), mFrame(aFrame), @@ -3299,8 +3304,8 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { mSkipSides = aFrame->PreReflowBlockLevelLogicalSkipSides(); mBorderPadding.ApplySkipSides(mSkipSides); } - mCols.mIsMasonry = aFrame->IsMasonry(eLogicalAxisInline); - mRows.mIsMasonry = aFrame->IsMasonry(eLogicalAxisBlock); + mCols.mIsMasonry = aFrame->IsMasonry(LogicalAxis::Inline); + mRows.mIsMasonry = aFrame->IsMasonry(LogicalAxis::Block); MOZ_ASSERT(!(mCols.mIsMasonry && mRows.mIsMasonry), "can't have masonry layout in both axes"); } @@ -3463,7 +3468,7 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::Grid { * @param aFromIndex the zero-based index to start counting from * @param aLineNameList the explicit named lines * @param aSide the axis+edge we're resolving names for (e.g. if we're - resolving a grid-row-start line, pass eLogicalSideBStart) + resolving a grid-row-start line, pass LogicalSide::BStart) * @param aExplicitGridEnd the last line in the explicit grid * @param aStyle the StylePosition() for the grid container * @return a definite line (1-based), clamped to @@ -3546,7 +3551,7 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::Grid { if (!mParentGrid) { return nullptr; } - bool isRows = aIsOrthogonal == (aAxis == eLogicalAxisInline); + bool isRows = aIsOrthogonal == (aAxis == LogicalAxis::Inline); return isRows ? mParentGrid->mRowNameMap : mParentGrid->mColNameMap; } @@ -3684,38 +3689,56 @@ static Subgrid* SubgridComputeMarginBorderPadding( SizeComputationInput sz(subgridFrame, nullptr, cbWM, pmPercentageBasis); subgrid->mMarginBorderPadding = sz.ComputedLogicalMargin(cbWM) + sz.ComputedLogicalBorderPadding(cbWM); + if (aGridItem.mFrame == subgridFrame) { + return subgrid; + } - if (aGridItem.mFrame != subgridFrame) { - nsHTMLScrollFrame* scrollFrame = - do_QueryFrame(aGridItem.mFrame->GetScrollTargetFrame()); - if (scrollFrame) { - MOZ_ASSERT( - sz.ComputedLogicalMargin(cbWM) == LogicalMargin(cbWM) && - sz.ComputedLogicalBorder(cbWM) == LogicalMargin(cbWM), - "A scrolled inner frame should not have any margin or border!"); - - // Add the margin and border from the (outer) scroll frame. - SizeComputationInput szScrollFrame(aGridItem.mFrame, nullptr, cbWM, - pmPercentageBasis); - subgrid->mMarginBorderPadding += - szScrollFrame.ComputedLogicalMargin(cbWM) + - szScrollFrame.ComputedLogicalBorder(cbWM); - - nsMargin ssz = scrollFrame->IntrinsicScrollbarGutterSize(); + bool scroller = false; + nsIFrame* outerFrame = [&]() -> nsIFrame* { + if (nsHTMLScrollFrame* scrollFrame = + do_QueryFrame(aGridItem.mFrame->GetScrollTargetFrame())) { + scroller = true; + return scrollFrame; + } + if (nsHTMLButtonControlFrame* f = do_QueryFrame(aGridItem.mFrame)) { + return f; + } + return nullptr; + }(); + + if (outerFrame) { + MOZ_ASSERT(sz.ComputedLogicalMargin(cbWM) == LogicalMargin(cbWM) && + sz.ComputedLogicalBorder(cbWM) == LogicalMargin(cbWM), + "A scrolled inner frame / button content frame " + "should not have any margin or border / padding!"); + + // Add the margin and border from the (outer) frame. Padding is factored-in + // for scrollers already (except for the scrollbar gutter), but not for + // button-content. + SizeComputationInput szOuterFrame(outerFrame, nullptr, cbWM, + pmPercentageBasis); + subgrid->mMarginBorderPadding += szOuterFrame.ComputedLogicalMargin(cbWM) + + szOuterFrame.ComputedLogicalBorder(cbWM); + if (scroller) { + nsMargin ssz = static_cast<nsHTMLScrollFrame*>(outerFrame) + ->IntrinsicScrollbarGutterSize(); subgrid->mMarginBorderPadding += LogicalMargin(cbWM, ssz); + } else { + subgrid->mMarginBorderPadding += + szOuterFrame.ComputedLogicalPadding(cbWM); } + } - if (aGridItem.mFrame->IsFieldSetFrame()) { - const auto* f = static_cast<nsFieldSetFrame*>(aGridItem.mFrame); - const auto* inner = f->GetInner(); - auto wm = inner->GetWritingMode(); - LogicalPoint pos = inner->GetLogicalPosition(aGridItem.mFrame->GetSize()); - // The legend is always on the BStart side and it inflates the fieldset's - // "border area" size. The inner frame's b-start pos equals that size. - LogicalMargin offsets(wm, pos.B(wm), 0, 0, 0); - subgrid->mMarginBorderPadding += offsets.ConvertTo(cbWM, wm); - } + if (nsFieldSetFrame* f = do_QueryFrame(aGridItem.mFrame)) { + const auto* inner = f->GetInner(); + auto wm = inner->GetWritingMode(); + LogicalPoint pos = inner->GetLogicalPosition(aGridItem.mFrame->GetSize()); + // The legend is always on the BStart side and it inflates the fieldset's + // "border area" size. The inner frame's b-start pos equals that size. + LogicalMargin offsets(wm, pos.B(wm), 0, 0, 0); + subgrid->mMarginBorderPadding += offsets.ConvertTo(cbWM, wm); } + return subgrid; } @@ -3727,8 +3750,9 @@ static void CopyUsedTrackSizes(nsTArray<TrackSize>& aResult, LogicalAxis aSubgridAxis) { MOZ_ASSERT(aSubgridFrame->ParentGridContainerForSubgrid() == aUsedTrackSizesFrame); - aResult.SetLength(aSubgridAxis == eLogicalAxisInline ? aSubgrid->mGridColEnd - : aSubgrid->mGridRowEnd); + aResult.SetLength(aSubgridAxis == LogicalAxis::Inline + ? aSubgrid->mGridColEnd + : aSubgrid->mGridRowEnd); auto parentAxis = aSubgrid->mIsOrthogonal ? GetOrthogonalAxis(aSubgridAxis) : aSubgridAxis; const auto& parentSizes = aUsedTrackSizes->mSizes[parentAxis]; @@ -3740,7 +3764,7 @@ static void CopyUsedTrackSizes(nsTArray<TrackSize>& aResult, const auto cbwm = aUsedTrackSizesFrame->GetWritingMode(); const auto wm = aSubgridFrame->GetWritingMode(); // Recompute the MBP to resolve percentages against the resolved track sizes. - if (parentAxis == eLogicalAxisInline) { + if (parentAxis == LogicalAxis::Inline) { // Find the subgrid's grid item frame in its parent grid container. This // is usually the same as aSubgridFrame but it may also have a ScrollFrame, // FieldSetFrame etc. We just loop until we see the first ancestor @@ -3856,7 +3880,7 @@ void nsGridContainerFrame::UsedTrackSizes::ResolveSubgridTrackSizesForAxis( grid.mGridRowEnd = aSubgrid->mGridRowEnd; state.CalculateTrackSizesForAxis(aAxis, grid, aContentBoxSize, SizingConstraint::NoConstraint); - const auto& tracks = aAxis == eLogicalAxisInline ? state.mCols : state.mRows; + const auto& tracks = aAxis == LogicalAxis::Inline ? state.mCols : state.mRows; mSizes[aAxis].Assign(tracks.mSizes); mCanResolveLineRangeSize[aAxis] = tracks.mCanResolveLineRangeSize; MOZ_ASSERT(mCanResolveLineRangeSize[aAxis]); @@ -3865,11 +3889,11 @@ void nsGridContainerFrame::UsedTrackSizes::ResolveSubgridTrackSizesForAxis( void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis( LogicalAxis aAxis, const Grid& aGrid, nscoord aContentBoxSize, SizingConstraint aConstraint) { - auto& tracks = aAxis == eLogicalAxisInline ? mCols : mRows; + auto& tracks = aAxis == LogicalAxis::Inline ? mCols : mRows; const auto& sizingFunctions = - aAxis == eLogicalAxisInline ? mColFunctions : mRowFunctions; - const auto& gapStyle = aAxis == eLogicalAxisInline ? mGridStyle->mColumnGap - : mGridStyle->mRowGap; + aAxis == LogicalAxis::Inline ? mColFunctions : mRowFunctions; + const auto& gapStyle = aAxis == LogicalAxis::Inline ? mGridStyle->mColumnGap + : mGridStyle->mRowGap; if (tracks.mIsMasonry) { // See comment on nsGridContainerFrame::MasonryLayout(). tracks.Initialize(sizingFunctions, gapStyle, 2, aContentBoxSize); @@ -3877,7 +3901,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis( return; } uint32_t gridEnd = - aAxis == eLogicalAxisInline ? aGrid.mGridColEnd : aGrid.mGridRowEnd; + aAxis == LogicalAxis::Inline ? aGrid.mGridColEnd : aGrid.mGridRowEnd; Maybe<TrackSizingFunctions> fallbackTrackSizing; bool useParentGaps = false; @@ -3919,7 +3943,7 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis( *this, mGridItems, fallbackTrackSizing ? *fallbackTrackSizing : sizingFunctions, aContentBoxSize, - aAxis == eLogicalAxisInline ? &GridArea::mCols : &GridArea::mRows, + aAxis == LogicalAxis::Inline ? &GridArea::mCols : &GridArea::mRows, aConstraint); if (hasSubgridItems && @@ -3976,9 +4000,9 @@ void nsGridContainerFrame::GridReflowInput::CalculateTrackSizesForAxis( void nsGridContainerFrame::GridReflowInput::CalculateTrackSizes( const Grid& aGrid, const LogicalSize& aContentBox, SizingConstraint aConstraint) { - CalculateTrackSizesForAxis(eLogicalAxisInline, aGrid, aContentBox.ISize(mWM), + CalculateTrackSizesForAxis(LogicalAxis::Inline, aGrid, aContentBox.ISize(mWM), aConstraint); - CalculateTrackSizesForAxis(eLogicalAxisBlock, aGrid, aContentBox.BSize(mWM), + CalculateTrackSizesForAxis(LogicalAxis::Block, aGrid, aContentBox.BSize(mWM), aConstraint); } @@ -3999,7 +4023,7 @@ static void AlignJustifySelf(StyleAlignFlags aAlignment, LogicalAxis aAxis, // Set the position (aPos) for the requested alignment. if (offset != 0) { WritingMode wm = aRI.GetWritingMode(); - nscoord& pos = aAxis == eLogicalAxisBlock ? aPos->B(wm) : aPos->I(wm); + nscoord& pos = aAxis == LogicalAxis::Block ? aPos->B(wm) : aPos->I(wm); pos += MOZ_LIKELY(aFlags & AlignJustifyFlags::SameSide) ? offset : -offset; } } @@ -4016,7 +4040,7 @@ static void AlignSelf(const nsGridContainerFrame::GridItemInfo& aGridItem, aAlignSelf &= ~StyleAlignFlags::FLAG_BITS; WritingMode childWM = aRI.GetWritingMode(); - if (aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisBlock, childWM)) { + if (aCBWM.ParallelAxisStartsOnSameSide(LogicalAxis::Block, childWM)) { flags |= AlignJustifyFlags::SameSide; } @@ -4032,12 +4056,12 @@ static void AlignSelf(const nsGridContainerFrame::GridItemInfo& aGridItem, nscoord baselineAdjust = 0; if (aAlignSelf == StyleAlignFlags::BASELINE || aAlignSelf == StyleAlignFlags::LAST_BASELINE) { - aAlignSelf = aGridItem.GetSelfBaseline(aAlignSelf, eLogicalAxisBlock, + aAlignSelf = aGridItem.GetSelfBaseline(aAlignSelf, LogicalAxis::Block, &baselineAdjust); } bool isOrthogonal = aCBWM.IsOrthogonalTo(childWM); - LogicalAxis axis = isOrthogonal ? eLogicalAxisInline : eLogicalAxisBlock; + LogicalAxis axis = isOrthogonal ? LogicalAxis::Inline : LogicalAxis::Block; AlignJustifySelf(aAlignSelf, axis, flags, baselineAdjust, aCBSize, aRI, aSize, aPos); } @@ -4054,7 +4078,7 @@ static void JustifySelf(const nsGridContainerFrame::GridItemInfo& aGridItem, aJustifySelf &= ~StyleAlignFlags::FLAG_BITS; WritingMode childWM = aRI.GetWritingMode(); - if (aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisInline, childWM)) { + if (aCBWM.ParallelAxisStartsOnSameSide(LogicalAxis::Inline, childWM)) { flags |= AlignJustifyFlags::SameSide; } @@ -4073,12 +4097,12 @@ static void JustifySelf(const nsGridContainerFrame::GridItemInfo& aGridItem, aCBWM.IsBidiLTR() ? StyleAlignFlags::END : StyleAlignFlags::START; } else if (aJustifySelf == StyleAlignFlags::BASELINE || aJustifySelf == StyleAlignFlags::LAST_BASELINE) { - aJustifySelf = aGridItem.GetSelfBaseline(aJustifySelf, eLogicalAxisInline, + aJustifySelf = aGridItem.GetSelfBaseline(aJustifySelf, LogicalAxis::Inline, &baselineAdjust); } bool isOrthogonal = aCBWM.IsOrthogonalTo(childWM); - LogicalAxis axis = isOrthogonal ? eLogicalAxisBlock : eLogicalAxisInline; + LogicalAxis axis = isOrthogonal ? LogicalAxis::Block : LogicalAxis::Inline; AlignJustifySelf(aJustifySelf, axis, flags, baselineAdjust, aCBSize, aRI, aSize, aPos); } @@ -4245,8 +4269,8 @@ void nsGridContainerFrame::InitImplicitNamedAreas( AddImplicitNamedAreas(aTemplate.AsSubgrid()->line_names.AsSpan()); } }; - Add(aStyle->mGridTemplateColumns, IsSubgrid(eLogicalAxisInline)); - Add(aStyle->mGridTemplateRows, IsSubgrid(eLogicalAxisBlock)); + Add(aStyle->mGridTemplateColumns, IsSubgrid(LogicalAxis::Inline)); + Add(aStyle->mGridTemplateRows, IsSubgrid(LogicalAxis::Block)); if (areas && areas->count() == 0) { RemoveProperty(ImplicitNamedAreasProperty()); } @@ -4485,10 +4509,10 @@ nsGridContainerFrame::GridArea nsGridContainerFrame::Grid::PlaceDefinite( const nsStylePosition* itemStyle = aChild->StylePosition(); return GridArea( ResolveLineRange(itemStyle->mGridColumnStart, itemStyle->mGridColumnEnd, - aColLineNameMap, eLogicalAxisInline, mExplicitGridColEnd, - aStyle), + aColLineNameMap, LogicalAxis::Inline, + mExplicitGridColEnd, aStyle), ResolveLineRange(itemStyle->mGridRowStart, itemStyle->mGridRowEnd, - aRowLineNameMap, eLogicalAxisBlock, mExplicitGridRowEnd, + aRowLineNameMap, LogicalAxis::Block, mExplicitGridRowEnd, aStyle)); } @@ -4548,11 +4572,11 @@ nsGridContainerFrame::GridArea nsGridContainerFrame::Grid::PlaceAbsPos( int32_t gridRowStart = 1 - mExplicitGridOffsetRow; return GridArea(ResolveAbsPosLineRange( itemStyle->mGridColumnStart, itemStyle->mGridColumnEnd, - aColLineNameMap, eLogicalAxisInline, mExplicitGridColEnd, + aColLineNameMap, LogicalAxis::Inline, mExplicitGridColEnd, gridColStart, mGridColEnd, aStyle), ResolveAbsPosLineRange( itemStyle->mGridRowStart, itemStyle->mGridRowEnd, - aRowLineNameMap, eLogicalAxisBlock, mExplicitGridRowEnd, + aRowLineNameMap, LogicalAxis::Block, mExplicitGridRowEnd, gridRowStart, mGridRowEnd, aStyle)); } @@ -4736,10 +4760,10 @@ void nsGridContainerFrame::Grid::SubgridPlaceGridItems( MOZ_ASSERT(aGridItem.mArea.IsDefinite() || aGridItem.mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW), "the subgrid's lines should be resolved by now"); - if (aGridItem.IsSubgrid(eLogicalAxisInline)) { + if (aGridItem.IsSubgrid(LogicalAxis::Inline)) { aParentState.mFrame->AddStateBits(NS_STATE_GRID_HAS_COL_SUBGRID_ITEM); } - if (aGridItem.IsSubgrid(eLogicalAxisBlock)) { + if (aGridItem.IsSubgrid(LogicalAxis::Block)) { aParentState.mFrame->AddStateBits(NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM); } auto* childGrid = aGridItem.SubgridFrame(); @@ -4787,11 +4811,11 @@ void nsGridContainerFrame::Grid::SubgridPlaceGridItems( // computing them otherwise. RepeatTrackSizingInput repeatSizing(state.mWM); if (!childGrid->IsColSubgrid() && state.mColFunctions.mHasRepeatAuto) { - repeatSizing.InitFromStyle(eLogicalAxisInline, state.mWM, + repeatSizing.InitFromStyle(LogicalAxis::Inline, state.mWM, state.mFrame->Style()); } if (!childGrid->IsRowSubgrid() && state.mRowFunctions.mHasRepeatAuto) { - repeatSizing.InitFromStyle(eLogicalAxisBlock, state.mWM, + repeatSizing.InitFromStyle(LogicalAxis::Block, state.mWM, state.mFrame->Style()); } @@ -4812,8 +4836,8 @@ void nsGridContainerFrame::Grid::PlaceGridItems( if (aState.mFrame->HasSubgridItems() || aState.mFrame->IsSubgrid()) { if (auto* uts = aState.mFrame->GetUsedTrackSizes()) { uts->mCanResolveLineRangeSize = {false, false}; - uts->mSizes[eLogicalAxisInline].ClearAndRetainStorage(); - uts->mSizes[eLogicalAxisBlock].ClearAndRetainStorage(); + uts->mSizes[LogicalAxis::Inline].ClearAndRetainStorage(); + uts->mSizes[LogicalAxis::Block].ClearAndRetainStorage(); } } @@ -4847,11 +4871,11 @@ void nsGridContainerFrame::Grid::PlaceGridItems( uint32_t extent = subgridRange->Extent(); mExplicitGridColEnd = extent + 1; // the grid is 1-based at this point parentLineNameMap = - ParentLineMapForAxis(subgrid->mIsOrthogonal, eLogicalAxisInline); + ParentLineMapForAxis(subgrid->mIsOrthogonal, LogicalAxis::Inline); auto parentWM = aState.mFrame->ParentGridContainerForSubgrid()->GetWritingMode(); subgridAxisIsSameDirection = - aState.mWM.ParallelAxisStartsOnSameSide(eLogicalAxisInline, parentWM); + aState.mWM.ParallelAxisStartsOnSameSide(LogicalAxis::Inline, parentWM); } mGridColEnd = mExplicitGridColEnd; LineNameMap colLineNameMap(gridStyle, mAreas, aState.mColFunctions, @@ -4882,11 +4906,11 @@ void nsGridContainerFrame::Grid::PlaceGridItems( uint32_t extent = subgridRange->Extent(); mExplicitGridRowEnd = extent + 1; // the grid is 1-based at this point parentLineNameMap = - ParentLineMapForAxis(subgrid->mIsOrthogonal, eLogicalAxisBlock); + ParentLineMapForAxis(subgrid->mIsOrthogonal, LogicalAxis::Block); auto parentWM = aState.mFrame->ParentGridContainerForSubgrid()->GetWritingMode(); subgridAxisIsSameDirection = - aState.mWM.ParallelAxisStartsOnSameSide(eLogicalAxisBlock, parentWM); + aState.mWM.ParallelAxisStartsOnSameSide(LogicalAxis::Block, parentWM); } mGridRowEnd = mExplicitGridRowEnd; LineNameMap rowLineNameMap(gridStyle, mAreas, aState.mRowFunctions, @@ -4900,16 +4924,16 @@ void nsGridContainerFrame::Grid::PlaceGridItems( if (isSubgridOrItemInSubgrid) { const auto& area = aItem.mArea; if (area.mCols.mStart == 0) { - aItem.mState[eLogicalAxisInline] |= ItemState::eStartEdge; + aItem.mState[LogicalAxis::Inline] |= ItemState::eStartEdge; } if (area.mCols.mEnd == mGridColEnd) { - aItem.mState[eLogicalAxisInline] |= ItemState::eEndEdge; + aItem.mState[LogicalAxis::Inline] |= ItemState::eEndEdge; } if (area.mRows.mStart == 0) { - aItem.mState[eLogicalAxisBlock] |= ItemState::eStartEdge; + aItem.mState[LogicalAxis::Block] |= ItemState::eStartEdge; } if (area.mRows.mEnd == mGridRowEnd) { - aItem.mState[eLogicalAxisBlock] |= ItemState::eEndEdge; + aItem.mState[LogicalAxis::Block] |= ItemState::eEndEdge; } } }; @@ -4945,8 +4969,8 @@ void nsGridContainerFrame::Grid::PlaceGridItems( aState.mRowFunctions.mExplicitGridOffset = mExplicitGridOffsetRow; const int32_t offsetToColZero = int32_t(mExplicitGridOffsetCol) - 1; const int32_t offsetToRowZero = int32_t(mExplicitGridOffsetRow) - 1; - const bool isRowMasonry = aState.mFrame->IsMasonry(eLogicalAxisBlock); - const bool isColMasonry = aState.mFrame->IsMasonry(eLogicalAxisInline); + const bool isRowMasonry = aState.mFrame->IsMasonry(LogicalAxis::Block); + const bool isColMasonry = aState.mFrame->IsMasonry(LogicalAxis::Inline); const bool isMasonry = isColMasonry || isRowMasonry; mGridColEnd += offsetToColZero; mGridRowEnd += offsetToRowZero; @@ -5100,7 +5124,7 @@ void nsGridContainerFrame::Grid::PlaceGridItems( // Force all items into the 1st/2nd track and have span 1 in the masonry axis. // (See comment on nsGridContainerFrame::MasonryLayout().) if (isMasonry) { - auto masonryAxis = isRowMasonry ? eLogicalAxisBlock : eLogicalAxisInline; + auto masonryAxis = isRowMasonry ? LogicalAxis::Block : LogicalAxis::Inline; aState.mIter.Reset(); for (; !aState.mIter.AtEnd(); aState.mIter.Next()) { auto& item = aState.mGridItems[aState.mIter.ItemIndex()]; @@ -5168,16 +5192,16 @@ void nsGridContainerFrame::Grid::PlaceGridItems( // An abs.pos. subgrid with placement auto/1 or -1/auto technically // doesn't span any parent tracks. Inhibit subgridding in this case. - if (info->IsSubgrid(eLogicalAxisInline)) { + if (info->IsSubgrid(LogicalAxis::Inline)) { if (info->mArea.mCols.mStart == zeroOffsetGridColEnd.SavedValue() || info->mArea.mCols.mEnd == 0) { - info->InhibitSubgrid(aState.mFrame, eLogicalAxisInline); + info->InhibitSubgrid(aState.mFrame, LogicalAxis::Inline); } } - if (info->IsSubgrid(eLogicalAxisBlock)) { + if (info->IsSubgrid(LogicalAxis::Block)) { if (info->mArea.mRows.mStart == zeroOffsetGridRowEnd.SavedValue() || info->mArea.mRows.mEnd == 0) { - info->InhibitSubgrid(aState.mFrame, eLogicalAxisBlock); + info->InhibitSubgrid(aState.mFrame, LogicalAxis::Block); } } @@ -5219,18 +5243,18 @@ void nsGridContainerFrame::Grid::PlaceGridItems( // Adjust the line numbers in the grid areas. for (auto& item : aState.mGridItems) { if (numEmptyCols) { - item.AdjustForRemovedTracks(eLogicalAxisInline, *colAdjust); + item.AdjustForRemovedTracks(LogicalAxis::Inline, *colAdjust); } if (numEmptyRows) { - item.AdjustForRemovedTracks(eLogicalAxisBlock, *rowAdjust); + item.AdjustForRemovedTracks(LogicalAxis::Block, *rowAdjust); } } for (auto& item : aState.mAbsPosItems) { if (numEmptyCols) { - item.AdjustForRemovedTracks(eLogicalAxisInline, *colAdjust); + item.AdjustForRemovedTracks(LogicalAxis::Inline, *colAdjust); } if (numEmptyRows) { - item.AdjustForRemovedTracks(eLogicalAxisBlock, *rowAdjust); + item.AdjustForRemovedTracks(LogicalAxis::Block, *rowAdjust); } } // Adjust the grid size. @@ -5258,11 +5282,11 @@ void nsGridContainerFrame::Grid::PlaceGridItems( LineRange columnLines = ResolveLineRange(lineStartAndEnd, lineStartAndEnd, colLineNameMap, - eLogicalAxisInline, mExplicitGridColEnd, gridStyle); + LogicalAxis::Inline, mExplicitGridColEnd, gridStyle); LineRange rowLines = ResolveLineRange(lineStartAndEnd, lineStartAndEnd, rowLineNameMap, - eLogicalAxisBlock, mExplicitGridRowEnd, gridStyle); + LogicalAxis::Block, mExplicitGridRowEnd, gridStyle); // Put the resolved line indices back into the area structure. areaInfo.columns.start = columnLines.mStart + mExplicitGridOffsetCol; @@ -5322,7 +5346,7 @@ static nscoord MeasuringReflow(nsIFrame* aChild, ComputeSizeFlags csFlags = ComputeSizeFlag::IsGridMeasuringReflow; // Shrink-wrap grid items that will be aligned (rather than stretched) in // their own inline axis. - if (!parent->GridItemShouldStretch(aChild, eLogicalAxisInline)) { + if (!parent->GridItemShouldStretch(aChild, LogicalAxis::Inline)) { csFlags += ComputeSizeFlag::ShrinkWrap; } if (aAvailableSize.ISize(wm) == INFINITE_ISIZE_COORD) { @@ -5434,7 +5458,7 @@ static void PostReflowStretchChild( } ReflowInput ri(pc, aReflowInput, aChild, aAvailableSize, Some(aCBSize), {}, {}, csFlags); - if (aChildAxis == eLogicalAxisBlock) { + if (aChildAxis == LogicalAxis::Block) { ri.SetComputedBSize(ri.ApplyMinMaxBSize(aNewContentBoxSize)); } else { ri.SetComputedISize(ri.ApplyMinMaxISize(aNewContentBoxSize)); @@ -5542,18 +5566,18 @@ static nscoord ContentContribution( auto subgridAxis = aCBWM.IsOrthogonalTo(subgridFrame->GetWritingMode()) ? GetOrthogonalAxis(aAxis) : aAxis; - auto& gapStyle = subgridAxis == eLogicalAxisBlock + auto& gapStyle = subgridAxis == LogicalAxis::Block ? subgridFrame->StylePosition()->mRowGap : subgridFrame->StylePosition()->mColumnGap; if (!gapStyle.IsNormal()) { - auto subgridExtent = subgridAxis == eLogicalAxisBlock + auto subgridExtent = subgridAxis == LogicalAxis::Block ? subgrid->mGridRowEnd : subgrid->mGridColEnd; if (subgridExtent > 1) { nscoord subgridGap = nsLayoutUtils::ResolveGapToLength(gapStyle, NS_UNCONSTRAINEDSIZE); auto& tracks = - aAxis == eLogicalAxisBlock ? aState.mRows : aState.mCols; + aAxis == LogicalAxis::Block ? aState.mRows : aState.mCols; auto gapDelta = subgridGap - tracks.mGridGap; if (!itemEdgeBits) { extraMargin += gapDelta; @@ -5572,7 +5596,7 @@ static nscoord ContentContribution( auto childWM = child->GetWritingMode(); const bool isOrthogonal = childWM.IsOrthogonalTo(aCBWM); auto childAxis = isOrthogonal ? GetOrthogonalAxis(aAxis) : aAxis; - if (size == NS_INTRINSIC_ISIZE_UNKNOWN && childAxis == eLogicalAxisBlock) { + if (size == NS_INTRINSIC_ISIZE_UNKNOWN && childAxis == LogicalAxis::Block) { // We need to reflow the child to find its BSize contribution. // XXX this will give mostly correct results for now (until bug 1174569). nscoord availISize = INFINITE_ISIZE_COORD; @@ -5595,8 +5619,8 @@ static nscoord ContentContribution( } // The grid-item's inline-axis as expressed in the subgrid's WM. auto subgridAxis = childWM.IsOrthogonalTo(subgridFrame->GetWritingMode()) - ? eLogicalAxisBlock - : eLogicalAxisInline; + ? LogicalAxis::Block + : LogicalAxis::Inline; uts->ResolveTrackSizesForAxis(subgridFrame, subgridAxis, *aRC); if (uts->mCanResolveLineRangeSize[subgridAxis]) { auto* subgrid = @@ -5642,7 +5666,7 @@ static nscoord ContentContribution( } } } - if (isOrthogonal == (aAxis == eLogicalAxisInline)) { + if (isOrthogonal == (aAxis == LogicalAxis::Inline)) { bMinSizeClamp = aMinSizeClamp; } else { iMinSizeClamp = aMinSizeClamp; @@ -5739,7 +5763,8 @@ static nscoord MinSize(const GridItemInfo& aGridItem, StyleSize sizeStyle = axis == eAxisHorizontal ? stylePos->mWidth : stylePos->mHeight; - auto ourInlineAxis = child->GetWritingMode().PhysicalAxis(eLogicalAxisInline); + auto ourInlineAxis = + child->GetWritingMode().PhysicalAxis(LogicalAxis::Inline); // max-content and min-content should behave as initial value in block axis. // FIXME: Bug 567039: moz-fit-content and -moz-available are not supported // for block size dimension on sizing properties (e.g. height), so we @@ -6006,7 +6031,7 @@ void nsGridContainerFrame::Tracks::InitializeItemBaselines( const auto childWM = child->GetWritingMode(); const bool isOrthogonal = containerWM.IsOrthogonalTo(childWM); - const bool isInlineAxis = mAxis == eLogicalAxisInline; // i.e. columns + const bool isInlineAxis = mAxis == LogicalAxis::Inline; // i.e. columns // XXX update the line below to include orthogonal grid/table boxes // XXX since they have baselines in both dimensions. And flexbox with @@ -6281,7 +6306,7 @@ void nsGridContainerFrame::Tracks::InitializeItemBaselinesInMasonryAxis( auto state = ItemState(0); auto childWM = child->GetWritingMode(); const bool isOrthogonal = wm.IsOrthogonalTo(childWM); - const bool isInlineAxis = mAxis == eLogicalAxisInline; // i.e. columns + const bool isInlineAxis = mAxis == LogicalAxis::Inline; // i.e. columns // XXX update the line below to include orthogonal grid/table boxes // XXX since they have baselines in both dimensions. And flexbox with // XXX reversed main/cross axis? @@ -6449,10 +6474,10 @@ void nsGridContainerFrame::Tracks::AlignBaselineSubtree( const bool isFirstBaseline = state & ItemState::eFirstBaseline; if (isFirstBaseline) { baselineTrack = - mAxis == eLogicalAxisBlock ? area.mRows.mStart : area.mCols.mStart; + mAxis == LogicalAxis::Block ? area.mRows.mStart : area.mCols.mStart; } else { baselineTrack = - (mAxis == eLogicalAxisBlock ? area.mRows.mEnd : area.mCols.mEnd) - 1; + (mAxis == LogicalAxis::Block ? area.mRows.mEnd : area.mCols.mEnd) - 1; } const TrackSize& sz = mSizes[baselineTrack]; auto baselineGroup = isFirstBaseline ? BaselineSharingGroup::First @@ -6855,7 +6880,7 @@ float nsGridContainerFrame::Tracks::FindUsedFlexFraction( nscoord spaceToFill = ContentContribution(item, aState, rc, wm, mAxis, pb, IntrinsicISizeType::PrefISize); const LineRange& range = - mAxis == eLogicalAxisInline ? item.mArea.mCols : item.mArea.mRows; + mAxis == LogicalAxis::Inline ? item.mArea.mCols : item.mArea.mRows; MOZ_ASSERT(range.Extent() >= 1); const auto spannedGaps = range.Extent() - 1; if (spannedGaps > 0) { @@ -6898,10 +6923,10 @@ void nsGridContainerFrame::Tracks::StretchFlexibleTracks( nscoord maxSize = NS_UNCONSTRAINEDSIZE; if (aState.mReflowInput) { auto* ri = aState.mReflowInput; - minSize = mAxis == eLogicalAxisBlock ? ri->ComputedMinBSize() - : ri->ComputedMinISize(); - maxSize = mAxis == eLogicalAxisBlock ? ri->ComputedMaxBSize() - : ri->ComputedMaxISize(); + minSize = mAxis == LogicalAxis::Block ? ri->ComputedMinBSize() + : ri->ComputedMinISize(); + maxSize = mAxis == LogicalAxis::Block ? ri->ComputedMaxBSize() + : ri->ComputedMaxISize(); } Maybe<CopyableAutoTArray<TrackSize, 32>> origSizes; bool applyMinMax = (minSize != 0 || maxSize != NS_UNCONSTRAINEDSIZE) && @@ -6958,7 +6983,7 @@ void nsGridContainerFrame::Tracks::StretchFlexibleTracks( void nsGridContainerFrame::Tracks::AlignJustifyContent( const nsStylePosition* aStyle, StyleContentDistribution aAligmentStyleValue, WritingMode aWM, nscoord aContentBoxSize, bool aIsSubgriddedAxis) { - const bool isAlign = mAxis == eLogicalAxisBlock; + const bool isAlign = mAxis == LogicalAxis::Block; // Align-/justify-content doesn't apply in a subgridded axis. // Gap properties do apply though so we need to stretch/position the tracks // to center-align the gaps with the parent's gaps. @@ -7223,25 +7248,25 @@ LogicalSize nsGridContainerFrame::GridReflowInput::PercentageBasisFor( if (auto* uts = subgridFrame->GetUsedTrackSizes()) { auto subgridWM = subgridFrame->GetWritingMode(); LogicalSize cbSize(subgridWM, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - if (!subgridFrame->IsSubgrid(eLogicalAxisInline) && - uts->mCanResolveLineRangeSize[eLogicalAxisInline]) { + if (!subgridFrame->IsSubgrid(LogicalAxis::Inline) && + uts->mCanResolveLineRangeSize[LogicalAxis::Inline]) { // NOTE: At this point aGridItem.mArea is in this->mFrame coordinates // and thus may have been transposed. The range values in a non- // subgridded axis still has its original values in subgridFrame's // coordinates though. - auto rangeAxis = subgridWM.IsOrthogonalTo(mWM) ? eLogicalAxisBlock - : eLogicalAxisInline; + auto rangeAxis = subgridWM.IsOrthogonalTo(mWM) ? LogicalAxis::Block + : LogicalAxis::Inline; const auto& range = aGridItem.mArea.LineRangeForAxis(rangeAxis); cbSize.ISize(subgridWM) = - range.ToLength(uts->mSizes[eLogicalAxisInline]); + range.ToLength(uts->mSizes[LogicalAxis::Inline]); } - if (!subgridFrame->IsSubgrid(eLogicalAxisBlock) && - uts->mCanResolveLineRangeSize[eLogicalAxisBlock]) { - auto rangeAxis = subgridWM.IsOrthogonalTo(mWM) ? eLogicalAxisInline - : eLogicalAxisBlock; + if (!subgridFrame->IsSubgrid(LogicalAxis::Block) && + uts->mCanResolveLineRangeSize[LogicalAxis::Block]) { + auto rangeAxis = subgridWM.IsOrthogonalTo(mWM) ? LogicalAxis::Inline + : LogicalAxis::Block; const auto& range = aGridItem.mArea.LineRangeForAxis(rangeAxis); cbSize.BSize(subgridWM) = - range.ToLength(uts->mSizes[eLogicalAxisBlock]); + range.ToLength(uts->mSizes[LogicalAxis::Block]); } return cbSize.ConvertTo(wm, subgridWM); } @@ -7249,7 +7274,7 @@ LogicalSize nsGridContainerFrame::GridReflowInput::PercentageBasisFor( return LogicalSize(wm, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); } - if (aAxis == eLogicalAxisInline || !mCols.mCanResolveLineRangeSize) { + if (aAxis == LogicalAxis::Inline || !mCols.mCanResolveLineRangeSize) { return LogicalSize(wm, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); } // Note: for now, we only resolve transferred percentages to row sizing. @@ -7428,7 +7453,7 @@ void nsGridContainerFrame::GridReflowInput::AlignJustifyTracksInMasonryAxis( ContainingBlockFor(item->mArea).Size(wm).ConvertTo(childWM, wm); LogicalSize availableSize = cb; cb.Size(masonryChildAxis, childWM) = alignmentContainerSize; - availableSize.Size(eLogicalAxisBlock, childWM) = + availableSize.Size(LogicalAxis::Block, childWM) = NS_UNCONSTRAINEDSIZE; const auto& bp = child->GetLogicalUsedBorderAndPadding(childWM); newSize -= bp.StartEnd(masonryChildAxis, childWM); @@ -7626,9 +7651,9 @@ void nsGridContainerFrame::ReflowInFlowChild( aChild->RemoveProperty(aProp); } }; - SetProp(eLogicalAxisBlock, + SetProp(LogicalAxis::Block, isOrthogonal ? IBaselinePadProperty() : BBaselinePadProperty()); - SetProp(eLogicalAxisInline, + SetProp(LogicalAxis::Inline, isOrthogonal ? BBaselinePadProperty() : IBaselinePadProperty()); } else { // By convention, for frames that perform CSS Box Alignment, we position @@ -7654,9 +7679,9 @@ void nsGridContainerFrame::ReflowInFlowChild( ComputeSizeFlags csFlags; if (aGridItemInfo) { const auto childIAxisInWM = - isOrthogonal ? eLogicalAxisBlock : eLogicalAxisInline; + isOrthogonal ? LogicalAxis::Block : LogicalAxis::Inline; // Clamp during reflow if we're stretching in that axis. - if (GridItemShouldStretch(aChild, eLogicalAxisInline)) { + if (GridItemShouldStretch(aChild, LogicalAxis::Inline)) { if (aGridItemInfo->mState[childIAxisInWM] & ItemState::eClampMarginBoxMinSize) { csFlags += ComputeSizeFlag::IClampMarginBoxMinSize; @@ -7666,7 +7691,7 @@ void nsGridContainerFrame::ReflowInFlowChild( } const auto childBAxisInWM = GetOrthogonalAxis(childIAxisInWM); - if (GridItemShouldStretch(aChild, eLogicalAxisBlock) && + if (GridItemShouldStretch(aChild, LogicalAxis::Block) && aGridItemInfo->mState[childBAxisInWM] & ItemState::eClampMarginBoxMinSize) { csFlags += ComputeSizeFlag::BClampMarginBoxMinSize; @@ -7702,7 +7727,7 @@ void nsGridContainerFrame::ReflowInFlowChild( // nsBlockFrame::ComputeFinalSize the size. if (isConstrainedBSize && !wm.IsOrthogonalTo(childWM)) { const bool stretch = childRI.mStylePosition->BSize(childWM).IsAuto() && - GridItemShouldStretch(aChild, eLogicalAxisBlock); + GridItemShouldStretch(aChild, LogicalAxis::Block); if (stretch) { aChild->SetProperty(FragStretchBSizeProperty(), *aStretchBSize); } else { @@ -7750,7 +7775,7 @@ void nsGridContainerFrame::ReflowInFlowChild( ? StyleAlignFlags::SELF_START : StyleAlignFlags::SELF_END}; } - if (aAxis == eLogicalAxisBlock) { + if (aAxis == LogicalAxis::Block) { AlignSelf(*aGridItemInfo, align, aCBSize, wm, childRI, size, flags, &childPos); } else { @@ -7759,10 +7784,10 @@ void nsGridContainerFrame::ReflowInFlowChild( } }; if (aStatus.IsComplete()) { - applyItemSelfAlignment(eLogicalAxisBlock, + applyItemSelfAlignment(LogicalAxis::Block, cb.BSize(wm) - consumedGridAreaBSize); } - applyItemSelfAlignment(eLogicalAxisInline, cb.ISize(wm)); + applyItemSelfAlignment(LogicalAxis::Inline, cb.ISize(wm)); } // else, nsAbsoluteContainingBlock.cpp will handle align/justify-self. FinishReflowChild(aChild, pc, childSize, &childRI, childWM, childPos, @@ -8006,7 +8031,7 @@ nscoord nsGridContainerFrame::ReflowRowsInFragmentainer( const auto rowCount = aState.mRows.mSizes.Length(); nscoord masonryAxisGap; const auto wm = aState.mWM; - const bool isColMasonry = IsMasonry(eLogicalAxisInline); + const bool isColMasonry = IsMasonry(LogicalAxis::Inline); if (isColMasonry) { for (auto& sz : aState.mCols.mSizes) { sz.mPosition = 0; @@ -8174,15 +8199,15 @@ nscoord nsGridContainerFrame::ReflowRowsInFragmentainer( } if (isColMasonry) { auto childWM = child->GetWritingMode(); - auto childAxis = - !childWM.IsOrthogonalTo(wm) ? eLogicalAxisInline : eLogicalAxisBlock; + auto childAxis = !childWM.IsOrthogonalTo(wm) ? LogicalAxis::Inline + : LogicalAxis::Block; auto normalPos = child->GetLogicalNormalPosition(wm, aContainerSize); auto sz = - childAxis == eLogicalAxisBlock ? child->BSize() : child->ISize(); - auto pos = normalPos.Pos(eLogicalAxisInline, wm) + sz + + childAxis == LogicalAxis::Block ? child->BSize() : child->ISize(); + auto pos = normalPos.Pos(LogicalAxis::Inline, wm) + sz + child->GetLogicalUsedMargin(childWM).End(childAxis, childWM); masonryAxisPos.ref()[row] = - pos + masonryAxisGap - aContentArea.Start(eLogicalAxisInline, wm); + pos + masonryAxisGap - aContentArea.Start(LogicalAxis::Inline, wm); } } @@ -8281,7 +8306,7 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState, aState.mIter.Reset(CSSOrderAwareFrameIterator::ChildFilter::IncludeAll); size_t absposIndex = 0; const LogicalAxis masonryAxis = - IsMasonry(eLogicalAxisBlock) ? eLogicalAxisBlock : eLogicalAxisInline; + IsMasonry(LogicalAxis::Block) ? LogicalAxis::Block : LogicalAxis::Inline; const auto wm = aState.mWM; for (; !aState.mIter.AtEnd(); aState.mIter.Next()) { nsIFrame* child = *aState.mIter; @@ -8323,7 +8348,7 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState, const auto masonryAutoFlow = aState.mGridStyle->mMasonryAutoFlow; const bool definiteFirst = masonryAutoFlow.order == StyleMasonryItemOrder::DefiniteFirst; - if (masonryAxis == eLogicalAxisBlock) { + if (masonryAxis == LogicalAxis::Block) { std::stable_sort(sortedItems.begin(), sortedItems.end(), definiteFirst ? GridItemInfo::RowMasonryDefiniteFirst : GridItemInfo::RowMasonryOrdered); @@ -8366,8 +8391,8 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState, lastItems.SetLength(gridAxisTrackCount); PodZero(lastItems.Elements(), gridAxisTrackCount); const nscoord gap = nsLayoutUtils::ResolveGapToLength( - masonryAxis == eLogicalAxisBlock ? aState.mGridStyle->mRowGap - : aState.mGridStyle->mColumnGap, + masonryAxis == LogicalAxis::Block ? aState.mGridStyle->mRowGap + : aState.mGridStyle->mColumnGap, masonryTracks.mContentBoxSize); masonryTracks.mGridGap = gap; uint32_t cursor = 0; @@ -8495,7 +8520,7 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState, auto childAxis = !childWM.IsOrthogonalTo(wm) ? masonryAxis : gridAxis; auto normalPos = aChild->GetLogicalNormalPosition(wm, aContainerSize); auto sz = - childAxis == eLogicalAxisBlock ? aChild->BSize() : aChild->ISize(); + childAxis == LogicalAxis::Block ? aChild->BSize() : aChild->ISize(); return containerToMasonryBoxOffset + normalPos.Pos(masonryAxis, wm) + sz + aChild->GetLogicalUsedMargin(childWM).End(childAxis, childWM); }; @@ -8668,7 +8693,7 @@ nscoord nsGridContainerFrame::MasonryLayout(GridReflowInput& aState, consumeAllSpace ? toFragmentainerEnd : offsetToMarginBoxEnd(child); } else { LogicalSize percentBasis( - aState.PercentageBasisFor(eLogicalAxisInline, *item)); + aState.PercentageBasisFor(LogicalAxis::Inline, *item)); IntrinsicISizeType type = aConstraint == SizingConstraint::MaxContent ? IntrinsicISizeType::PrefISize : IntrinsicISizeType::MinISize; @@ -8775,19 +8800,19 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aState, // so we let ReflowInFragmentainer() deal with grid-axis fragmentation // in the else-clause below. if (IsMasonry() && - !(IsMasonry(eLogicalAxisInline) && fragmentainer.isSome())) { + !(IsMasonry(LogicalAxis::Inline) && fragmentainer.isSome())) { aState.mInFragmentainer = fragmentainer.isSome(); nscoord sz = MasonryLayout( aState, aContentArea, SizingConstraint::NoConstraint, aDesiredSize, aStatus, fragmentainer.ptrOr(nullptr), aContainerSize); - if (IsMasonry(eLogicalAxisBlock)) { + if (IsMasonry(LogicalAxis::Block)) { bSize = aState.mReflowInput->ComputedBSize(); if (bSize == NS_UNCONSTRAINEDSIZE) { bSize = aState.mReflowInput->ApplyMinMaxBSize(sz); } } } else if (MOZ_UNLIKELY(fragmentainer.isSome())) { - if (IsMasonry(eLogicalAxisInline) && !GetPrevInFlow()) { + if (IsMasonry(LogicalAxis::Inline) && !GetPrevInFlow()) { // First we do an unconstrained reflow to resolve the item placement // which is then kept as-is in the constrained reflow below. MasonryLayout(aState, aContentArea, SizingConstraint::NoConstraint, @@ -8804,10 +8829,12 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aState, if (!child->IsPlaceholderFrame()) { info = &aState.mGridItems[aState.mIter.ItemIndex()]; } + nsReflowStatus childStatus; ReflowInFlowChild(child, info, aContainerSize, Nothing(), nullptr, aState, - aContentArea, aDesiredSize, aStatus); - MOZ_ASSERT(aStatus.IsComplete(), + aContentArea, aDesiredSize, childStatus); + MOZ_ASSERT(childStatus.IsComplete(), "child should be complete in unconstrained reflow"); + aStatus.MergeCompletionStatusFrom(childStatus); } } @@ -8868,7 +8895,6 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsGridContainerFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); if (IsFrameTreeTooDeep(aReflowInput, aDesiredSize, aStatus)) { @@ -8952,11 +8978,11 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, if (containBSize) { bSize = *containBSize; } else { - if (IsMasonry(eLogicalAxisBlock)) { + if (IsMasonry(LogicalAxis::Block)) { bSize = computedBSize; } else { const auto& rowSizes = gridReflowInput.mRows.mSizes; - if (MOZ_LIKELY(!IsSubgrid(eLogicalAxisBlock))) { + if (MOZ_LIKELY(!IsSubgrid(LogicalAxis::Block))) { // Note: we can't use GridLineEdge here since we haven't calculated // the rows' mPosition yet (happens in AlignJustifyContent below). for (const auto& sz : rowSizes) { @@ -9025,7 +9051,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, } // Save the final row sizes for use by subgrids, if needed. if (HasSubgridItems() || IsSubgrid()) { - StoreUsedTrackSizes(eLogicalAxisBlock, rowSizes); + StoreUsedTrackSizes(LogicalAxis::Block, rowSizes); } } @@ -9122,8 +9148,8 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, } // TODO: fix align-tracks alignment in fragments - if ((IsMasonry(eLogicalAxisBlock) && !prevInFlow) || - IsMasonry(eLogicalAxisInline)) { + if ((IsMasonry(LogicalAxis::Block) && !prevInFlow) || + IsMasonry(LogicalAxis::Inline)) { gridReflowInput.AlignJustifyTracksInMasonryAxis( contentArea.Size(wm), aDesiredSize.PhysicalSize()); } @@ -9221,7 +9247,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, // the ComputedGridTrackInfo and related properties const auto* subgrid = GetProperty(Subgrid::Prop()); - const auto* subgridColRange = subgrid && IsSubgrid(eLogicalAxisInline) + const auto* subgridColRange = subgrid && IsSubgrid(LogicalAxis::Inline) ? &subgrid->SubgridCols() : nullptr; @@ -9252,7 +9278,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, // taken by rvalue, but computing the size first prevents any changes in the // argument types of the constructor from breaking this. const uint32_t numColExplicitTracks = - IsSubgrid(eLogicalAxisInline) + IsSubgrid(LogicalAxis::Inline) ? colTrackSizes.Length() : gridReflowInput.mColFunctions.NumExplicitTracks(); ComputedGridTrackInfo* colInfo = new ComputedGridTrackInfo( @@ -9261,10 +9287,10 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, std::move(colTrackStates), std::move(colRemovedRepeatTracks), gridReflowInput.mColFunctions.mRepeatAutoStart, colLineNameMap.GetResolvedLineNamesForComputedGridTrackInfo(), - IsSubgrid(eLogicalAxisInline), IsMasonry(eLogicalAxisInline)); + IsSubgrid(LogicalAxis::Inline), IsMasonry(LogicalAxis::Inline)); SetProperty(GridColTrackInfo(), colInfo); - const auto* subgridRowRange = subgrid && IsSubgrid(eLogicalAxisBlock) + const auto* subgridRowRange = subgrid && IsSubgrid(LogicalAxis::Block) ? &subgrid->SubgridRows() : nullptr; LineNameMap rowLineNameMap( @@ -9294,7 +9320,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, // taken by rvalue, but computing the size first prevents any changes in the // argument types of the constructor from breaking this. const uint32_t numRowExplicitTracks = - IsSubgrid(eLogicalAxisBlock) + IsSubgrid(LogicalAxis::Block) ? rowTrackSizes.Length() : gridReflowInput.mRowFunctions.NumExplicitTracks(); // Row info has to accommodate fragmentation of the grid, which may happen @@ -9307,7 +9333,7 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext, std::move(rowRemovedRepeatTracks), gridReflowInput.mRowFunctions.mRepeatAutoStart, rowLineNameMap.GetResolvedLineNamesForComputedGridTrackInfo(), - IsSubgrid(eLogicalAxisBlock), IsMasonry(eLogicalAxisBlock)); + IsSubgrid(LogicalAxis::Block), IsMasonry(LogicalAxis::Block)); SetProperty(GridRowTrackInfo(), rowInfo); if (prevInFlow) { @@ -9613,16 +9639,16 @@ nscoord nsGridContainerFrame::IntrinsicISize(gfxContext* aRenderingContext, // They're only used for auto-repeat so we skip computing them otherwise. RepeatTrackSizingInput repeatSizing(state.mWM); if (!IsColSubgrid() && state.mColFunctions.mHasRepeatAuto) { - repeatSizing.InitFromStyle(eLogicalAxisInline, state.mWM, + repeatSizing.InitFromStyle(LogicalAxis::Inline, state.mWM, state.mFrame->Style()); } if ((!IsRowSubgrid() && state.mRowFunctions.mHasRepeatAuto && !(state.mGridStyle->mGridAutoFlow & StyleGridAutoFlow::ROW)) || - IsMasonry(eLogicalAxisInline)) { + IsMasonry(LogicalAxis::Inline)) { // Only 'grid-auto-flow:column' can create new implicit columns, so that's // the only case where our block-size can affect the number of columns. // Masonry layout always depends on how many rows we have though. - repeatSizing.InitFromStyle(eLogicalAxisBlock, state.mWM, + repeatSizing.InitFromStyle(LogicalAxis::Block, state.mWM, state.mFrame->Style()); } @@ -9640,13 +9666,13 @@ nscoord nsGridContainerFrame::IntrinsicISize(gfxContext* aRenderingContext, auto constraint = aType == IntrinsicISizeType::MinISize ? SizingConstraint::MinContent : SizingConstraint::MaxContent; - if (IsMasonry(eLogicalAxisInline)) { + if (IsMasonry(LogicalAxis::Inline)) { ReflowOutput desiredSize(state.mWM); nsSize containerSize; LogicalRect contentArea(state.mWM); nsReflowStatus status; state.mRows.mSizes.SetLength(grid.mGridRowEnd); - state.CalculateTrackSizesForAxis(eLogicalAxisInline, grid, + state.CalculateTrackSizesForAxis(LogicalAxis::Inline, grid, NS_UNCONSTRAINEDSIZE, constraint); return MasonryLayout(state, contentArea, constraint, desiredSize, status, nullptr, containerSize); @@ -9656,7 +9682,7 @@ nscoord nsGridContainerFrame::IntrinsicISize(gfxContext* aRenderingContext, return nscoord(0); } - state.CalculateTrackSizesForAxis(eLogicalAxisInline, grid, + state.CalculateTrackSizesForAxis(LogicalAxis::Inline, grid, NS_UNCONSTRAINEDSIZE, constraint); if (MOZ_LIKELY(!IsSubgrid())) { @@ -9672,7 +9698,6 @@ nscoord nsGridContainerFrame::GetMinISize(gfxContext* aRC) { return f->GetMinISize(aRC); } - DISPLAY_MIN_INLINE_SIZE(this, mCachedMinISize); if (mCachedMinISize == NS_INTRINSIC_ISIZE_UNKNOWN) { Maybe<nscoord> containISize = ContainIntrinsicISize(); mCachedMinISize = containISize @@ -9688,7 +9713,6 @@ nscoord nsGridContainerFrame::GetPrefISize(gfxContext* aRC) { return f->GetPrefISize(aRC); } - DISPLAY_PREF_INLINE_SIZE(this, mCachedPrefISize); if (mCachedPrefISize == NS_INTRINSIC_ISIZE_UNKNOWN) { Maybe<nscoord> containISize = ContainIntrinsicISize(); mCachedPrefISize = containISize @@ -9770,7 +9794,7 @@ StyleAlignFlags nsGridContainerFrame::CSSAlignmentForAbsPosChild( "This method should only be called for abspos children"); StyleAlignFlags alignment = - (aLogicalAxis == eLogicalAxisInline) + (aLogicalAxis == LogicalAxis::Inline) ? aChildRI.mStylePosition->UsedJustifySelf(Style())._0 : aChildRI.mStylePosition->UsedAlignSelf(Style())._0; @@ -9792,7 +9816,7 @@ StyleAlignFlags nsGridContainerFrame::CSSAlignmentForAbsPosChild( alignment = StyleAlignFlags::END; } else if (alignment == StyleAlignFlags::LEFT || alignment == StyleAlignFlags::RIGHT) { - if (aLogicalAxis == eLogicalAxisInline) { + if (aLogicalAxis == LogicalAxis::Inline) { const bool isLeft = (alignment == StyleAlignFlags::LEFT); WritingMode wm = GetWritingMode(); alignment = (isLeft == wm.IsBidiLTR()) ? StyleAlignFlags::START @@ -9827,7 +9851,7 @@ nscoord nsGridContainerFrame::SynthesizeBaseline( nscoord start; nscoord size; - if (aAxis == eLogicalAxisBlock) { + if (aAxis == LogicalAxis::Block) { start = child->GetLogicalNormalPosition(aCBWM, aCBPhysicalSize).B(aCBWM); size = child->BSize(aCBWM); if (grid && aGridOrderItem.mIsInEdgeTrack) { @@ -9836,13 +9860,13 @@ nscoord nsGridContainerFrame::SynthesizeBaseline( } else if (!isOrthogonal && aGridOrderItem.mIsInEdgeTrack) { // This assertion is mostly for documentation purposes; it must hold, // given the checks in our 'if' statements. (We know aAxis is - // eLogicalAxisBlock, and isOrthogonal is false, which means childAxis - // must be eLogicalAxisBlock). If instead we got here with a childAxis of - // eLogicalAxisInline, then our call to + // LogicalAxis::Block, and isOrthogonal is false, which means childAxis + // must be LogicalAxis::Block). If instead we got here with a childAxis of + // LogicalAxis::Inline, then our call to // Baseline::SynthesizeBaselineFromBorderBox might incorrectly think // it makes sense to use a central baseline, in an axis where that // doesn't make sense. - MOZ_ASSERT(childAxis == eLogicalAxisBlock, "unexpected childAxis"); + MOZ_ASSERT(childAxis == LogicalAxis::Block, "unexpected childAxis"); baseline = child ->GetNaturalBaselineBOffset(childWM, aGroup, BaselineExportContext::Other) @@ -9893,8 +9917,8 @@ void nsGridContainerFrame::CalculateBaselines( } else if (firstBaseline == NS_INTRINSIC_ISIZE_UNKNOWN) { FindItemInGridOrderResult gridOrderFirstItem = FindFirstItemInGridOrder( *aIter, *aGridItems, - axis == eLogicalAxisBlock ? &GridArea::mRows : &GridArea::mCols, - axis == eLogicalAxisBlock ? &GridArea::mCols : &GridArea::mRows, + axis == LogicalAxis::Block ? &GridArea::mRows : &GridArea::mCols, + axis == LogicalAxis::Block ? &GridArea::mCols : &GridArea::mRows, aFragmentStartTrack); mBaseline[axis][BaselineSharingGroup::First] = SynthesizeBaseline( gridOrderFirstItem, axis, BaselineSharingGroup::First, aCBPhysicalSize, @@ -9929,8 +9953,8 @@ void nsGridContainerFrame::CalculateBaselines( iter.SetItemCount(aGridItems->Length()); FindItemInGridOrderResult gridOrderLastItem = FindLastItemInGridOrder( iter, *aGridItems, - axis == eLogicalAxisBlock ? &GridArea::mRows : &GridArea::mCols, - axis == eLogicalAxisBlock ? &GridArea::mCols : &GridArea::mRows, + axis == LogicalAxis::Block ? &GridArea::mRows : &GridArea::mCols, + axis == LogicalAxis::Block ? &GridArea::mCols : &GridArea::mRows, aFragmentStartTrack, aFirstExcludedTrack); mBaseline[axis][BaselineSharingGroup::Last] = SynthesizeBaseline(gridOrderLastItem, axis, BaselineSharingGroup::Last, @@ -10124,7 +10148,7 @@ bool nsGridContainerFrame::GridItemShouldStretch(const nsIFrame* aChild, } const auto* pos = aChild->StylePosition(); - const auto alignment = (aAxis == eLogicalAxisInline) == !isOrthogonal + const auto alignment = (aAxis == LogicalAxis::Inline) == !isOrthogonal ? pos->UsedJustifySelf(Style())._0 : pos->UsedAlignSelf(Style())._0; return alignment == StyleAlignFlags::NORMAL || diff --git a/layout/generic/nsGridContainerFrame.h b/layout/generic/nsGridContainerFrame.h index cf3a3b5776..cb3eef68c3 100644 --- a/layout/generic/nsGridContainerFrame.h +++ b/layout/generic/nsGridContainerFrame.h @@ -233,12 +233,12 @@ class nsGridContainerFrame final : public nsContainerFrame, /** Return true if this frame is subgridded in its aAxis. */ bool IsSubgrid(LogicalAxis aAxis) const { - return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock + return HasAnyStateBits(aAxis == mozilla::LogicalAxis::Block ? NS_STATE_GRID_IS_ROW_SUBGRID : NS_STATE_GRID_IS_COL_SUBGRID); } - bool IsColSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisInline); } - bool IsRowSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisBlock); } + bool IsColSubgrid() const { return IsSubgrid(mozilla::LogicalAxis::Inline); } + bool IsRowSubgrid() const { return IsSubgrid(mozilla::LogicalAxis::Block); } /** Return true if this frame is subgridded in any axis. */ bool IsSubgrid() const { return HasAnyStateBits(NS_STATE_GRID_IS_ROW_SUBGRID | @@ -247,7 +247,7 @@ class nsGridContainerFrame final : public nsContainerFrame, /** Return true if this frame has an item that is subgridded in our aAxis. */ bool HasSubgridItems(LogicalAxis aAxis) const { - return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock + return HasAnyStateBits(aAxis == mozilla::LogicalAxis::Block ? NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM : NS_STATE_GRID_HAS_COL_SUBGRID_ITEM); } @@ -375,10 +375,10 @@ class nsGridContainerFrame final : public nsContainerFrame, mozilla::IntrinsicISizeType aConstraint); nscoord GetBBaseline(BaselineSharingGroup aBaselineGroup) const { - return mBaseline[mozilla::eLogicalAxisBlock][aBaselineGroup]; + return mBaseline[mozilla::LogicalAxis::Block][aBaselineGroup]; } nscoord GetIBaseline(BaselineSharingGroup aBaselineGroup) const { - return mBaseline[mozilla::eLogicalAxisInline][aBaselineGroup]; + return mBaseline[mozilla::LogicalAxis::Inline][aBaselineGroup]; } /** diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index 07aeabec07..4b646359e5 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -382,7 +382,6 @@ nscoord nsHTMLCanvasFrame::GetMinISize(gfxContext* aRenderingContext) { result = nsPresContext::CSSPixelsToAppUnits( vertical ? GetCanvasSize().height : GetCanvasSize().width); } - DISPLAY_MIN_INLINE_SIZE(this, result); return result; } @@ -398,7 +397,6 @@ nscoord nsHTMLCanvasFrame::GetPrefISize(gfxContext* aRenderingContext) { result = nsPresContext::CSSPixelsToAppUnits( vertical ? GetCanvasSize().height : GetCanvasSize().width); } - DISPLAY_PREF_INLINE_SIZE(this, result); return result; } @@ -438,7 +436,6 @@ void nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE( NS_FRAME_TRACE_CALLS, diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 479c26d18b..27f09b84f6 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -2017,6 +2017,12 @@ bool nsIFrame::GetShapeBoxBorderRadii(nscoord aRadii[8]) const { } } +nscoord nsIFrame::OneEmInAppUnits() const { + return StyleFont() + ->mFont.size.ScaledBy(nsLayoutUtils::FontSizeInflationFor(this)) + .ToAppUnits(); +} + ComputedStyle* nsIFrame::GetAdditionalComputedStyle(int32_t aIndex) const { MOZ_ASSERT(aIndex >= 0, "invalid index number"); return nullptr; @@ -2396,6 +2402,15 @@ already_AddRefed<ComputedStyle> nsIFrame::ComputeHighlightSelectionStyle( *element, PseudoStyleType::highlight, aHighlightName, Style()); } +already_AddRefed<ComputedStyle> nsIFrame::ComputeTargetTextStyle() const { + const Element* element = FindElementAncestorForMozSelection(GetContent()); + if (!element) { + return nullptr; + } + return PresContext()->StyleSet()->ProbePseudoElementStyle( + *element, PseudoStyleType::targetText, nullptr, Style()); +} + template <typename SizeOrMaxSize> static inline bool IsIntrinsicKeyword(const SizeOrMaxSize& aSize) { // All keywords other than auto/none/-moz-available depend on intrinsic sizes. @@ -4039,6 +4054,13 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, return; } + nsIFrame* child = aChild; + auto* placeholder = child->IsPlaceholderFrame() + ? static_cast<nsPlaceholderFrame*>(child) + : nullptr; + nsIFrame* childOrOutOfFlow = + placeholder ? placeholder->GetOutOfFlowFrame() : child; + // If we're generating a display list for printing, include Link items for // frames that correspond to HTML link elements so that we can have active // links in saved PDF output. Note that the state of "within a link" is @@ -4050,17 +4072,10 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, Maybe<nsDisplayListBuilder::Linkifier> linkifier; if (StaticPrefs::print_save_as_pdf_links_enabled() && aBuilder->IsForPrinting()) { - linkifier.emplace(aBuilder, aChild, aLists.Content()); - linkifier->MaybeAppendLink(aBuilder, aChild); + linkifier.emplace(aBuilder, childOrOutOfFlow, aLists.Content()); + linkifier->MaybeAppendLink(aBuilder, childOrOutOfFlow); } - nsIFrame* child = aChild; - auto* placeholder = child->IsPlaceholderFrame() - ? static_cast<nsPlaceholderFrame*>(child) - : nullptr; - nsIFrame* childOrOutOfFlow = - placeholder ? placeholder->GetOutOfFlowFrame() : child; - nsIFrame* parent = childOrOutOfFlow->GetParent(); const auto* parentDisplay = parent->StyleDisplay(); const auto overflowClipAxes = @@ -5120,7 +5135,9 @@ nsresult nsIFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack, return rv; } if (aAmountBack == eSelectWord) { - frameSelection->SetIsDoubleClickSelection(true); + frameSelection->SetClickSelectionType(ClickSelectionType::Double); + } else if (aAmountBack == eSelectParagraph) { + frameSelection->SetClickSelectionType(ClickSelectionType::Triple); } // maintain selection @@ -5989,18 +6006,10 @@ void nsIFrame::MarkSubtreeDirty() { } /* virtual */ -nscoord nsIFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result = 0; - DISPLAY_MIN_INLINE_SIZE(this, result); - return result; -} +nscoord nsIFrame::GetMinISize(gfxContext* aRenderingContext) { return 0; } /* virtual */ -nscoord nsIFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result = 0; - DISPLAY_PREF_INLINE_SIZE(this, result); - return result; -} +nscoord nsIFrame::GetPrefISize(gfxContext* aRenderingContext) { return 0; } /* virtual */ void nsIFrame::AddInlineMinISize(gfxContext* aRenderingContext, @@ -6319,14 +6328,12 @@ static MinMaxSize ComputeTransferredMinMaxInlineSize( if (aMinMaxBSize.mMinSize > 0) { transferredISize.mMinSize = aAspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, aMinMaxBSize.mMinSize, - aBoxSizingAdjustment); + LogicalAxis::Inline, aWM, aMinMaxBSize.mMinSize, aBoxSizingAdjustment); } if (aMinMaxBSize.mMaxSize != NS_UNCONSTRAINEDSIZE) { transferredISize.mMaxSize = aAspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, aMinMaxBSize.mMaxSize, - aBoxSizingAdjustment); + LogicalAxis::Inline, aWM, aMinMaxBSize.mMaxSize, aBoxSizingAdjustment); } // Minimum size wins over maximum size. @@ -6393,11 +6400,11 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( // indicates which axis (in this frame's own WM) corresponds to its // flex container's main axis. LogicalAxis flexMainAxis = - eLogicalAxisInline; // (init to make valgrind happy) + LogicalAxis::Inline; // (init to make valgrind happy) if (isFlexItem) { flexMainAxis = nsFlexContainerFrame::IsItemInlineAxisMainAxis(this) - ? eLogicalAxisInline - : eLogicalAxisBlock; + ? LogicalAxis::Inline + : LogicalAxis::Block; } const bool isOrthogonal = aWM.IsOrthogonalTo(alignCB->GetWritingMode()); @@ -6426,8 +6433,8 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( bool mayUseAspectRatio = aspectRatio && !isAutoBSize; if (!aFlags.contains(ComputeSizeFlag::ShrinkWrap) && !StyleMargin()->HasInlineAxisAuto(aWM) && - !alignCB->IsMasonry(isOrthogonal ? eLogicalAxisBlock - : eLogicalAxisInline)) { + !alignCB->IsMasonry(isOrthogonal ? LogicalAxis::Block + : LogicalAxis::Inline)) { auto inlineAxisAlignment = isOrthogonal ? StylePosition()->UsedAlignSelf(alignCB->Style())._0 : StylePosition()->UsedJustifySelf(alignCB->Style())._0; @@ -6451,7 +6458,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), styleBSize.AsLengthPercentage()); result.ISize(aWM) = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); aspectRatioUsage = AspectRatioUsage::ToComputeISize; } @@ -6468,7 +6475,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), styleBSize.AsLengthPercentage()); result.ISize(aWM) = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, boxSizingAdjust); + LogicalAxis::Inline, aWM, bSize, boxSizingAdjust); aspectRatioUsage = AspectRatioUsage::ToComputeISize; } @@ -6523,7 +6530,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( // flex container's main-axis. (Those properties get applied later in // the flexbox algorithm.) const bool isFlexItemInlineAxisMainAxis = - isFlexItem && flexMainAxis == eLogicalAxisInline; + isFlexItem && flexMainAxis == LogicalAxis::Inline; // Grid items that are subgridded in inline-axis also ignore their min & max // sizing properties in that axis. const bool shouldIgnoreMinMaxISize = @@ -6602,8 +6609,8 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( } else if (MOZ_UNLIKELY(isGridItem) && styleBSize.IsAuto() && !aFlags.contains(ComputeSizeFlag::IsGridMeasuringReflow) && !IsTrueOverflowContainer() && - !alignCB->IsMasonry(isOrthogonal ? eLogicalAxisInline - : eLogicalAxisBlock)) { + !alignCB->IsMasonry(isOrthogonal ? LogicalAxis::Inline + : LogicalAxis::Block)) { auto cbSize = aCBSize.BSize(aWM); if (cbSize != NS_UNCONSTRAINEDSIZE) { // 'auto' block-size for grid-level box - fill the CB for 'stretch' / @@ -6628,8 +6635,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( // https://drafts.csswg.org/css-grid/#grid-item-sizing if (!stretch && mayUseAspectRatio) { result.BSize(aWM) = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, result.ISize(aWM), - boxSizingAdjust); + LogicalAxis::Block, aWM, result.ISize(aWM), boxSizingAdjust); MOZ_ASSERT(aspectRatioUsage == AspectRatioUsage::None); aspectRatioUsage = AspectRatioUsage::ToComputeBSize; } @@ -6651,8 +6657,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( // applied (so aspectRatioUsage flag is set as expected). That's why we // apply aspect-ratio unconditionally for auto block size here. result.BSize(aWM) = aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisBlock, aWM, result.ISize(aWM), - boxSizingAdjust); + LogicalAxis::Block, aWM, result.ISize(aWM), boxSizingAdjust); MOZ_ASSERT(aspectRatioUsage == AspectRatioUsage::None); aspectRatioUsage = AspectRatioUsage::ToComputeBSize; } @@ -6662,7 +6667,7 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( // container's main-axis. (Those properties get applied later in the flexbox // algorithm.) const bool isFlexItemBlockAxisMainAxis = - isFlexItem && flexMainAxis == eLogicalAxisBlock; + isFlexItem && flexMainAxis == LogicalAxis::Block; // Grid items that are subgridded in block-axis also ignore their min & max // sizing properties in that axis. const bool shouldIgnoreMinMaxBSize = @@ -6789,7 +6794,7 @@ Maybe<nscoord> nsIFrame::ComputeInlineSizeFromAspectRatio( aCBSize.BSize(aWM), aContentEdgeToBoxSizing.BSize(aWM), styleBSize.AsLengthPercentage()); return Some(aspectRatio.ComputeRatioDependentSize( - LogicalAxis::eLogicalAxisInline, aWM, bSize, aContentEdgeToBoxSizing)); + LogicalAxis::Inline, aWM, bSize, aContentEdgeToBoxSizing)); } nsIFrame::ISizeComputationResult nsIFrame::ComputeISizeValue( @@ -8560,6 +8565,12 @@ const nsFrameSelection* nsIFrame::GetConstFrameSelection() const { bool nsIFrame::IsFrameSelected() const { NS_ASSERTION(!GetContent() || GetContent()->IsMaybeSelected(), "use the public IsSelected() instead"); + if (StaticPrefs::dom_shadowdom_selection_across_boundary_enabled()) { + if (const ShadowRoot* shadowRoot = + GetContent()->GetShadowRootForSelection()) { + return shadowRoot->IsSelected(0, shadowRoot->GetChildCount()); + } + } return GetContent()->IsSelected(0, GetContent()->GetChildCount()); } @@ -8983,6 +8994,13 @@ nsresult nsIFrame::PeekOffsetForParagraph(PeekOffsetStruct* aPos) { if (reachedLimit) { // no "stop frame" found aPos->mResultContent = frame->GetContent(); + if (ShadowRoot* shadowRoot = + aPos->mResultContent->GetShadowRootForSelection()) { + // Even if there's no children for this node, + // the elements inside the shadow root is still + // selectable + aPos->mResultContent = shadowRoot; + } if (aPos->mDirection == eDirPrevious) { aPos->mContentOffset = 0; } else if (aPos->mResultContent) { @@ -10698,21 +10716,27 @@ ComputedStyle* nsIFrame::DoGetParentComputedStyle( } void nsIFrame::GetLastLeaf(nsIFrame** aFrame) { - if (!aFrame || !*aFrame) return; - nsIFrame* child = *aFrame; - // if we are a block frame then go for the last line of 'this' - while (1) { - child = child->PrincipalChildList().FirstChild(); - if (!child) return; // nothing to do - nsIFrame* siblingFrame; - nsIContent* content; - // ignore anonymous elements, e.g. mozTableAdd* mozTableRemove* - // see bug 278197 comment #12 #13 for details - while ((siblingFrame = child->GetNextSibling()) && - (content = siblingFrame->GetContent()) && - !content->IsRootOfNativeAnonymousSubtree()) - child = siblingFrame; - *aFrame = child; + if (!aFrame || !*aFrame) { + return; + } + for (nsIFrame* maybeLastLeaf = (*aFrame)->PrincipalChildList().LastChild(); + maybeLastLeaf;) { + nsIFrame* lastChildNotInSubTree = nullptr; + for (nsIFrame* child = maybeLastLeaf; child; + child = child->GetPrevSibling()) { + nsIContent* content = child->GetContent(); + // ignore anonymous elements, e.g. mozTableAdd* mozTableRemove* + // see bug 278197 comment #12 #13 for details + if (content && !content->IsRootOfNativeAnonymousSubtree()) { + lastChildNotInSubTree = child; + break; + } + } + if (!lastChildNotInSubTree) { + return; + } + *aFrame = lastChildNotInSubTree; + maybeLastLeaf = lastChildNotInSubTree->PrincipalChildList().LastChild(); } } @@ -10907,7 +10931,7 @@ void nsIFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame, // Now that we've updated the style on aChildFrame, check whether it itself // has anon boxes to deal with. ServoRestyleState childrenState(*aChildFrame, aRestyleState, childHint, - ServoRestyleState::Type::InFlow); + ServoRestyleState::CanUseHandledHints::Yes); aChildFrame->UpdateStyleOfOwnedAnonBoxes(childrenState); // Assuming anon boxes don't have ::backdrop associated with them... if that @@ -11655,1037 +11679,6 @@ void nsIFrame::VerifyDirtyBitSet(const nsFrameList& aFrameList) { } } -// Start Display Reflow -DR_cookie::DR_cookie(nsPresContext* aPresContext, nsIFrame* aFrame, - const ReflowInput& aReflowInput, ReflowOutput& aMetrics, - nsReflowStatus& aStatus) - : mPresContext(aPresContext), - mFrame(aFrame), - mReflowInput(aReflowInput), - mMetrics(aMetrics), - mStatus(aStatus) { - MOZ_COUNT_CTOR(DR_cookie); - mValue = nsIFrame::DisplayReflowEnter(aPresContext, mFrame, mReflowInput); -} - -DR_cookie::~DR_cookie() { - MOZ_COUNT_DTOR(DR_cookie); - nsIFrame::DisplayReflowExit(mPresContext, mFrame, mMetrics, mStatus, mValue); -} - -DR_layout_cookie::DR_layout_cookie(nsIFrame* aFrame) : mFrame(aFrame) { - MOZ_COUNT_CTOR(DR_layout_cookie); - mValue = nsIFrame::DisplayLayoutEnter(mFrame); -} - -DR_layout_cookie::~DR_layout_cookie() { - MOZ_COUNT_DTOR(DR_layout_cookie); - nsIFrame::DisplayLayoutExit(mFrame, mValue); -} - -DR_intrinsic_inline_size_cookie::DR_intrinsic_inline_size_cookie( - nsIFrame* aFrame, const char* aType, nscoord& aResult) - : mFrame(aFrame), mType(aType), mResult(aResult) { - MOZ_COUNT_CTOR(DR_intrinsic_inline_size_cookie); - mValue = nsIFrame::DisplayIntrinsicISizeEnter(mFrame, mType); -} - -DR_intrinsic_inline_size_cookie::~DR_intrinsic_inline_size_cookie() { - MOZ_COUNT_DTOR(DR_intrinsic_inline_size_cookie); - nsIFrame::DisplayIntrinsicISizeExit(mFrame, mType, mResult, mValue); -} - -DR_intrinsic_size_cookie::DR_intrinsic_size_cookie(nsIFrame* aFrame, - const char* aType, - nsSize& aResult) - : mFrame(aFrame), mType(aType), mResult(aResult) { - MOZ_COUNT_CTOR(DR_intrinsic_size_cookie); - mValue = nsIFrame::DisplayIntrinsicSizeEnter(mFrame, mType); -} - -DR_intrinsic_size_cookie::~DR_intrinsic_size_cookie() { - MOZ_COUNT_DTOR(DR_intrinsic_size_cookie); - nsIFrame::DisplayIntrinsicSizeExit(mFrame, mType, mResult, mValue); -} - -DR_init_constraints_cookie::DR_init_constraints_cookie( - nsIFrame* aFrame, ReflowInput* aState, nscoord aCBWidth, nscoord aCBHeight, - const mozilla::Maybe<mozilla::LogicalMargin> aBorder, - const mozilla::Maybe<mozilla::LogicalMargin> aPadding) - : mFrame(aFrame), mState(aState) { - MOZ_COUNT_CTOR(DR_init_constraints_cookie); - nsMargin border; - if (aBorder) { - border = aBorder->GetPhysicalMargin(aFrame->GetWritingMode()); - } - nsMargin padding; - if (aPadding) { - padding = aPadding->GetPhysicalMargin(aFrame->GetWritingMode()); - } - mValue = ReflowInput::DisplayInitConstraintsEnter( - mFrame, mState, aCBWidth, aCBHeight, aBorder ? &border : nullptr, - aPadding ? &padding : nullptr); -} - -DR_init_constraints_cookie::~DR_init_constraints_cookie() { - MOZ_COUNT_DTOR(DR_init_constraints_cookie); - ReflowInput::DisplayInitConstraintsExit(mFrame, mState, mValue); -} - -DR_init_offsets_cookie::DR_init_offsets_cookie( - nsIFrame* aFrame, SizeComputationInput* aState, nscoord aPercentBasis, - WritingMode aCBWritingMode, - const mozilla::Maybe<mozilla::LogicalMargin> aBorder, - const mozilla::Maybe<mozilla::LogicalMargin> aPadding) - : mFrame(aFrame), mState(aState) { - MOZ_COUNT_CTOR(DR_init_offsets_cookie); - nsMargin border; - if (aBorder) { - border = aBorder->GetPhysicalMargin(aFrame->GetWritingMode()); - } - nsMargin padding; - if (aPadding) { - padding = aPadding->GetPhysicalMargin(aFrame->GetWritingMode()); - } - mValue = SizeComputationInput::DisplayInitOffsetsEnter( - mFrame, mState, aPercentBasis, aCBWritingMode, - aBorder ? &border : nullptr, aPadding ? &padding : nullptr); -} - -DR_init_offsets_cookie::~DR_init_offsets_cookie() { - MOZ_COUNT_DTOR(DR_init_offsets_cookie); - SizeComputationInput::DisplayInitOffsetsExit(mFrame, mState, mValue); -} - -struct DR_Rule; - -struct DR_FrameTypeInfo { - DR_FrameTypeInfo(LayoutFrameType aFrameType, const char* aFrameNameAbbrev, - const char* aFrameName); - ~DR_FrameTypeInfo(); - - LayoutFrameType mType; - char mNameAbbrev[16]; - char mName[32]; - nsTArray<DR_Rule*> mRules; - - private: - DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) = delete; -}; - -struct DR_FrameTreeNode; -struct DR_Rule; - -struct DR_State { - DR_State(); - ~DR_State(); - void Init(); - void AddFrameTypeInfo(LayoutFrameType aFrameType, - const char* aFrameNameAbbrev, const char* aFrameName); - DR_FrameTypeInfo* GetFrameTypeInfo(LayoutFrameType aFrameType); - DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName); - void InitFrameTypeTable(); - DR_FrameTreeNode* CreateTreeNode(nsIFrame* aFrame, - const ReflowInput* aReflowInput); - void FindMatchingRule(DR_FrameTreeNode& aNode); - bool RuleMatches(DR_Rule& aRule, DR_FrameTreeNode& aNode); - bool GetToken(FILE* aFile, char* aBuf, size_t aBufSize); - DR_Rule* ParseRule(FILE* aFile); - void ParseRulesFile(); - void AddRule(nsTArray<DR_Rule*>& aRules, DR_Rule& aRule); - bool IsWhiteSpace(int c); - bool GetNumber(char* aBuf, int32_t& aNumber); - void PrettyUC(nscoord aSize, char* aBuf, int aBufSize); - void PrintMargin(const char* tag, const nsMargin* aMargin); - void DisplayFrameTypeInfo(nsIFrame* aFrame, int32_t aIndent); - void DeleteTreeNode(DR_FrameTreeNode& aNode); - - bool mInited; - bool mActive; - int32_t mCount; - int32_t mAssert; - int32_t mIndent; - bool mIndentUndisplayedFrames; - bool mDisplayPixelErrors; - nsTArray<DR_Rule*> mWildRules; - nsTArray<DR_FrameTypeInfo> mFrameTypeTable; - // reflow specific state - nsTArray<DR_FrameTreeNode*> mFrameTreeLeaves; -}; - -static DR_State* DR_state; // the one and only DR_State - -struct DR_RulePart { - explicit DR_RulePart(LayoutFrameType aFrameType) - : mFrameType(aFrameType), mNext(0) {} - - void Destroy(); - - LayoutFrameType mFrameType; - DR_RulePart* mNext; -}; - -void DR_RulePart::Destroy() { - if (mNext) { - mNext->Destroy(); - } - delete this; -} - -struct DR_Rule { - DR_Rule() : mLength(0), mTarget(nullptr), mDisplay(false) { - MOZ_COUNT_CTOR(DR_Rule); - } - ~DR_Rule() { - if (mTarget) mTarget->Destroy(); - MOZ_COUNT_DTOR(DR_Rule); - } - void AddPart(LayoutFrameType aFrameType); - - uint32_t mLength; - DR_RulePart* mTarget; - bool mDisplay; -}; - -void DR_Rule::AddPart(LayoutFrameType aFrameType) { - DR_RulePart* newPart = new DR_RulePart(aFrameType); - newPart->mNext = mTarget; - mTarget = newPart; - mLength++; -} - -DR_FrameTypeInfo::~DR_FrameTypeInfo() { - int32_t numElements; - numElements = mRules.Length(); - for (int32_t i = numElements - 1; i >= 0; i--) { - delete mRules.ElementAt(i); - } -} - -DR_FrameTypeInfo::DR_FrameTypeInfo(LayoutFrameType aFrameType, - const char* aFrameNameAbbrev, - const char* aFrameName) { - mType = aFrameType; - PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev)); - PL_strncpyz(mName, aFrameName, sizeof(mName)); -} - -struct DR_FrameTreeNode { - DR_FrameTreeNode(nsIFrame* aFrame, DR_FrameTreeNode* aParent) - : mFrame(aFrame), mParent(aParent), mDisplay(0), mIndent(0) { - MOZ_COUNT_CTOR(DR_FrameTreeNode); - } - - MOZ_COUNTED_DTOR(DR_FrameTreeNode) - - nsIFrame* mFrame; - DR_FrameTreeNode* mParent; - bool mDisplay; - uint32_t mIndent; -}; - -// DR_State implementation - -DR_State::DR_State() - : mInited(false), - mActive(false), - mCount(0), - mAssert(-1), - mIndent(0), - mIndentUndisplayedFrames(false), - mDisplayPixelErrors(false) { - MOZ_COUNT_CTOR(DR_State); -} - -void DR_State::Init() { - char* env = PR_GetEnv("GECKO_DISPLAY_REFLOW_ASSERT"); - int32_t num; - if (env) { - if (GetNumber(env, num)) - mAssert = num; - else - printf("GECKO_DISPLAY_REFLOW_ASSERT - invalid value = %s", env); - } - - env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_START"); - if (env) { - if (GetNumber(env, num)) - mIndent = num; - else - printf("GECKO_DISPLAY_REFLOW_INDENT_START - invalid value = %s", env); - } - - env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES"); - if (env) { - if (GetNumber(env, num)) - mIndentUndisplayedFrames = num; - else - printf( - "GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES - invalid value = %s", - env); - } - - env = PR_GetEnv("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS"); - if (env) { - if (GetNumber(env, num)) - mDisplayPixelErrors = num; - else - printf("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS - invalid value = %s", - env); - } - - InitFrameTypeTable(); - ParseRulesFile(); - mInited = true; -} - -DR_State::~DR_State() { - MOZ_COUNT_DTOR(DR_State); - int32_t numElements, i; - numElements = mWildRules.Length(); - for (i = numElements - 1; i >= 0; i--) { - delete mWildRules.ElementAt(i); - } - numElements = mFrameTreeLeaves.Length(); - for (i = numElements - 1; i >= 0; i--) { - delete mFrameTreeLeaves.ElementAt(i); - } -} - -bool DR_State::GetNumber(char* aBuf, int32_t& aNumber) { - if (sscanf(aBuf, "%d", &aNumber) > 0) - return true; - else - return false; -} - -bool DR_State::IsWhiteSpace(int c) { - return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'); -} - -bool DR_State::GetToken(FILE* aFile, char* aBuf, size_t aBufSize) { - bool haveToken = false; - aBuf[0] = 0; - // get the 1st non whitespace char - int c = -1; - for (c = getc(aFile); (c > 0) && IsWhiteSpace(c); c = getc(aFile)) { - } - - if (c > 0) { - haveToken = true; - aBuf[0] = c; - // get everything up to the next whitespace char - size_t cX; - for (cX = 1; cX + 1 < aBufSize; cX++) { - c = getc(aFile); - if (c < 0) { // EOF - ungetc(' ', aFile); - break; - } else { - if (IsWhiteSpace(c)) { - break; - } else { - aBuf[cX] = c; - } - } - } - aBuf[cX] = 0; - } - return haveToken; -} - -DR_Rule* DR_State::ParseRule(FILE* aFile) { - char buf[128]; - int32_t doDisplay; - DR_Rule* rule = nullptr; - while (GetToken(aFile, buf, sizeof(buf))) { - if (GetNumber(buf, doDisplay)) { - if (rule) { - rule->mDisplay = !!doDisplay; - break; - } else { - printf("unexpected token - %s \n", buf); - } - } else { - if (!rule) { - rule = new DR_Rule; - } - if (strcmp(buf, "*") == 0) { - rule->AddPart(LayoutFrameType::None); - } else { - DR_FrameTypeInfo* info = GetFrameTypeInfo(buf); - if (info) { - rule->AddPart(info->mType); - } else { - printf("invalid frame type - %s \n", buf); - } - } - } - } - return rule; -} - -void DR_State::AddRule(nsTArray<DR_Rule*>& aRules, DR_Rule& aRule) { - int32_t numRules = aRules.Length(); - for (int32_t ruleX = 0; ruleX < numRules; ruleX++) { - DR_Rule* rule = aRules.ElementAt(ruleX); - NS_ASSERTION(rule, "program error"); - if (aRule.mLength > rule->mLength) { - aRules.InsertElementAt(ruleX, &aRule); - return; - } - } - aRules.AppendElement(&aRule); -} - -static Maybe<bool> ShouldLogReflow(const char* processes) { - switch (processes[0]) { - case 'A': - case 'a': - return Some(true); - case 'P': - case 'p': - return Some(XRE_IsParentProcess()); - case 'C': - case 'c': - return Some(XRE_IsContentProcess()); - default: - return Nothing{}; - } -} - -void DR_State::ParseRulesFile() { - char* processes = PR_GetEnv("GECKO_DISPLAY_REFLOW_PROCESSES"); - if (processes) { - Maybe<bool> enableLog = ShouldLogReflow(processes); - if (enableLog.isNothing()) { - MOZ_CRASH("GECKO_DISPLAY_REFLOW_PROCESSES: [a]ll [p]arent [c]ontent"); - } else if (enableLog.value()) { - DR_Rule* rule = new DR_Rule; - rule->AddPart(LayoutFrameType::None); - rule->mDisplay = true; - AddRule(mWildRules, *rule); - mActive = true; - } - return; - } - - char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE"); - if (path) { - FILE* inFile = fopen(path, "r"); - if (!inFile) { - MOZ_CRASH( - "Failed to open the specified rules file; Try `--setpref " - "security.sandbox.content.level=2` if the sandbox is at cause"); - } - for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) { - if (rule->mTarget) { - LayoutFrameType fType = rule->mTarget->mFrameType; - if (fType != LayoutFrameType::None) { - DR_FrameTypeInfo* info = GetFrameTypeInfo(fType); - AddRule(info->mRules, *rule); - } else { - AddRule(mWildRules, *rule); - } - mActive = true; - } - } - - fclose(inFile); - } -} - -void DR_State::AddFrameTypeInfo(LayoutFrameType aFrameType, - const char* aFrameNameAbbrev, - const char* aFrameName) { - mFrameTypeTable.EmplaceBack(aFrameType, aFrameNameAbbrev, aFrameName); -} - -DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(LayoutFrameType aFrameType) { - int32_t numEntries = mFrameTypeTable.Length(); - NS_ASSERTION(numEntries != 0, "empty FrameTypeTable"); - for (int32_t i = 0; i < numEntries; i++) { - DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i); - if (info.mType == aFrameType) { - return &info; - } - } - return &mFrameTypeTable.ElementAt(numEntries - - 1); // return unknown frame type -} - -DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(char* aFrameName) { - int32_t numEntries = mFrameTypeTable.Length(); - NS_ASSERTION(numEntries != 0, "empty FrameTypeTable"); - for (int32_t i = 0; i < numEntries; i++) { - DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i); - if ((strcmp(aFrameName, info.mName) == 0) || - (strcmp(aFrameName, info.mNameAbbrev) == 0)) { - return &info; - } - } - return &mFrameTypeTable.ElementAt(numEntries - - 1); // return unknown frame type -} - -void DR_State::InitFrameTypeTable() { - AddFrameTypeInfo(LayoutFrameType::Block, "block", "block"); - AddFrameTypeInfo(LayoutFrameType::Br, "br", "br"); - AddFrameTypeInfo(LayoutFrameType::ColorControl, "color", "colorControl"); - AddFrameTypeInfo(LayoutFrameType::GfxButtonControl, "button", - "gfxButtonControl"); - AddFrameTypeInfo(LayoutFrameType::HTMLButtonControl, "HTMLbutton", - "HTMLButtonControl"); - AddFrameTypeInfo(LayoutFrameType::HTMLCanvas, "HTMLCanvas", "HTMLCanvas"); - AddFrameTypeInfo(LayoutFrameType::SubDocument, "subdoc", "subDocument"); - AddFrameTypeInfo(LayoutFrameType::Image, "img", "image"); - AddFrameTypeInfo(LayoutFrameType::Inline, "inline", "inline"); - AddFrameTypeInfo(LayoutFrameType::Letter, "letter", "letter"); - AddFrameTypeInfo(LayoutFrameType::Line, "line", "line"); - AddFrameTypeInfo(LayoutFrameType::ListControl, "select", "select"); - AddFrameTypeInfo(LayoutFrameType::Page, "page", "page"); - AddFrameTypeInfo(LayoutFrameType::Placeholder, "place", "placeholder"); - AddFrameTypeInfo(LayoutFrameType::Canvas, "canvas", "canvas"); - AddFrameTypeInfo(LayoutFrameType::Scroll, "scroll", "scroll"); - AddFrameTypeInfo(LayoutFrameType::TableCell, "cell", "tableCell"); - AddFrameTypeInfo(LayoutFrameType::TableCol, "col", "tableCol"); - AddFrameTypeInfo(LayoutFrameType::TableColGroup, "colG", "tableColGroup"); - AddFrameTypeInfo(LayoutFrameType::Table, "tbl", "table"); - AddFrameTypeInfo(LayoutFrameType::TableWrapper, "tblW", "tableWrapper"); - AddFrameTypeInfo(LayoutFrameType::TableRowGroup, "rowG", "tableRowGroup"); - AddFrameTypeInfo(LayoutFrameType::TableRow, "row", "tableRow"); - AddFrameTypeInfo(LayoutFrameType::TextInput, "textCtl", "textInput"); - AddFrameTypeInfo(LayoutFrameType::Text, "text", "text"); - AddFrameTypeInfo(LayoutFrameType::Viewport, "VP", "viewport"); - AddFrameTypeInfo(LayoutFrameType::Slider, "Slider", "Slider"); - AddFrameTypeInfo(LayoutFrameType::None, "unknown", "unknown"); -} - -void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame, int32_t aIndent) { - DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->Type()); - if (frameTypeInfo) { - for (int32_t i = 0; i < aIndent; i++) { - printf(" "); - } - if (!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) { - if (aFrame) { - nsAutoString name; - aFrame->GetFrameName(name); - printf("%s %p ", NS_LossyConvertUTF16toASCII(name).get(), - (void*)aFrame); - } else { - printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame); - } - } else { - printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame); - } - } -} - -bool DR_State::RuleMatches(DR_Rule& aRule, DR_FrameTreeNode& aNode) { - NS_ASSERTION(aRule.mTarget, "program error"); - - DR_RulePart* rulePart; - DR_FrameTreeNode* parentNode; - for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent; - rulePart && parentNode; - rulePart = rulePart->mNext, parentNode = parentNode->mParent) { - if (rulePart->mFrameType != LayoutFrameType::None) { - if (parentNode->mFrame) { - if (rulePart->mFrameType != parentNode->mFrame->Type()) { - return false; - } - } else - NS_ASSERTION(false, "program error"); - } - // else wild card match - } - return true; -} - -void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode) { - if (!aNode.mFrame) { - NS_ASSERTION(false, "invalid DR_FrameTreeNode \n"); - return; - } - - bool matchingRule = false; - - DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->Type()); - NS_ASSERTION(info, "program error"); - int32_t numRules = info->mRules.Length(); - for (int32_t ruleX = 0; ruleX < numRules; ruleX++) { - DR_Rule* rule = info->mRules.ElementAt(ruleX); - if (rule && RuleMatches(*rule, aNode)) { - aNode.mDisplay = rule->mDisplay; - matchingRule = true; - break; - } - } - if (!matchingRule) { - int32_t numWildRules = mWildRules.Length(); - for (int32_t ruleX = 0; ruleX < numWildRules; ruleX++) { - DR_Rule* rule = mWildRules.ElementAt(ruleX); - if (rule && RuleMatches(*rule, aNode)) { - aNode.mDisplay = rule->mDisplay; - break; - } - } - } -} - -DR_FrameTreeNode* DR_State::CreateTreeNode(nsIFrame* aFrame, - const ReflowInput* aReflowInput) { - // find the frame of the parent reflow input (usually just the parent of - // aFrame) - nsIFrame* parentFrame; - if (aReflowInput) { - const ReflowInput* parentRI = aReflowInput->mParentReflowInput; - parentFrame = (parentRI) ? parentRI->mFrame : nullptr; - } else { - parentFrame = aFrame->GetParent(); - } - - // find the parent tree node leaf - DR_FrameTreeNode* parentNode = nullptr; - - DR_FrameTreeNode* lastLeaf = nullptr; - if (mFrameTreeLeaves.Length()) - lastLeaf = mFrameTreeLeaves.ElementAt(mFrameTreeLeaves.Length() - 1); - if (lastLeaf) { - for (parentNode = lastLeaf; - parentNode && (parentNode->mFrame != parentFrame); - parentNode = parentNode->mParent) { - } - } - DR_FrameTreeNode* newNode = new DR_FrameTreeNode(aFrame, parentNode); - FindMatchingRule(*newNode); - - newNode->mIndent = mIndent; - if (newNode->mDisplay || mIndentUndisplayedFrames) { - ++mIndent; - } - - if (lastLeaf && (lastLeaf == parentNode)) { - mFrameTreeLeaves.RemoveLastElement(); - } - mFrameTreeLeaves.AppendElement(newNode); - mCount++; - - return newNode; -} - -void DR_State::PrettyUC(nscoord aSize, char* aBuf, int aBufSize) { - if (NS_UNCONSTRAINEDSIZE == aSize) { - strcpy(aBuf, "UC"); - } else { - if ((nscoord)0xdeadbeefU == aSize) { - strcpy(aBuf, "deadbeef"); - } else { - snprintf(aBuf, aBufSize, "%d", aSize); - } - } -} - -void DR_State::PrintMargin(const char* tag, const nsMargin* aMargin) { - if (aMargin) { - char t[16], r[16], b[16], l[16]; - PrettyUC(aMargin->top, t, 16); - PrettyUC(aMargin->right, r, 16); - PrettyUC(aMargin->bottom, b, 16); - PrettyUC(aMargin->left, l, 16); - printf(" %s=%s,%s,%s,%s", tag, t, r, b, l); - } else { - // use %p here for consistency with other null-pointer printouts - printf(" %s=%p", tag, (void*)aMargin); - } -} - -void DR_State::DeleteTreeNode(DR_FrameTreeNode& aNode) { - mFrameTreeLeaves.RemoveElement(&aNode); - int32_t numLeaves = mFrameTreeLeaves.Length(); - if ((0 == numLeaves) || - (aNode.mParent != mFrameTreeLeaves.ElementAt(numLeaves - 1))) { - mFrameTreeLeaves.AppendElement(aNode.mParent); - } - - if (aNode.mDisplay || mIndentUndisplayedFrames) { - --mIndent; - } - // delete the tree node - delete &aNode; -} - -static void CheckPixelError(nscoord aSize, int32_t aPixelToTwips) { - if (NS_UNCONSTRAINEDSIZE != aSize) { - if ((aSize % aPixelToTwips) > 0) { - printf("VALUE %d is not a whole pixel \n", aSize); - } - } -} - -static void DisplayReflowEnterPrint(nsPresContext* aPresContext, - nsIFrame* aFrame, - const ReflowInput& aReflowInput, - DR_FrameTreeNode& aTreeNode, - bool aChanged) { - if (aTreeNode.mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, aTreeNode.mIndent); - - char width[16]; - char height[16]; - - DR_state->PrettyUC(aReflowInput.AvailableWidth(), width, 16); - DR_state->PrettyUC(aReflowInput.AvailableHeight(), height, 16); - printf("Reflow a=%s,%s ", width, height); - - DR_state->PrettyUC(aReflowInput.ComputedWidth(), width, 16); - DR_state->PrettyUC(aReflowInput.ComputedHeight(), height, 16); - printf("c=%s,%s ", width, height); - - if (aFrame->HasAnyStateBits(NS_FRAME_IS_DIRTY)) printf("dirty "); - - if (aFrame->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN)) - printf("dirty-children "); - - if (aReflowInput.mFlags.mSpecialBSizeReflow) printf("special-bsize "); - - if (aReflowInput.IsHResize()) printf("h-resize "); - - if (aReflowInput.IsVResize()) printf("v-resize "); - - nsIFrame* inFlow = aFrame->GetPrevInFlow(); - if (inFlow) { - printf("pif=%p ", (void*)inFlow); - } - inFlow = aFrame->GetNextInFlow(); - if (inFlow) { - printf("nif=%p ", (void*)inFlow); - } - if (aChanged) - printf("CHANGED \n"); - else - printf("cnt=%d \n", DR_state->mCount); - if (DR_state->mDisplayPixelErrors) { - int32_t d2a = aPresContext->AppUnitsPerDevPixel(); - CheckPixelError(aReflowInput.AvailableWidth(), d2a); - CheckPixelError(aReflowInput.AvailableHeight(), d2a); - CheckPixelError(aReflowInput.ComputedWidth(), d2a); - CheckPixelError(aReflowInput.ComputedHeight(), d2a); - } - } -} - -void* nsIFrame::DisplayReflowEnter(nsPresContext* aPresContext, - nsIFrame* aFrame, - const ReflowInput& aReflowInput) { - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - NS_ASSERTION(aFrame, "invalid call"); - - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, &aReflowInput); - if (treeNode) { - DisplayReflowEnterPrint(aPresContext, aFrame, aReflowInput, *treeNode, - false); - } - return treeNode; -} - -void* nsIFrame::DisplayLayoutEnter(nsIFrame* aFrame) { - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - NS_ASSERTION(aFrame, "invalid call"); - - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr); - if (treeNode && treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - printf("XULLayout\n"); - } - return treeNode; -} - -void* nsIFrame::DisplayIntrinsicISizeEnter(nsIFrame* aFrame, - const char* aType) { - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - NS_ASSERTION(aFrame, "invalid call"); - - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr); - if (treeNode && treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - printf("Get%sISize\n", aType); - } - return treeNode; -} - -void* nsIFrame::DisplayIntrinsicSizeEnter(nsIFrame* aFrame, const char* aType) { - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - NS_ASSERTION(aFrame, "invalid call"); - - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr); - if (treeNode && treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - printf("Get%sSize\n", aType); - } - return treeNode; -} - -void nsIFrame::DisplayReflowExit(nsPresContext* aPresContext, nsIFrame* aFrame, - ReflowOutput& aMetrics, - const nsReflowStatus& aStatus, - void* aFrameTreeNode) { - if (!DR_state->mActive) return; - - NS_ASSERTION(aFrame, "DisplayReflowExit - invalid call"); - if (!aFrameTreeNode) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - - char width[16]; - char height[16]; - char x[16]; - char y[16]; - DR_state->PrettyUC(aMetrics.Width(), width, 16); - DR_state->PrettyUC(aMetrics.Height(), height, 16); - printf("Reflow d=%s,%s", width, height); - - if (!aStatus.IsEmpty()) { - printf(" status=%s", ToString(aStatus).c_str()); - } - if (aFrame->HasOverflowAreas()) { - DR_state->PrettyUC(aMetrics.InkOverflow().x, x, 16); - DR_state->PrettyUC(aMetrics.InkOverflow().y, y, 16); - DR_state->PrettyUC(aMetrics.InkOverflow().width, width, 16); - DR_state->PrettyUC(aMetrics.InkOverflow().height, height, 16); - printf(" vis-o=(%s,%s) %s x %s", x, y, width, height); - - nsRect storedOverflow = aFrame->InkOverflowRect(); - DR_state->PrettyUC(storedOverflow.x, x, 16); - DR_state->PrettyUC(storedOverflow.y, y, 16); - DR_state->PrettyUC(storedOverflow.width, width, 16); - DR_state->PrettyUC(storedOverflow.height, height, 16); - printf(" vis-sto=(%s,%s) %s x %s", x, y, width, height); - - DR_state->PrettyUC(aMetrics.ScrollableOverflow().x, x, 16); - DR_state->PrettyUC(aMetrics.ScrollableOverflow().y, y, 16); - DR_state->PrettyUC(aMetrics.ScrollableOverflow().width, width, 16); - DR_state->PrettyUC(aMetrics.ScrollableOverflow().height, height, 16); - printf(" scr-o=(%s,%s) %s x %s", x, y, width, height); - - storedOverflow = aFrame->ScrollableOverflowRect(); - DR_state->PrettyUC(storedOverflow.x, x, 16); - DR_state->PrettyUC(storedOverflow.y, y, 16); - DR_state->PrettyUC(storedOverflow.width, width, 16); - DR_state->PrettyUC(storedOverflow.height, height, 16); - printf(" scr-sto=(%s,%s) %s x %s", x, y, width, height); - } - printf("\n"); - if (DR_state->mDisplayPixelErrors) { - int32_t d2a = aPresContext->AppUnitsPerDevPixel(); - CheckPixelError(aMetrics.Width(), d2a); - CheckPixelError(aMetrics.Height(), d2a); - } - } - DR_state->DeleteTreeNode(*treeNode); -} - -void nsIFrame::DisplayLayoutExit(nsIFrame* aFrame, void* aFrameTreeNode) { - if (!DR_state->mActive) return; - - NS_ASSERTION(aFrame, "non-null frame required"); - if (!aFrameTreeNode) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - nsRect rect = aFrame->GetRect(); - printf("XULLayout=%d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height); - } - DR_state->DeleteTreeNode(*treeNode); -} - -void nsIFrame::DisplayIntrinsicISizeExit(nsIFrame* aFrame, const char* aType, - nscoord aResult, - void* aFrameTreeNode) { - if (!DR_state->mActive) return; - - NS_ASSERTION(aFrame, "non-null frame required"); - if (!aFrameTreeNode) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - char iSize[16]; - DR_state->PrettyUC(aResult, iSize, 16); - printf("Get%sISize=%s\n", aType, iSize); - } - DR_state->DeleteTreeNode(*treeNode); -} - -void nsIFrame::DisplayIntrinsicSizeExit(nsIFrame* aFrame, const char* aType, - nsSize aResult, void* aFrameTreeNode) { - if (!DR_state->mActive) return; - - NS_ASSERTION(aFrame, "non-null frame required"); - if (!aFrameTreeNode) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - - char width[16]; - char height[16]; - DR_state->PrettyUC(aResult.width, width, 16); - DR_state->PrettyUC(aResult.height, height, 16); - printf("Get%sSize=%s,%s\n", aType, width, height); - } - DR_state->DeleteTreeNode(*treeNode); -} - -/* static */ -void nsIFrame::DisplayReflowStartup() { DR_state = new DR_State(); } - -/* static */ -void nsIFrame::DisplayReflowShutdown() { - delete DR_state; - DR_state = nullptr; -} - -void DR_cookie::Change() const { - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)mValue; - if (treeNode && treeNode->mDisplay) { - DisplayReflowEnterPrint(mPresContext, mFrame, mReflowInput, *treeNode, - true); - } -} - -/* static */ -void* ReflowInput::DisplayInitConstraintsEnter(nsIFrame* aFrame, - ReflowInput* aState, - nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight, - const nsMargin* aBorder, - const nsMargin* aPadding) { - MOZ_ASSERT(aFrame, "non-null frame required"); - MOZ_ASSERT(aState, "non-null state required"); - - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, aState); - if (treeNode && treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - - printf("InitConstraints parent=%p", (void*)aState->mParentReflowInput); - - char width[16]; - char height[16]; - - DR_state->PrettyUC(aContainingBlockWidth, width, 16); - DR_state->PrettyUC(aContainingBlockHeight, height, 16); - printf(" cb=%s,%s", width, height); - - DR_state->PrettyUC(aState->AvailableWidth(), width, 16); - DR_state->PrettyUC(aState->AvailableHeight(), height, 16); - printf(" as=%s,%s", width, height); - - DR_state->PrintMargin("b", aBorder); - DR_state->PrintMargin("p", aPadding); - putchar('\n'); - } - return treeNode; -} - -/* static */ -void ReflowInput::DisplayInitConstraintsExit(nsIFrame* aFrame, - ReflowInput* aState, - void* aValue) { - MOZ_ASSERT(aFrame, "non-null frame required"); - MOZ_ASSERT(aState, "non-null state required"); - - if (!DR_state->mActive) return; - if (!aValue) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aValue; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - char cmiw[16], cw[16], cmxw[16], cmih[16], ch[16], cmxh[16]; - DR_state->PrettyUC(aState->ComputedMinWidth(), cmiw, 16); - DR_state->PrettyUC(aState->ComputedWidth(), cw, 16); - DR_state->PrettyUC(aState->ComputedMaxWidth(), cmxw, 16); - DR_state->PrettyUC(aState->ComputedMinHeight(), cmih, 16); - DR_state->PrettyUC(aState->ComputedHeight(), ch, 16); - DR_state->PrettyUC(aState->ComputedMaxHeight(), cmxh, 16); - printf("InitConstraints= cw=(%s <= %s <= %s) ch=(%s <= %s <= %s)", cmiw, cw, - cmxw, cmih, ch, cmxh); - const nsMargin m = aState->ComputedPhysicalOffsets(); - DR_state->PrintMargin("co", &m); - putchar('\n'); - } - DR_state->DeleteTreeNode(*treeNode); -} - -/* static */ -void* SizeComputationInput::DisplayInitOffsetsEnter( - nsIFrame* aFrame, SizeComputationInput* aState, nscoord aPercentBasis, - WritingMode aCBWritingMode, const nsMargin* aBorder, - const nsMargin* aPadding) { - MOZ_ASSERT(aFrame, "non-null frame required"); - MOZ_ASSERT(aState, "non-null state required"); - - if (!DR_state->mInited) DR_state->Init(); - if (!DR_state->mActive) return nullptr; - - // aState is not necessarily a ReflowInput - DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr); - if (treeNode && treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - - char pctBasisStr[16]; - DR_state->PrettyUC(aPercentBasis, pctBasisStr, 16); - printf("InitOffsets pct_basis=%s", pctBasisStr); - - DR_state->PrintMargin("b", aBorder); - DR_state->PrintMargin("p", aPadding); - putchar('\n'); - } - return treeNode; -} - -/* static */ -void SizeComputationInput::DisplayInitOffsetsExit(nsIFrame* aFrame, - SizeComputationInput* aState, - void* aValue) { - MOZ_ASSERT(aFrame, "non-null frame required"); - MOZ_ASSERT(aState, "non-null state required"); - - if (!DR_state->mActive) return; - if (!aValue) return; - - DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aValue; - if (treeNode->mDisplay) { - DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent); - printf("InitOffsets="); - const auto m = aState->ComputedPhysicalMargin(); - DR_state->PrintMargin("m", &m); - const auto p = aState->ComputedPhysicalPadding(); - DR_state->PrintMargin("p", &p); - const auto bp = aState->ComputedPhysicalBorderPadding(); - DR_state->PrintMargin("b+p", &bp); - putchar('\n'); - } - DR_state->DeleteTreeNode(*treeNode); -} - -// End Display Reflow - // Validation of SideIsVertical. # define CASE(side, result) \ static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong") diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 16f3d17d64..6e55ebe1c7 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -937,6 +937,8 @@ class nsIFrame : public nsQueryFrame { already_AddRefed<ComputedStyle> ComputeHighlightSelectionStyle( nsAtom* aHighlightName); + already_AddRefed<ComputedStyle> ComputeTargetTextStyle() const; + /** * Accessor functions for geometric parent. */ @@ -1586,6 +1588,11 @@ class nsIFrame : public nsQueryFrame { bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const; /** + * Returns one em unit, adjusted for font inflation if needed, in app units. + */ + nscoord OneEmInAppUnits() const; + + /** * `GetNaturalBaselineBOffset`, but determines the baseline sharing group * through `GetDefaultBaselineSharingGroup` (If not specified), assuming line * layout context, and never fails, returning a synthesized baseline through @@ -3932,6 +3939,9 @@ class nsIFrame : public nsQueryFrame { public: // given a frame five me the first/last leaf available // XXX Robert O'Callahan wants to move these elsewhere + // FIXME: Only GetLastLeaf() never returns a leaf frame in native anonymous + // subtrees under aFrame. However, GetFirstLeaf() may return a leaf frame + // in a native anonymous subtree. static void GetLastLeaf(nsIFrame** aFrame); static void GetFirstLeaf(nsIFrame** aFrame); @@ -5482,25 +5492,6 @@ class nsIFrame : public nsQueryFrame { // NS_FRAME_IS_DIRTY bit set static void VerifyDirtyBitSet(const nsFrameList& aFrameList); - // Display Reflow Debugging - static void* DisplayReflowEnter(nsPresContext* aPresContext, nsIFrame* aFrame, - const ReflowInput& aReflowInput); - static void* DisplayLayoutEnter(nsIFrame* aFrame); - static void* DisplayIntrinsicISizeEnter(nsIFrame* aFrame, const char* aType); - static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame, const char* aType); - static void DisplayReflowExit(nsPresContext* aPresContext, nsIFrame* aFrame, - ReflowOutput& aMetrics, - const nsReflowStatus& aStatus, - void* aFrameTreeNode); - static void DisplayLayoutExit(nsIFrame* aFrame, void* aFrameTreeNode); - static void DisplayIntrinsicISizeExit(nsIFrame* aFrame, const char* aType, - nscoord aResult, void* aFrameTreeNode); - static void DisplayIntrinsicSizeExit(nsIFrame* aFrame, const char* aType, - nsSize aResult, void* aFrameTreeNode); - - static void DisplayReflowStartup(); - static void DisplayReflowShutdown(); - static mozilla::LazyLogModule sFrameLogModule; #endif }; diff --git a/layout/generic/nsIFrameInlines.h b/layout/generic/nsIFrameInlines.h index e187f0dfb0..f53ba607c0 100644 --- a/layout/generic/nsIFrameInlines.h +++ b/layout/generic/nsIFrameInlines.h @@ -36,7 +36,7 @@ bool nsIFrame::IsFlexOrGridItem() const { bool nsIFrame::IsMasonry(mozilla::LogicalAxis aAxis) const { MOZ_DIAGNOSTIC_ASSERT(IsGridContainerFrame()); - return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock + return HasAnyStateBits(aAxis == mozilla::LogicalAxis::Block ? NS_STATE_GRID_IS_ROW_MASONRY : NS_STATE_GRID_IS_COL_MASONRY); } diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index c1e69df6c9..91d8430b60 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1476,8 +1476,6 @@ nscoord nsImageFrame::GetContinuationOffset() const { nscoord nsImageFrame::GetMinISize(gfxContext* aRenderingContext) { // XXX The caller doesn't account for constraints of the block-size, // min-block-size, and max-block-size properties. - DebugOnly<nscoord> result; - DISPLAY_MIN_INLINE_SIZE(this, result); EnsureIntrinsicSizeAndRatio(); const auto& iSize = GetWritingMode().IsVertical() ? mIntrinsicSize.height : mIntrinsicSize.width; @@ -1487,8 +1485,6 @@ nscoord nsImageFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord nsImageFrame::GetPrefISize(gfxContext* aRenderingContext) { // XXX The caller doesn't account for constraints of the block-size, // min-block-size, and max-block-size properties. - DebugOnly<nscoord> result; - DISPLAY_PREF_INLINE_SIZE(this, result); EnsureIntrinsicSizeAndRatio(); const auto& iSize = GetWritingMode().IsVertical() ? mIntrinsicSize.height : mIntrinsicSize.width; @@ -1526,7 +1522,6 @@ void nsImageFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsImageFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE( NS_FRAME_TRACE_CALLS, diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 7a99ecbe5d..b481c71827 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -270,7 +270,6 @@ void nsInlineFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsInlineFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); if (!aReflowInput.mLineLayout) { diff --git a/layout/generic/nsLeafFrame.cpp b/layout/generic/nsLeafFrame.cpp index 2688da3d4b..6125f6b800 100644 --- a/layout/generic/nsLeafFrame.cpp +++ b/layout/generic/nsLeafFrame.cpp @@ -24,18 +24,12 @@ void nsLeafFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, /* virtual */ nscoord nsLeafFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_MIN_INLINE_SIZE(this, result); - result = GetIntrinsicISize(); - return result; + return GetIntrinsicISize(); } /* virtual */ nscoord nsLeafFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_PREF_INLINE_SIZE(this, result); - result = GetIntrinsicISize(); - return result; + return GetIntrinsicISize(); } /* virtual */ diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp index 18051aa69a..53a6914030 100644 --- a/layout/generic/nsLineBox.cpp +++ b/layout/generic/nsLineBox.cpp @@ -217,7 +217,7 @@ void nsLineBox::List(FILE* out, const char* aPrefix, IsPreviousMarginDirty() ? "prevmargindirty" : "prevmarginclean", IsImpactedByFloat() ? "impacted" : "not-impacted", IsLineWrapped() ? "wrapped" : "not-wrapped", - HasForcedLineBreak() ? "forced-break" : "no-break", + HasForcedLineBreakAfter() ? "forced-break-after" : "no-break", StyleClearToString(FloatClearTypeBefore()), StyleClearToString(FloatClearTypeAfter())); diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index d46cf9604a..e35f36a481 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -238,42 +238,40 @@ class nsLineBox final : public nsLineLink { } } - // mHasForcedLineBreak bit & mFloatClearType value - // Break information is applied *before* the line if the line is a block, - // or *after* the line if the line is an inline. - bool HasForcedLineBreak() const { return mFlags.mHasForcedLineBreak; } + // mHasForcedLineBreakAfter bit & mFloatClearType value void ClearForcedLineBreak() { - mFlags.mHasForcedLineBreak = false; + mFlags.mHasForcedLineBreakAfter = false; mFlags.mFloatClearType = mozilla::StyleClear::None; } - bool HasForcedLineBreakBefore() const { - return IsBlock() && HasForcedLineBreak(); + bool HasFloatClearTypeBefore() const { + return FloatClearTypeBefore() != mozilla::StyleClear::None; } - void SetForcedLineBreakBefore(mozilla::StyleClear aClearType) { - MOZ_ASSERT(IsBlock(), "Only blocks have break-before"); + void SetFloatClearTypeBefore(mozilla::StyleClear aClearType) { + MOZ_ASSERT(IsBlock(), "Only block lines have break-before status!"); MOZ_ASSERT(aClearType != mozilla::StyleClear::None, "Only StyleClear:Left/Right/Both are allowed before a line"); - mFlags.mHasForcedLineBreak = true; mFlags.mFloatClearType = aClearType; } mozilla::StyleClear FloatClearTypeBefore() const { - return IsBlock() ? FloatClearType() : mozilla::StyleClear::None; + return IsBlock() ? mFlags.mFloatClearType : mozilla::StyleClear::None; } bool HasForcedLineBreakAfter() const { - return IsInline() && HasForcedLineBreak(); + MOZ_ASSERT(IsInline() || !mFlags.mHasForcedLineBreakAfter, + "A block line shouldn't set mHasForcedLineBreakAfter bit!"); + return IsInline() && mFlags.mHasForcedLineBreakAfter; } void SetForcedLineBreakAfter(mozilla::StyleClear aClearType) { - MOZ_ASSERT(IsInline(), "Only inlines have break-after"); - mFlags.mHasForcedLineBreak = true; + MOZ_ASSERT(IsInline(), "Only inline lines have break-after status!"); + mFlags.mHasForcedLineBreakAfter = true; mFlags.mFloatClearType = aClearType; } bool HasFloatClearTypeAfter() const { - return IsInline() && FloatClearType() != mozilla::StyleClear::None; + return FloatClearTypeAfter() != mozilla::StyleClear::None; } mozilla::StyleClear FloatClearTypeAfter() const { - return IsInline() ? FloatClearType() : mozilla::StyleClear::None; + return IsInline() ? mFlags.mFloatClearType : mozilla::StyleClear::None; } // mCarriedOutBEndMargin value @@ -316,7 +314,7 @@ class nsLineBox final : public nsLineLink { nsRect InkOverflowRect() const { return GetOverflowArea(mozilla::OverflowType::Ink); } - nsRect ScrollableOverflowRect() { + nsRect ScrollableOverflowRect() const { return GetOverflowArea(mozilla::OverflowType::Scrollable); } @@ -520,11 +518,15 @@ class nsLineBox final : public nsLineLink { // Has this line moved to a different fragment of the block since // the last time it was reflowed? bool mMovedFragments : 1; - // mHasForcedLineBreak indicates that this line has either a break-before or - // a break-after. - bool mHasForcedLineBreak : 1; - // mFloatClearType indicates that there's a float clearance before or after - // this line. + // mHasForcedLineBreakAfter indicates that this *inline* line has a + // break-after status due to a float clearance or ending with <br>. A block + // line shouldn't set this bit. + // + // Note: This bit is unrelated to CSS break-after property because it is all + // about line break-after for inline-level boxes. + bool mHasForcedLineBreakAfter : 1; + // mFloatClearType indicates that there's a float clearance before a block + // line, or after an inline line. mozilla::StyleClear mFloatClearType; }; @@ -570,8 +572,6 @@ class nsLineBox final : public nsLineLink { FlagBits mFlags; }; - mozilla::StyleClear FloatClearType() const { return mFlags.mFloatClearType; }; - union { ExtraData* mData; ExtraBlockData* mBlockData; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index ab6924faa4..be6f64f1fe 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -1713,10 +1713,10 @@ void nsLineLayout::AdjustLeadings(nsIFrame* spanFrame, PerSpanData* psd, if (aStyleText->HasEffectiveTextEmphasis()) { nscoord bsize = GetBSizeOfEmphasisMarks(spanFrame, aInflation); LogicalSide side = aStyleText->TextEmphasisSide(mRootSpan->mWritingMode); - if (side == eLogicalSideBStart) { + if (side == LogicalSide::BStart) { requiredStartLeading += bsize; } else { - MOZ_ASSERT(side == eLogicalSideBEnd, + MOZ_ASSERT(side == LogicalSide::BEnd, "emphasis marks must be in block axis"); requiredEndLeading += bsize; } @@ -2341,7 +2341,7 @@ void nsLineLayout::VerticalAlignFrames(PerSpanData* psd) { delta = emphasisHeight; } LogicalSide side = mStyleText->TextEmphasisSide(lineWM); - if (side == eLogicalSideBStart) { + if (side == LogicalSide::BStart) { blockStart -= delta; } else { blockEnd += delta; diff --git a/layout/generic/nsPageContentFrame.cpp b/layout/generic/nsPageContentFrame.cpp index 11e634894d..1c82ca1523 100644 --- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -35,7 +35,6 @@ void nsPageContentFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); MOZ_ASSERT(mPD, "Need a pointer to nsSharedPageData before reflow starts"); diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index fb9cfa2e81..de573962af 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -9,6 +9,7 @@ #include "mozilla/AppUnits.h" #include "mozilla/PresShell.h" #include "mozilla/StaticPrefs_layout.h" +#include "mozilla/StaticPrefs_print.h" #include "mozilla/gfx/2D.h" #include "mozilla/intl/Segmenter.h" #include "gfxContext.h" @@ -213,7 +214,6 @@ void nsPageFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsPageFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); MOZ_ASSERT(mPD, "Need a pointer to nsSharedPageData before reflow starts"); @@ -540,6 +540,69 @@ static std::tuple<uint32_t, uint32_t> GetRowAndColFromIdx(uint32_t aIdxOnSheet, return {aIdxOnSheet / aNumCols, aIdxOnSheet % aNumCols}; } +// The minimum ratio for which we will center the page on the sheet when using +// auto-detect logic. +// Note that this ratio is of the content's size to the sheet size scaled to be +// in content space, and so the actual ratio will always be from 0.0 to 1.0, +// with this marking the smallest ratio we consider a near-miss. +// The ratio of A4 on Letter is 0.915034. A threshold of 0.9 will ensure that +// A4 on Letter works, as well as other near-misses. +// +// The ratio is computed as so: +// scale = min(1, sheetHeight / pageHeight, sheetWidth / pageWidth) +// +// Where pageSize is pageWidth or pageHeight, and sheetSize is sheetWidth or +// sheetHeight, respectively: +// scaledPageSize = pageSize * scale +// ratio = scaledPageSize / sheetSize +// +// A4 (210mm x 297mm) on US Letter (215.9mm x 279.4mm) is derived as so: +// scale = min(1, 215.9 / 210, 279.4 / 297) = 0.9407407407.. +// +// Using the widths: +// scaledPageSize = (210 * 0.940741) = 197.556 +// ratio = 197.556 / 215.9 = 0.915034 +// +// See nsPageFrame::ComputeSinglePPSPageSizeScale for scale calculation, and +// OffsetToCenterPage for ratio calculation. +constexpr float kCenterPageRatioThreshold = 0.9f; + +// Numeric values for the pref "print.center_page_on_sheet" +enum { + kPrintCenterPageOnSheetNever = 0, + kPrintCenterPageOnSheetAlways = 1, + kPrintCenterPageOnSheetAuto = 2 +}; + +// Returns an offset to center the page on the sheet, with a given scale. +// When no centering can/should happen, this will avoid extra calculations and +// return 0.0f. +// This takes into account the value of the pref "print.center_page_on_sheet". +static float OffsetToCenterPage(nscoord aContentSize, nscoord aSheetSize, + float aScale, float aAppUnitsPerPixel) { + MOZ_ASSERT(aScale <= 1.0f && aScale > 0.0f, + "Scale must be in the range (0,1]"); + const unsigned centerPagePref = StaticPrefs::print_center_page_on_sheet(); + if (centerPagePref == kPrintCenterPageOnSheetNever) { + return 0.0f; + } + + // Determine the ratio of scaled page to the sheet size. + const float sheetSize = + NSAppUnitsToFloatPixels(aSheetSize, aAppUnitsPerPixel); + const float scaledContentSize = + NSAppUnitsToFloatPixels(aContentSize, aAppUnitsPerPixel) * aScale; + const float ratio = scaledContentSize / sheetSize; + + // If the ratio is within the threshold, or the pref indicates we should + // always center the page, return half the difference to form the offset. + if (centerPagePref == kPrintCenterPageOnSheetAlways || + ratio >= kCenterPageRatioThreshold) { + return (sheetSize - scaledContentSize) * 0.5f; + } + return 0.0f; +} + // Helper for BuildDisplayList: static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform( const nsIFrame* aFrame, float aAppUnitsPerPixel) { @@ -561,8 +624,8 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform( gfx::Matrix4x4 transform; if (ppsInfo->mNumPages == 1) { + const nsSize sheetSize = sheetFrame->GetSizeForChildren(); if (rotation != 0.0) { - const nsSize sheetSize = sheetFrame->GetSizeForChildren(); const bool sheetIsPortrait = sheetSize.width < sheetSize.height; const bool rotatingClockwise = rotation > 0.0; @@ -584,7 +647,21 @@ static gfx::Matrix4x4 ComputePagesPerSheetAndPageSizeTransform( NSAppUnitsToFloatPixels(-y, aAppUnitsPerPixel), 0); } - float scale = pageFrame->ComputeSinglePPSPageSizeScale(contentPageSize); + // If the difference in horizontal size, after scaling, is relatively small + // then center the page on the sheet. + const float scale = + pageFrame->ComputeSinglePPSPageSizeScale(contentPageSize); + const float centeringOffset = OffsetToCenterPage( + contentPageSize.width, sheetSize.width, scale, aAppUnitsPerPixel); + + // Only bother with the translation if it is at least one pixel. + // It's possible for a mismatch in the paper size reported by the print + // server and the paper size from Gecko to lead to small offsets, or + // even (in combination with floating point error) a very small negative + // offset. Do not apply an offset in those cases. + if (centeringOffset >= 1.0f) { + transform.PreTranslate(centeringOffset, 0, 0); + } transform.PreScale(scale, scale, 1); return transform; } @@ -937,7 +1014,6 @@ void nsPageBreakFrame::Reflow(nsPresContext* aPresContext, const ReflowInput& aReflowInput, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); // Override reflow, since we don't want to deal with what our diff --git a/layout/generic/nsPageSequenceFrame.cpp b/layout/generic/nsPageSequenceFrame.cpp index a3348433cb..cd3c2cd6a5 100644 --- a/layout/generic/nsPageSequenceFrame.cpp +++ b/layout/generic/nsPageSequenceFrame.cpp @@ -266,7 +266,6 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext, MOZ_ASSERT(aPresContext->IsRootPaginatedDocument(), "A Page Sequence is only for real pages"); DO_GLOBAL_REFLOW_COUNT("nsPageSequenceFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE_REFLOW_IN("nsPageSequenceFrame::Reflow"); diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index f6b4d53193..aad2c816e5 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -124,7 +124,6 @@ void nsPlaceholderFrame::Reflow(nsPresContext* aPresContext, MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); aDesiredSize.ClearSize(); } diff --git a/layout/generic/nsRubyBaseContainerFrame.cpp b/layout/generic/nsRubyBaseContainerFrame.cpp index 6e29152bc9..50b08b6f5b 100644 --- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -275,7 +275,6 @@ void nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsRubyBaseContainerFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); if (!aReflowInput.mLineLayout) { diff --git a/layout/generic/nsRubyFrame.cpp b/layout/generic/nsRubyFrame.cpp index d7da5bc321..d6119f44fb 100644 --- a/layout/generic/nsRubyFrame.cpp +++ b/layout/generic/nsRubyFrame.cpp @@ -94,7 +94,6 @@ void nsRubyFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsRubyFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); if (!aReflowInput.mLineLayout) { @@ -345,11 +344,11 @@ void nsRubyFrame::ReflowSegment(nsPresContext* aPresContext, : 0); position = offsetRect.Origin(lineWM) + offset; aReflowInput.mLineLayout->AdvanceICoord(size.ISize(lineWM)); - } else if (logicalSide == eLogicalSideBStart) { + } else if (logicalSide == LogicalSide::BStart) { offsetRect.BStart(lineWM) -= size.BSize(lineWM); offsetRect.BSize(lineWM) += size.BSize(lineWM); position = offsetRect.Origin(lineWM); - } else if (logicalSide == eLogicalSideBEnd) { + } else if (logicalSide == LogicalSide::BEnd) { position = offsetRect.Origin(lineWM) + LogicalPoint(lineWM, 0, offsetRect.BSize(lineWM)); offsetRect.BSize(lineWM) += size.BSize(lineWM); diff --git a/layout/generic/nsRubyTextContainerFrame.cpp b/layout/generic/nsRubyTextContainerFrame.cpp index 855d7c1825..8494b36a28 100644 --- a/layout/generic/nsRubyTextContainerFrame.cpp +++ b/layout/generic/nsRubyTextContainerFrame.cpp @@ -105,7 +105,6 @@ void nsRubyTextContainerFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsRubyTextContainerFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); // Although a ruby text container may have continuations, returning diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index bfbd7763a9..69b4042033 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -555,7 +555,6 @@ nsresult nsSubDocumentFrame::GetFrameName(nsAString& aResult) const { /* virtual */ nscoord nsSubDocumentFrame::GetMinISize(gfxContext* aRenderingContext) { nscoord result; - DISPLAY_MIN_INLINE_SIZE(this, result); nsCOMPtr<nsIObjectLoadingContent> iolc = do_QueryInterface(mContent); auto olc = static_cast<nsObjectLoadingContent*>(iolc.get()); @@ -575,18 +574,13 @@ nscoord nsSubDocumentFrame::GetMinISize(gfxContext* aRenderingContext) { /* virtual */ nscoord nsSubDocumentFrame::GetPrefISize(gfxContext* aRenderingContext) { - nscoord result; - DISPLAY_PREF_INLINE_SIZE(this, result); - // If the subdocument is an SVG document, then in theory we want to return // the same thing that SVGOuterSVGFrame::GetPrefISize does. That method // has some special handling of percentage values to avoid unhelpful zero // sizing in the presence of orthogonal writing modes. We don't bother // with that for SVG documents in <embed> and <object>, since that special // handling doesn't look up across document boundaries anyway. - result = GetIntrinsicISize(); - - return result; + return GetIntrinsicISize(); } /* virtual */ @@ -676,7 +670,6 @@ void nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE( NS_FRAME_TRACE_CALLS, diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 9afefc5c28..0ad527e842 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1929,8 +1929,8 @@ bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, // Map inline-end and inline-start to physical sides for checking presence // of non-zero margin/border/padding. - Side side1 = wm.PhysicalSide(eLogicalSideIEnd); - Side side2 = wm.PhysicalSide(eLogicalSideIStart); + Side side1 = wm.PhysicalSide(LogicalSide::IEnd); + Side side2 = wm.PhysicalSide(LogicalSide::IStart); // If the frames have an embedding level that is opposite to the writing // mode, we need to swap which sides we're checking. if (aFrame1->GetEmbeddingLevel().IsRTL() == wm.IsBidiLTR()) { @@ -3611,6 +3611,20 @@ void nsTextFrame::PropertyProvider::GetSpacing(Range aRange, !(mTextRun->GetFlags2() & nsTextFrameUtils::Flags::HasTab)); } +static bool CanAddSpacingBefore(const gfxTextRun* aTextRun, uint32_t aOffset, + bool aNewlineIsSignificant) { + const auto* g = aTextRun->GetCharacterGlyphs(); + MOZ_ASSERT(aOffset < aTextRun->GetLength()); + if (aNewlineIsSignificant && g[aOffset].CharIsNewline()) { + return false; + } + if (!aOffset) { + return true; + } + return g[aOffset].IsClusterStart() && g[aOffset].IsLigatureGroupStart() && + !g[aOffset - 1].CharIsFormattingControl() && !g[aOffset].CharIsTab(); +} + static bool CanAddSpacingAfter(const gfxTextRun* aTextRun, uint32_t aOffset, bool aNewlineIsSignificant) { const auto* g = aTextRun->GetCharacterGlyphs(); @@ -3683,14 +3697,45 @@ void nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange, nsSkipCharsRunIterator run( start, nsSkipCharsRunIterator::LENGTH_UNSKIPPED_ONLY, aRange.Length()); bool newlineIsSignificant = mTextStyle->NewlineIsSignificant(mFrame); + // Which letter-spacing model are we using? + // 0 - Gecko legacy model, spacing added to trailing side of letter + // 1 - WebKit/Blink-compatible, spacing added to right-hand side + // 2 - Symmetrical spacing, half added to each side + gfxFloat before, after; + switch (StaticPrefs::layout_css_letter_spacing_model()) { + default: // use Gecko legacy behavior if pref value is unknown + case 0: + before = 0.0; + after = mLetterSpacing; + break; + case 1: + if (mTextRun->IsRightToLeft()) { + before = mLetterSpacing; + after = 0.0; + } else { + before = 0.0; + after = mLetterSpacing; + } + break; + case 2: + before = mLetterSpacing / 2.0; + after = mLetterSpacing - before; + break; + } while (run.NextRun()) { uint32_t runOffsetInSubstring = run.GetSkippedOffset() - aRange.start; gfxSkipCharsIterator iter = run.GetPos(); for (int32_t i = 0; i < run.GetRunLength(); ++i) { - if (CanAddSpacingAfter(mTextRun, run.GetSkippedOffset() + i, + if (before != 0.0 && + CanAddSpacingBefore(mTextRun, run.GetSkippedOffset() + i, + newlineIsSignificant)) { + aSpacing[runOffsetInSubstring + i].mBefore += before; + } + if (after != 0.0 && + CanAddSpacingAfter(mTextRun, run.GetSkippedOffset() + i, newlineIsSignificant)) { // End of a cluster, not in a ligature: put letter-spacing after it - aSpacing[runOffsetInSubstring + i].mAfter += mLetterSpacing; + aSpacing[runOffsetInSubstring + i].mAfter += after; } if (IsCSSWordSpacingSpace(mFrag, i + run.GetOriginalOffset(), mFrame, mTextStyle)) { @@ -5050,25 +5095,25 @@ nsRect nsTextFrame::UpdateTextEmphasis(WritingMode aWM, : do_AddRef(aProvider.GetFontMetrics()); // When the writing mode is vertical-lr the line is inverted, and thus // the ascent and descent are swapped. - nscoord absOffset = (side == eLogicalSideBStart) != aWM.IsLineInverted() + nscoord absOffset = (side == LogicalSide::BStart) != aWM.IsLineInverted() ? baseFontMetrics->MaxAscent() + fm->MaxDescent() : baseFontMetrics->MaxDescent() + fm->MaxAscent(); RubyBlockLeadings leadings; if (nsRubyFrame* ruby = FindFurthestInlineRubyAncestor(this)) { leadings = ruby->GetBlockLeadings(); } - if (side == eLogicalSideBStart) { + if (side == LogicalSide::BStart) { info->baselineOffset = -absOffset - leadings.mStart; overflowRect.BStart(aWM) = -overflowRect.BSize(aWM) - leadings.mStart; } else { - MOZ_ASSERT(side == eLogicalSideBEnd); + MOZ_ASSERT(side == LogicalSide::BEnd); info->baselineOffset = absOffset + leadings.mEnd; overflowRect.BStart(aWM) = frameSize.BSize(aWM) + leadings.mEnd; } // If text combined, fix the gap between the text frame and its parent. if (isTextCombined) { nscoord gap = (baseFontMetrics->MaxHeight() - frameSize.BSize(aWM)) / 2; - overflowRect.BStart(aWM) += gap * (side == eLogicalSideBStart ? -1 : 1); + overflowRect.BStart(aWM) += gap * (side == LogicalSide::BStart ? -1 : 1); } SetProperty(EmphasisMarkProperty(), info); @@ -5676,6 +5721,10 @@ bool nsTextFrame::GetSelectionTextColors(SelectionType aSelectionType, aHighlightName, aBackground); return hasForeground || hasBackground; } + case SelectionType::eTargetText: { + aTextPaintStyle.GetTargetTextColors(aForeground, aBackground); + return true; + } case SelectionType::eURLSecondary: aTextPaintStyle.GetURLSecondaryColor(aForeground); *aBackground = NS_RGBA(0, 0, 0, 0); @@ -9216,7 +9265,6 @@ void nsTextFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsTextFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); InvalidateSelectionState(); diff --git a/layout/generic/nsTextPaintStyle.cpp b/layout/generic/nsTextPaintStyle.cpp index e97a059b07..f29fa753d0 100644 --- a/layout/generic/nsTextPaintStyle.cpp +++ b/layout/generic/nsTextPaintStyle.cpp @@ -213,6 +213,24 @@ void nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor, *aBackColor = NS_TRANSPARENT; } +void nsTextPaintStyle::GetTargetTextColors(nscolor* aForeColor, + nscolor* aBackColor) { + NS_ASSERTION(aForeColor, "aForeColor is null"); + NS_ASSERTION(aBackColor, "aBackColor is null"); + const RefPtr<const ComputedStyle> targetTextStyle = + mFrame->ComputeTargetTextStyle(); + if (targetTextStyle) { + *aForeColor = targetTextStyle->GetVisitedDependentColor( + &nsStyleText::mWebkitTextFillColor); + *aBackColor = targetTextStyle->GetVisitedDependentColor( + &nsStyleBackground::mBackgroundColor); + return; + } + // XXX(:jjaschke): Before shipping this feature, a sensible set of colors must + // be set (Bug 1867940). + // in the meantime, use the colors of find selection. + GetHighlightColors(aForeColor, aBackColor); +} bool nsTextPaintStyle::GetCustomHighlightTextColor(nsAtom* aHighlightName, nscolor* aForeColor) { NS_ASSERTION(aForeColor, "aForeColor is null"); diff --git a/layout/generic/nsTextPaintStyle.h b/layout/generic/nsTextPaintStyle.h index adf28fdad8..94cd3cf322 100644 --- a/layout/generic/nsTextPaintStyle.h +++ b/layout/generic/nsTextPaintStyle.h @@ -65,6 +65,7 @@ class MOZ_STACK_CLASS nsTextPaintStyle { */ bool GetSelectionColors(nscolor* aForeColor, nscolor* aBackColor); void GetHighlightColors(nscolor* aForeColor, nscolor* aBackColor); + void GetTargetTextColors(nscolor* aForeColor, nscolor* aBackColor); // Computes colors for custom highlights. // Returns false if there are no rules associated with `aHighlightName`. bool GetCustomHighlightTextColor(nsAtom* aHighlightName, nscolor* aForeColor); diff --git a/layout/generic/nsTextRunTransformations.cpp b/layout/generic/nsTextRunTransformations.cpp index d18a7ec293..de9fd31fda 100644 --- a/layout/generic/nsTextRunTransformations.cpp +++ b/layout/generic/nsTextRunTransformations.cpp @@ -80,6 +80,26 @@ bool nsTransformedTextRun::SetPotentialLineBreaks(Range aRange, return changed; } +void nsTransformedTextRun::SetEmergencyWrapPositions() { + // This parallels part of what gfxShapedText::SetupClusterBoundaries() does + // for normal textruns. + bool prevWasHyphen = false; + for (uint32_t pos : IntegerRange(mString.Length())) { + const char16_t ch = mString[pos]; + if (prevWasHyphen) { + if (nsContentUtils::IsAlphanumeric(ch)) { + mCharacterGlyphs[pos].SetCanBreakBefore( + CompressedGlyph::FLAG_BREAK_TYPE_EMERGENCY_WRAP); + } + prevWasHyphen = false; + } + if (nsContentUtils::IsHyphen(ch) && pos && + nsContentUtils::IsAlphanumeric(mString[pos - 1])) { + prevWasHyphen = true; + } + } +} + size_t nsTransformedTextRun::SizeOfExcludingThis( mozilla::MallocSizeOf aMallocSizeOf) { size_t total = gfxTextRun::SizeOfExcludingThis(aMallocSizeOf); diff --git a/layout/generic/nsTextRunTransformations.h b/layout/generic/nsTextRunTransformations.h index 915211c6af..6bcf26a8c0 100644 --- a/layout/generic/nsTextRunTransformations.h +++ b/layout/generic/nsTextRunTransformations.h @@ -202,7 +202,10 @@ class nsTransformedTextRun final : public gfxTextRun { mOwnsFactory(aOwnsFactory), mNeedsRebuild(true) { mCharacterGlyphs = reinterpret_cast<CompressedGlyph*>(this + 1); + SetEmergencyWrapPositions(); } + + void SetEmergencyWrapPositions(); }; /** diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index d5bcc45969..e003058c3e 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -226,7 +226,6 @@ void nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, nsReflowStatus& aStatus) { MarkInReflow(); DO_GLOBAL_REFLOW_COUNT("nsVideoFrame"); - DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus); MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); NS_FRAME_TRACE( NS_FRAME_TRACE_CALLS, @@ -375,14 +374,9 @@ nsIFrame::SizeComputationResult nsVideoFrame::ComputeSize( } nscoord nsVideoFrame::GetMinISize(gfxContext* aRenderingContext) { - nscoord result; - // Bind the result variable to a RAII-based debug object - the variable - // therefore must match the function's return value. - DISPLAY_MIN_INLINE_SIZE(this, result); // This call handles size-containment nsSize size = GetIntrinsicSize().ToSize().valueOr(nsSize()); - result = GetWritingMode().IsVertical() ? size.height : size.width; - return result; + return GetWritingMode().IsVertical() ? size.height : size.width; } nscoord nsVideoFrame::GetPrefISize(gfxContext* aRenderingContext) { diff --git a/layout/generic/test/mochitest.toml b/layout/generic/test/mochitest.toml index 5c06c90eb7..dcaac3de7a 100644 --- a/layout/generic/test/mochitest.toml +++ b/layout/generic/test/mochitest.toml @@ -12,6 +12,7 @@ support-files = [ "file_SlowTallImage.sjs", "bug1174521.html", "!/gfx/layers/apz/test/mochitest/apz_test_utils.js", + "selection_cross_shadow_boundary_helper.js", ] ["test_bug240933.html"] @@ -265,6 +266,42 @@ support-files = [ ["test_selection_changes_with_middle_mouse_button.html"] +["test_selection_cross_shadow_boundary_1_backward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_1_backward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_1_forward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_1_forward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_2_backward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_2_backward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_2_forward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_2_forward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_multi_ranges_forward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_multi_ranges_forward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_multi_ranges_backward_drag.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + +["test_selection_cross_shadow_boundary_multi_ranges_backward_click.html"] +skip-if = ["release_or_beta"] # requires Selection.getComposedRanges to be enabled (Nightly only) + ["test_selection_doubleclick.html"] ["test_selection_expanding.html"] diff --git a/layout/generic/test/selection_cross_shadow_boundary_helper.js b/layout/generic/test/selection_cross_shadow_boundary_helper.js new file mode 100644 index 0000000000..b2a596a27f --- /dev/null +++ b/layout/generic/test/selection_cross_shadow_boundary_helper.js @@ -0,0 +1,28 @@ +// Helper file for test_selection_cross_shadow_boundary_* related tests + +function drag( + fromTarget, + fromX, + fromY, + toTarget, + toX, + toY, + withAccelKey = false +) { + synthesizeMouse(fromTarget, fromX, fromY, { + type: "mousemove", + accelKey: withAccelKey, + }); + synthesizeMouse(fromTarget, fromX, fromY, { + type: "mousedown", + accelKey: withAccelKey, + }); + synthesizeMouse(toTarget, toX, toY, { + type: "mousemove", + accelKey: withAccelKey, + }); + synthesizeMouse(toTarget, toX, toY, { + type: "mouseup", + accelKey: withAccelKey, + }); +} diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_click.html new file mode 100644 index 0000000000..ee724b344c --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_click.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "<span>InnerText</span>"; + + const inner = host.shadowRoot.firstChild; + const rect = inner.getBoundingClientRect(); + + // Click the bottom right of "InnerText" + synthesizeMouse(inner, rect.width, rect.height, { type: "mousedown"}); + synthesizeMouse(inner, rect.width, rect.height, { type: "mouseup" }); + + // Click the top left of "OuterText" + synthesizeMouse(document.getElementById("outer"), 0, 0, { type: "mousedown" , shiftKey: true}); + synthesizeMouse(document.getElementById("outer"), 0, 0, { type: "mouseup" , shiftKey: true}); + + // Above two clicks should select both "OuterText" and "InnerText" + const sel = document.getSelection().getComposedRanges(host.shadowRoot)[0]; + + // backward selection + is(sel.endContainer, inner.firstChild, "endContainer is the InnerText"); + is(sel.endOffset, 9, "endOffset ends at the last character"); + is(sel.startContainer, outer.firstChild, "startContainer is the OuterText"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer">OuterText</span> + <div id="host"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_drag.html new file mode 100644 index 0000000000..f1737eaefa --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_1_backward_drag.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); + +function run() { + document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "<span>InnerText</span>"; + + const inner = host.shadowRoot.firstChild; + const rect = inner.getBoundingClientRect(); + + // Drag from the bottom right of InnerText to the + // top left of OuterText. + drag( + inner, + rect.width, + rect.height, + document.getElementById("outer"), + 0, + 0); + + // Above drag selects both "OuterText" and "InnerText" + const sel = document.getSelection().getComposedRanges(host.shadowRoot)[0]; + + // backward selection + is(sel.endContainer, inner.firstChild, "endContainer is the InnerText"); + is(sel.endOffset, 9, "endOffset ends at the last character"); + is(sel.startContainer, outer.firstChild, "startContainer is the OuterText"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer">OuterText</span> + <div id="host"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_click.html new file mode 100644 index 0000000000..dcf4f9ad16 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_click.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "<span>InnerText</span>"; + + // Click the top left of "OuterText" + synthesizeMouse(document.getElementById("outer"), 0, 0, { type: "mousedown" }); + synthesizeMouse(document.getElementById("outer"), 0, 0, { type: "mouseup" }); + + // Click the bottom right of "InnerText" + const inner = host.shadowRoot.firstChild; + const rect = inner.getBoundingClientRect(); + synthesizeMouse(inner, rect.width, rect.height, { type: "mousedown", shiftKey: true}); + synthesizeMouse(inner, rect.width, rect.height, { type: "mouseup" , shiftKey: true}); + + // Above two clicks should select both "OuterText" and "InnerText" + const sel = document.getSelection().getComposedRanges(host.shadowRoot)[0]; + + // forward selection + is(sel.startContainer, outer.firstChild, "startContainer is the OuterText"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + is(sel.endContainer, inner.firstChild, "endContainer is the InnerText"); + is(sel.endOffset, 9, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer">OuterText</span> + <div id="host"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_drag.html new file mode 100644 index 0000000000..6a351ff16b --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_1_forward_drag.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "<span>InnerText</span>"; + + const inner = host.shadowRoot.firstChild; + const rect = inner.getBoundingClientRect(); + + // drag from the top left of OuterText + // to the bottom right of InnerText + drag( + document.getElementById("outer"), + 0, + 0, + inner, + rect.width, + rect.height); + + // Above drag selects should select both "OuterText" and "InnerText" + const sel = document.getSelection().getComposedRanges(host.shadowRoot)[0]; + + // forward selection + is(sel.startContainer, outer.firstChild, "startContainer is the OuterText"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + is(sel.endContainer, inner.firstChild, "endContainer is the InnerText"); + is(sel.endOffset, 9, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer">OuterText</span> + <div id="host"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_click.html new file mode 100644 index 0000000000..8df867a0a5 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_click.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); + +function run() { + const root1 = document.getElementById("host1").attachShadow({ mode: "open" }); + root1.innerHTML = "InnerText1"; + + const root2 = document.getElementById("host2").attachShadow({ mode: "open" }); + root2.innerHTML = "<span>InnerText2</span>"; + + + + const inner2 = root2.firstChild; + const rect = inner2.getBoundingClientRect(); + + // Click the bottom right of "InnerText2" + synthesizeMouse(inner2, rect.width, rect.height, { type: "mousedown" }); + synthesizeMouse(inner2, rect.width, rect.height, { type: "mouseup" }); + + // Click the top left of "OuterText1" + synthesizeMouse(document.getElementById("outer1"), 0, 0, { type: "mousedown", shiftKey: true}); + synthesizeMouse(document.getElementById("outer1"), 0, 0, { type: "mouseup" , shiftKey: true}); + + // Above clicks selects should select + // "OuterText1", "OuterText2", "InnerText1" and "InnerText2". + const sel = document.getSelection().getComposedRanges(root2)[0]; + + // backward selection + is(sel.endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(sel.endOffset, 10, "endOffset ends at the last character"); + is(sel.startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"></div> + <span id="outer2">OuterText2</span> + <div id="host2"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_drag.html new file mode 100644 index 0000000000..f79512d35e --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_2_backward_drag.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); + +function run() { + const root1 = document.getElementById("host1").attachShadow({ mode: "open" }); + root1.innerHTML = "InnerText1"; + + const root2 = document.getElementById("host2").attachShadow({ mode: "open" }); + root2.innerHTML = "<span>InnerText2</span>"; + + const inner2 = root2.firstChild; + const rect = inner2.getBoundingClientRect(); + + const outer1 = document.getElementById("outer1"); + // Drag from the bottom right of InnerText2 to + // the top left of OuterText1. + drag( + inner2, + rect.width, + rect.height, + outer1, + 0, + 0); + + // Above drag should selects + // "OuterText1", "OuterText2", "InnerText1" and "InnerText2". + const sel = document.getSelection().getComposedRanges(root2)[0]; + + // backward selection + is(sel.endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(sel.endOffset, 10, "endOffset ends at the last character"); + is(sel.startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"></div> + <span id="outer2">OuterText2</span> + <div id="host2"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_click.html new file mode 100644 index 0000000000..2ca2eaeda9 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_click.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); + +function run() { + const root1 = document.getElementById("host1").attachShadow({ mode: "open" }); + root1.innerHTML = "InnerText1"; + + const root2 = document.getElementById("host2").attachShadow({ mode: "open" }); + root2.innerHTML = "<span>InnerText2</span>"; + + const outer1 = document.getElementById("outer1"); + // Click the top left of "OuterText1" + synthesizeMouse(outer1, 0, 0, { type: "mousedown" }); + synthesizeMouse(outer1, 0, 0, { type: "mouseup" }); + + const inner2 = root2.firstChild; + const rect = inner2.getBoundingClientRect(); + + // Click the bottom right of "InnerText2" + synthesizeMouse(inner2, rect.width, rect.height, { type: "mousedown", shiftKey: true}); + synthesizeMouse(inner2, rect.width, rect.height, { type: "mouseup" , shiftKey: true}); + + // Above clicks should select + // "OuterText1", "OuterText2", "InnerText1" and "InnerText2". + const sel = document.getSelection().getComposedRanges(root2)[0]; + + // forward selection + is(sel.startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + is(sel.endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(sel.endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"></div> + <span id="outer2">OuterText2</span> + <div id="host2"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_drag.html new file mode 100644 index 0000000000..b92108de95 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_2_forward_drag.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); + +function run() { + const root1 = document.getElementById("host1").attachShadow({ mode: "open" }); + root1.innerHTML = "InnerText1"; + + const root2 = document.getElementById("host2").attachShadow({ mode: "open" }); + root2.innerHTML = "<span>InnerText2</span>"; + + const inner2 = root2.firstChild; + const rect = inner2.getBoundingClientRect(); + + const outer1 = document.getElementById("outer1"); + // Drag from the top lef of OuterText1 to the + // bottom right of InnerText2. + drag( + outer1, + 0, + 0, + inner2, + rect.width, + rect.height); + + // Above drag should select + // "OuterText1", "OuterText2", "InnerText1" and "InnerText2". + const sel = document.getSelection().getComposedRanges(root2)[0]; + + // forward selection + is(sel.startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(sel.startOffset, 0, "startOffset starts at the first character"); + is(sel.endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(sel.endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"></div> + <span id="outer2">OuterText2</span> + <div id="host2"></div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_click.html new file mode 100644 index 0000000000..a2a0d0e2be --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_click.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + const inner1 = host1.shadowRoot.querySelector("span"); + const rect1 = inner1.getBoundingClientRect(); + + // Click the bottom right of "InnerText1" + synthesizeMouse(inner1, rect1.width - 1, rect1.height - 1, { type: "mousedown" }); + synthesizeMouse(inner1, rect1.width - 1, rect1.height - 1, { type: "mouseup" }); + + // Click the top left of "OuterText1" + synthesizeMouse(document.getElementById("outer1"), 0, 0, { type: "mousedown", shiftKey: true }); + synthesizeMouse(document.getElementById("outer1"), 0, 0, { type: "mouseup", shiftKey: true }); + + const inner2 = host2.shadowRoot.querySelector("span"); + const rect2 = inner2.getBoundingClientRect(); + + // Click the bottom right of "InnerText2" with accelKey + synthesizeMouse(inner2, rect2.width, rect2.height, { type: "mousedown", accelKey: true}); + synthesizeMouse(inner2, rect2.width, rect2.height, { type: "mouseup" , accelKey: true}); + + // Click the top left of "OuterText2" + synthesizeMouse(document.getElementById("outer2"), 1, 1, { type: "mousedown", shiftKey: true}); + synthesizeMouse(document.getElementById("outer2"), 1, 1, { type: "mouseup", shiftKey: true}); + + const ranges = document.getSelection().getComposedRanges(host1.shadowRoot, host2.shadowRoot); + is(ranges.length, 2, "Above two drag selection should produce two ranges"); + + is(ranges[0].startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(ranges[0].startOffset, 0, "startOffset starts at the first character"); + is(ranges[0].endContainer, inner1.firstChild, "endContainer is the InnerText1"); + is(ranges[0].endOffset, 10, "endOffset ends at the last character"); + + is(ranges[1].startContainer, outer2.firstChild, "startContainer is the OuterText2"); + is(ranges[1].startOffset, 0, "startOffset starts at the first character"); + is(ranges[1].endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(ranges[1].endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"> + <template shadowrootmode="open"> + <span>InnerText1</span> + </template> + </div> + <br> + <span id="outer2">OuterText2</span> + <div id="host2"> + <template shadowrootmode="open"> + <span>InnerText2</span> + </template> + </div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_drag.html new file mode 100644 index 0000000000..317ee4f973 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_backward_drag.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + const inner1 = host1.shadowRoot.querySelector("span"); + const rect1 = inner1.getBoundingClientRect(); + + // drag from the bottom right of InnerText1 + // to the top left of OuterText1 + drag( + inner1, + rect1.width - 1, + rect1.height - 1, + document.getElementById("outer1"), + 1, + 1); + + const inner2 = host2.shadowRoot.querySelector("span"); + const rect2 = inner2.getBoundingClientRect(); + // drag from the bottom right of InnerText2 + // to the top left of OuterText2 + drag( + inner2, + rect2.width, + rect2.height, + document.getElementById("outer2"), + 1, + 1, + true /* accelKey */); + + const ranges = document.getSelection().getComposedRanges(host1.shadowRoot, host2.shadowRoot); + is(ranges.length, 2, "Above two drag selection should produce two ranges"); + + is(ranges[0].startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(ranges[0].startOffset, 0, "startOffset starts at the first character"); + is(ranges[0].endContainer, inner1.firstChild, "endContainer is the InnerText1"); + is(ranges[0].endOffset, 10, "endOffset ends at the last character"); + + is(ranges[1].startContainer, outer2.firstChild, "startContainer is the OuterText2"); + is(ranges[1].startOffset, 0, "startOffset starts at the first character"); + is(ranges[1].endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(ranges[1].endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"> + <template shadowrootmode="open"> + <span>InnerText1</span> + </template> + </div> + <br> + <span id="outer2">OuterText2</span> + <div id="host2"> + <template shadowrootmode="open"> + <span>InnerText2</span> + </template> + </div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_click.html b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_click.html new file mode 100644 index 0000000000..931c01fca0 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_click.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + // Click the top left of "OuterText1" + synthesizeMouse(document.getElementById("outer1"), 1, 1, { type: "mousedown" }); + synthesizeMouse(document.getElementById("outer1"), 1, 1, { type: "mouseup" }); + + const inner1 = host1.shadowRoot.querySelector("span"); + const rect1 = inner1.getBoundingClientRect(); + // Click the bottom right of "InnerText1" + synthesizeMouse(inner1, rect1.width - 1, rect1.height - 1, { type: "mousedown", shiftKey: true}); + synthesizeMouse(inner1, rect1.width - 1, rect1.height - 1, { type: "mouseup" , shiftKey: true}); + + // Click the top left of "OuterText2" with accelKey + synthesizeMouse(document.getElementById("outer2"), 1, 1, { type: "mousedown", accelKey: true}); + synthesizeMouse(document.getElementById("outer2"), 1, 1, { type: "mouseup", accelKey: true}); + + const inner2 = host2.shadowRoot.querySelector("span"); + const rect2 = inner2.getBoundingClientRect(); + // Click the bottom right of "InnerText2" + synthesizeMouse(inner2, rect2.width, rect2.height, { type: "mousedown", shiftKey: true}); + synthesizeMouse(inner2, rect2.width, rect2.height, { type: "mouseup" , shiftKey: true}); + + const ranges = document.getSelection().getComposedRanges(host1.shadowRoot, host2.shadowRoot); + is(ranges.length, 2, "Above two drag selection should produce two ranges"); + + is(ranges[0].startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(ranges[0].startOffset, 0, "startOffset starts at the first character"); + is(ranges[0].endContainer, inner1.firstChild, "endContainer is the InnerText1"); + is(ranges[0].endOffset, 10, "endOffset ends at the last character"); + + is(ranges[1].startContainer, outer2.firstChild, "startContainer is the OuterText2"); + is(ranges[1].startOffset, 0, "startOffset starts at the first character"); + is(ranges[1].endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(ranges[1].endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"> + <template shadowrootmode="open"> + <span>InnerText1</span> + </template> + </div> + <br> + <span id="outer2">OuterText2</span> + <div id="host2"> + <template shadowrootmode="open"> + <span>InnerText2</span> + </template> + </div> +</body> diff --git a/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_drag.html b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_drag.html new file mode 100644 index 0000000000..b45e588685 --- /dev/null +++ b/layout/generic/test/test_selection_cross_shadow_boundary_multi_ranges_forward_drag.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/layout/generic/test/selection_cross_shadow_boundary_helper.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script> +SimpleTest.waitForExplicitFinish(); +function run() { + const inner1 = host1.shadowRoot.querySelector("span"); + const rect1 = inner1.getBoundingClientRect(); + + // drag from the top left of OuterText1 + // to the bottom right of InnerText1 + drag( + document.getElementById("outer1"), + 1, + 1, + inner1, + rect1.width - 1, + rect1.height - 1); + + const inner2 = host2.shadowRoot.querySelector("span"); + const rect2 = inner2.getBoundingClientRect(); + // drag from the top left of OuterText2 + // to the bottom right of InnerText2 + drag( + document.getElementById("outer2"), + 1, + 1, + inner2, + rect2.width, + rect2.height, + true /* accelKey */); + + const ranges = document.getSelection().getComposedRanges(host1.shadowRoot, host2.shadowRoot); + is(ranges.length, 2, "Above two drag selection should produce two ranges"); + + is(ranges[0].startContainer, outer1.firstChild, "startContainer is the OuterText1"); + is(ranges[0].startOffset, 0, "startOffset starts at the first character"); + is(ranges[0].endContainer, inner1.firstChild, "endContainer is the InnerText1"); + is(ranges[0].endOffset, 10, "endOffset ends at the last character"); + + is(ranges[1].startContainer, outer2.firstChild, "startContainer is the OuterText2"); + is(ranges[1].startOffset, 0, "startOffset starts at the first character"); + is(ranges[1].endContainer, inner2.firstChild, "endContainer is the InnerText2"); + is(ranges[1].endOffset, 10, "endOffset ends at the last character"); + + SimpleTest.finish(); +} +</script> +<body onload="SimpleTest.waitForFocus(run);"> + <span id="outer1">OuterText1</span> + <div id="host1"> + <template shadowrootmode="open"> + <span>InnerText1</span> + </template> + </div> + <br> + <span id="outer2">OuterText2</span> + <div id="host2"> + <template shadowrootmode="open"> + <span>InnerText2</span> + </template> + </div> +</body> |