From 3d16d9585346c6def6b4747a768c058379c739ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Mon, 30 Sep 2024 12:18:39 +0000 Subject: [PATCH] Bug 1916988 - Support CSS width/height properties on MathML elements. r=emilio This patch implements support for the width/height properties on MathML elements [1]. The general algorithm from the spec is as follows: (1) The outcome of the math layout is a "math content box". (2) The content box sets its size from computed width/height values. If auto, it's the one of the "math content box". This patch ignores percentage values for now [2] [3]. (3) math content box is shifted so that its inline-start and top edges aligns with the ones of the content box. There are exceptions elements like mfrac and munder/mover/munderover which instead horizontally center the math content box within the content box. For baseline adjustment, we follow what Chromium does, see [4]. (4) Padding+border are added around the content box. Note that we ignore the box-sizing property for now [5]. The patch essentially tweaks the various MathML layout algorithms to perform steps (3) and (4) before the calls to GetBorderPaddingForPlace and InflateReflowAndBoundingMetrics. [1] https://w3c.github.io/mathml-core/#layout-algorithms [2] https://github.com/w3c/mathml-core/issues/76 [3] https://github.com/w3c/mathml-core/issues/77 [4] https://github.com/w3c/mathml-core/issues/259 [5] https://github.com/w3c/mathml-core/issues/257 Below is more information about test coverage: - width-height-001: Verify that width, height, inline-size and block-size properties sets the size of the content box. This test used to verify they are ignored, this patch fixes the `` tag. It also adds a test for the case the specified size is smaller than the content (we force non empty descendants to make sure this content is large enough) and to verify the width is used for the preferred width. - width-height-002, width-height-003: These are reftests visually checking offsets of the math content box within a larger content box (specified by width/height) for the mtext, mrow, mpadded, mfrac, msqrt, mroot, in LTR/RTL modes. In particular they allow to verify some painted elements like fraction bar and radical symbols. - width-height-004: This test more directly checks that the math content box is horizontally centered within a larger content box for munder, mover, munderover and mfrac. This patch extends the test to cover the case when the math content box is wider (i.e. overflowing outside the content box) and removes unnecessary specified height. - width-height-005: New test for other layout algorithm that don't center the math content box, checking inline-start edges of children when a width is specified. We check both LTR/RTL modes and wider/narrower content boxes. - width-height-006: Same but checking the top edges for larger/smaller height and verifying that baseline is perserved. Differential Revision: https://phabricator.services.mozilla.com/D221436 --- layout/mathml/nsMathMLContainerFrame.cpp | 61 +- layout/mathml/nsMathMLContainerFrame.h | 17 + layout/mathml/nsMathMLTokenFrame.cpp | 6 + layout/mathml/nsMathMLmencloseFrame.cpp | 10 +- layout/mathml/nsMathMLmfracFrame.cpp | 12 + layout/mathml/nsMathMLmfracFrame.h | 2 + layout/mathml/nsMathMLmmultiscriptsFrame.cpp | 5 + layout/mathml/nsMathMLmoFrame.cpp | 11 +- layout/mathml/nsMathMLmpaddedFrame.cpp | 10 +- layout/mathml/nsMathMLmrootFrame.cpp | 13 +- layout/mathml/nsMathMLmspaceFrame.cpp | 6 + layout/mathml/nsMathMLmunderoverFrame.cpp | 15 + layout/mathml/nsMathMLmunderoverFrame.h | 2 + .../fractions/frac-bar-003.html.ini | 2 - .../spaces/mspace-width-height-001.html.ini | 12 - .../relations/css-styling/display-2.html.ini | 4 +- .../css-styling/width-height-001.html.ini | 144 ----- .../css-styling/width-height-002.html.ini | 2 - .../css-styling/width-height-003.html.ini | 2 - .../css-styling/width-height-005.html.ini | 6 + .../css-styling/width-height-001.html | 32 +- .../css-styling/width-height-004.html | 63 +- .../css-styling/width-height-005.html | 541 ++++++++++++++++++ .../css-styling/width-height-006.html | 406 +++++++++++++ 24 files changed, 1208 insertions(+), 176 deletions(-) delete mode 100644 testing/web-platform/meta/mathml/presentation-markup/fractions/frac-bar-003.html.ini delete mode 100644 testing/web-platform/meta/mathml/presentation-markup/spaces/mspace-width-height-001.html.ini delete mode 100644 testing/web-platform/meta/mathml/relations/css-styling/width-height-001.html.ini delete mode 100644 testing/web-platform/meta/mathml/relations/css-styling/width-height-002.html.ini delete mode 100644 testing/web-platform/meta/mathml/relations/css-styling/width-height-003.html.ini create mode 100644 testing/web-platform/meta/mathml/relations/css-styling/width-height-005.html.ini create mode 100644 testing/web-platform/tests/mathml/relations/css-styling/width-height-005.html create mode 100644 testing/web-platform/tests/mathml/relations/css-styling/width-height-006.html diff --git a/layout/mathml/nsMathMLContainerFrame.cpp b/layout/mathml/nsMathMLContainerFrame.cpp index 1d1af5ce24413..342bee7fd8697 100644 --- a/layout/mathml/nsMathMLContainerFrame.cpp +++ b/layout/mathml/nsMathMLContainerFrame.cpp @@ -133,6 +133,59 @@ void nsMathMLContainerFrame::InflateReflowAndBoundingMetrics( aReflowOutput.Height() += aBorderPadding.TopBottom(); } +nsMathMLContainerFrame::WidthAndHeightForPlaceAdjustment +nsMathMLContainerFrame::GetWidthAndHeightForPlaceAdjustment( + const PlaceFlags& aFlags) { + WidthAndHeightForPlaceAdjustment sizes; + if (aFlags.contains(PlaceFlag::DoNotAdjustForWidthAndHeight)) { + return sizes; + } + const nsStylePosition* stylePos = StylePosition(); + const auto& width = stylePos->mWidth; + // TODO: Resolve percentages. + // https://github.com/w3c/mathml-core/issues/76 + if (width.ConvertsToLength()) { + sizes.width = Some(width.ToLength()); + } + if (!aFlags.contains(PlaceFlag::IntrinsicSize)) { + // TODO: Resolve percentages. + // https://github.com/w3c/mathml-core/issues/77 + const auto& height = stylePos->mHeight; + if (height.ConvertsToLength()) { + sizes.height = Some(height.ToLength()); + } + } + return sizes; +} + +nscoord nsMathMLContainerFrame::ApplyAdjustmentForWidthAndHeight( + const PlaceFlags& aFlags, const WidthAndHeightForPlaceAdjustment& aSizes, + ReflowOutput& aReflowOutput, nsBoundingMetrics& aBoundingMetrics) { + nscoord shiftX = 0; + if (aSizes.width) { + MOZ_ASSERT(!aFlags.contains(PlaceFlag::DoNotAdjustForWidthAndHeight)); + auto width = *aSizes.width; + auto oldWidth = aReflowOutput.Width(); + if (IsMathContentBoxHorizontallyCentered()) { + shiftX = (width - oldWidth) / 2; + } else if (StyleVisibility()->mDirection == StyleDirection::Rtl) { + shiftX = width - oldWidth; + } + aBoundingMetrics.leftBearing = 0; + aBoundingMetrics.rightBearing = width; + aBoundingMetrics.width = width; + aReflowOutput.mBoundingMetrics = aBoundingMetrics; + aReflowOutput.Width() = width; + } + if (aSizes.height) { + MOZ_ASSERT(!aFlags.contains(PlaceFlag::DoNotAdjustForWidthAndHeight)); + MOZ_ASSERT(!aFlags.contains(PlaceFlag::IntrinsicSize)); + auto height = *aSizes.height; + aReflowOutput.Height() = height; + } + return shiftX; +} + // helper to get the preferred size that a container frame should use to fire // the stretch on its stretchy child frames. void nsMathMLContainerFrame::GetPreferredStretchSize( @@ -1169,10 +1222,16 @@ nsresult nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.SetBlockStartAscent(ascent); aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply inline/block sizes to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + nscoord shiftX = ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, mBoundingMetrics); + shiftX += borderPadding.left; mReference.x = 0; mReference.y = aDesiredSize.BlockStartAscent(); @@ -1180,7 +1239,7 @@ nsresult nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget, ////////////////// // Place Children if (!aFlags.contains(PlaceFlag::MeasureOnly)) { - PositionRowChildFrames(borderPadding.left, aDesiredSize.BlockStartAscent()); + PositionRowChildFrames(shiftX, aDesiredSize.BlockStartAscent()); } return NS_OK; diff --git a/layout/mathml/nsMathMLContainerFrame.h b/layout/mathml/nsMathMLContainerFrame.h index cb43559908a8a..ec3d28e816c1a 100644 --- a/layout/mathml/nsMathMLContainerFrame.h +++ b/layout/mathml/nsMathMLContainerFrame.h @@ -157,6 +157,11 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame { // place some radical symbol on top of them and finally add its // padding/border around that radical symbol. IgnoreBorderPadding, + + // If DoNotAdjustForWidthAndHeight is set, the function will complete + // without setting the computed width and height after the math layout. This + // can be used similarly to IgnoreBorderPadding above. + DoNotAdjustForWidthAndHeight, }; using PlaceFlags = mozilla::EnumSet; @@ -247,6 +252,18 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame { nsMargin GetBorderPaddingForPlace(const PlaceFlags& aFlags); + struct WidthAndHeightForPlaceAdjustment { + mozilla::Maybe width; + mozilla::Maybe height; + }; + WidthAndHeightForPlaceAdjustment GetWidthAndHeightForPlaceAdjustment( + const PlaceFlags& aFlags); + + virtual bool IsMathContentBoxHorizontallyCentered() const { return false; } + nscoord ApplyAdjustmentForWidthAndHeight( + const PlaceFlags& aFlags, const WidthAndHeightForPlaceAdjustment& aSizes, + ReflowOutput& aReflowOutput, nsBoundingMetrics& aBoundingMetrics); + protected: // helper to add the inter-spacing when is the immediate parent. // Since we don't (yet) handle the root element ourselves, we need to diff --git a/layout/mathml/nsMathMLTokenFrame.cpp b/layout/mathml/nsMathMLTokenFrame.cpp index 29615327a479e..cbd92a30d7f01 100644 --- a/layout/mathml/nsMathMLTokenFrame.cpp +++ b/layout/mathml/nsMathMLTokenFrame.cpp @@ -178,6 +178,11 @@ nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.Height() = aDesiredSize.BlockStartAscent() + std::max(mBoundingMetrics.descent, descent); + // Apply width/height to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + auto shiftX = ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, @@ -185,6 +190,7 @@ nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget, if (!aFlags.contains(PlaceFlag::MeasureOnly)) { nscoord dx = borderPadding.left; + dx += shiftX; for (nsIFrame* childFrame : PrincipalChildList()) { ReflowOutput childSize(aDesiredSize.GetWritingMode()); GetReflowAndBoundingMetricsFor(childFrame, childSize, diff --git a/layout/mathml/nsMathMLmencloseFrame.cpp b/layout/mathml/nsMathMLmencloseFrame.cpp index 2b2211dbe1617..6f41471e7a21b 100644 --- a/layout/mathml/nsMathMLmencloseFrame.cpp +++ b/layout/mathml/nsMathMLmencloseFrame.cpp @@ -270,8 +270,9 @@ nsresult nsMathMLmencloseFrame::Place(DrawTarget* aDrawTarget, // Measure the size of our content using the base class to format like an // inferred mrow, without border/padding. ReflowOutput baseSize(aDesiredSize.GetWritingMode()); - PlaceFlags flags = - aFlags + PlaceFlag::MeasureOnly + PlaceFlag::IgnoreBorderPadding; + PlaceFlags flags = aFlags + PlaceFlag::MeasureOnly + + PlaceFlag::IgnoreBorderPadding + + PlaceFlag::DoNotAdjustForWidthAndHeight; nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, flags, baseSize); if (NS_FAILED(rv)) { @@ -527,6 +528,11 @@ nsresult nsMathMLmencloseFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + dx_left += ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, diff --git a/layout/mathml/nsMathMLmfracFrame.cpp b/layout/mathml/nsMathMLmfracFrame.cpp index 30b02aa56681d..aeb5e9a4e7df1 100644 --- a/layout/mathml/nsMathMLmfracFrame.cpp +++ b/layout/mathml/nsMathMLmfracFrame.cpp @@ -355,6 +355,18 @@ nsresult nsMathMLmfracFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.Width() = mBoundingMetrics.width; aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + auto shiftX = ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + if (sizes.width) { + // MathML Core says the math content box is horizontally centered + // but the fraction bar still takes the full width of the content box. + dxNum += shiftX; + dxDen += shiftX; + width = *sizes.width; + } + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, diff --git a/layout/mathml/nsMathMLmfracFrame.h b/layout/mathml/nsMathMLmfracFrame.h index 057efb1e43d6c..2808df9448976 100644 --- a/layout/mathml/nsMathMLmfracFrame.h +++ b/layout/mathml/nsMathMLmfracFrame.h @@ -95,6 +95,8 @@ class nsMathMLmfracFrame final : public nsMathMLContainerFrame { mLineThickness(0) {} virtual ~nsMathMLmfracFrame(); + bool IsMathContentBoxHorizontallyCentered() const final { return true; } + // Display a slash void DisplaySlash(nsDisplayListBuilder* aBuilder, const nsRect& aRect, nscoord aThickness, const nsDisplayListSet& aLists); diff --git a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp index 2d196aef8ee54..1b17bff2c38dd 100644 --- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp +++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp @@ -559,6 +559,11 @@ nsresult nsMathMLmmultiscriptsFrame::PlaceMultiScript( aDesiredSize.Width() = boundingMetrics.width; aDesiredSize.mBoundingMetrics = boundingMetrics; + // Apply width/height to math content box. + auto sizes = aFrame->GetWidthAndHeightForPlaceAdjustment(aFlags); + aFrame->ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + boundingMetrics); + // Add padding+border. auto borderPadding = aFrame->GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, boundingMetrics); diff --git a/layout/mathml/nsMathMLmoFrame.cpp b/layout/mathml/nsMathMLmoFrame.cpp index 2ec34d2f508a5..36c94e268b51f 100644 --- a/layout/mathml/nsMathMLmoFrame.cpp +++ b/layout/mathml/nsMathMLmoFrame.cpp @@ -741,7 +741,8 @@ nsMathMLmoFrame::Stretch(DrawTarget* aDrawTarget, // Place our children using the default method and no border/padding. // This will allow our child text frame to get its DidReflow() - PlaceFlags flags = PlaceFlag::IgnoreBorderPadding; + PlaceFlags flags(PlaceFlag::IgnoreBorderPadding, + PlaceFlag::DoNotAdjustForWidthAndHeight); nsresult rv = Place(aDrawTarget, flags, aDesiredStretchSize); if (NS_FAILED(rv)) { // Make sure the child frames get their DidReflow() calls. @@ -852,8 +853,10 @@ nsMathMLmoFrame::Stretch(DrawTarget* aDrawTarget, } flags = PlaceFlags(); + auto sizes = GetWidthAndHeightForPlaceAdjustment(flags); auto borderPadding = GetBorderPaddingForPlace(flags); - if (leadingSpace || trailingSpace || !borderPadding.IsAllZero()) { + if (leadingSpace || trailingSpace || !borderPadding.IsAllZero() || + sizes.width || sizes.height) { mBoundingMetrics.width += leadingSpace + trailingSpace; aDesiredStretchSize.Width() = mBoundingMetrics.width; aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width; @@ -866,6 +869,10 @@ nsMathMLmoFrame::Stretch(DrawTarget* aDrawTarget, aDesiredStretchSize.mBoundingMetrics.leftBearing += dx; aDesiredStretchSize.mBoundingMetrics.rightBearing += dx; + // Apply inline/block sizes to math content box. + dx += ApplyAdjustmentForWidthAndHeight(flags, sizes, aDesiredStretchSize, + mBoundingMetrics); + // Add border/padding. InflateReflowAndBoundingMetrics(borderPadding, aDesiredStretchSize, mBoundingMetrics); diff --git a/layout/mathml/nsMathMLmpaddedFrame.cpp b/layout/mathml/nsMathMLmpaddedFrame.cpp index 4ea75749fd421..1a5777a238b5a 100644 --- a/layout/mathml/nsMathMLmpaddedFrame.cpp +++ b/layout/mathml/nsMathMLmpaddedFrame.cpp @@ -286,8 +286,9 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget, const PlaceFlags& aFlags, ReflowOutput& aDesiredSize) { // First perform normal row layout without border/padding. - PlaceFlags flags = - aFlags + PlaceFlag::MeasureOnly + PlaceFlag::IgnoreBorderPadding; + PlaceFlags flags = aFlags + PlaceFlag::MeasureOnly + + PlaceFlag::IgnoreBorderPadding + + PlaceFlag::DoNotAdjustForWidthAndHeight; nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, flags, aDesiredSize); if (NS_FAILED(rv)) { DidReflowChildren(PrincipalChildList().FirstChild()); @@ -388,6 +389,11 @@ nsresult nsMathMLmpaddedFrame::Place(DrawTarget* aDrawTarget, mBoundingMetrics.descent = depth; aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + dx += ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, diff --git a/layout/mathml/nsMathMLmrootFrame.cpp b/layout/mathml/nsMathMLmrootFrame.cpp index b2744dc875209..8fe79a37a726e 100644 --- a/layout/mathml/nsMathMLmrootFrame.cpp +++ b/layout/mathml/nsMathMLmrootFrame.cpp @@ -180,8 +180,9 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget, } else { // Format our content as an mrow without border/padding to obtain the // square root base. The metrics/frame for the index are ignored. - PlaceFlags flags = - aFlags + PlaceFlag::MeasureOnly + PlaceFlag::IgnoreBorderPadding; + PlaceFlags flags = aFlags + PlaceFlag::MeasureOnly + + PlaceFlag::IgnoreBorderPadding + + PlaceFlag::DoNotAdjustForWidthAndHeight; nsresult rv = nsMathMLContainerFrame::Place(aDrawTarget, flags, baseSize); if (NS_FAILED(rv)) { DidReflowChildren(PrincipalChildList().FirstChild()); @@ -317,6 +318,12 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + const PlaceFlags flags; + auto sizes = GetWidthAndHeightForPlaceAdjustment(flags); + nscoord shiftX = ApplyAdjustmentForWidthAndHeight(flags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border around the final layout. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, @@ -360,7 +367,7 @@ nsresult nsMathMLmrootFrame::Place(DrawTarget* aDrawTarget, MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx), dy, ReflowChildFlags::Default); } else { - nscoord dx_left = borderPadding.left; + nscoord dx_left = borderPadding.left + shiftX; if (!isRTL) { dx_left += bmSqr.width; } diff --git a/layout/mathml/nsMathMLmspaceFrame.cpp b/layout/mathml/nsMathMLmspaceFrame.cpp index 1bf9f70ba0c20..ed4945ed4605c 100644 --- a/layout/mathml/nsMathMLmspaceFrame.cpp +++ b/layout/mathml/nsMathMLmspaceFrame.cpp @@ -113,6 +113,12 @@ nsresult nsMathMLmspaceFrame::Place(DrawTarget* aDrawTarget, // Also return our bounding metrics aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + const PlaceFlags flags; + auto sizes = GetWidthAndHeightForPlaceAdjustment(flags); + ApplyAdjustmentForWidthAndHeight(flags, sizes, aDesiredSize, + mBoundingMetrics); + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, diff --git a/layout/mathml/nsMathMLmunderoverFrame.cpp b/layout/mathml/nsMathMLmunderoverFrame.cpp index 0b532b0ec3ba4..315fa8e73cd5e 100644 --- a/layout/mathml/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/nsMathMLmunderoverFrame.cpp @@ -685,6 +685,14 @@ nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget, aDesiredSize.Width() = mBoundingMetrics.width; aDesiredSize.mBoundingMetrics = mBoundingMetrics; + // Apply width/height to math content box. + auto sizes = GetWidthAndHeightForPlaceAdjustment(aFlags); + auto shiftX = ApplyAdjustmentForWidthAndHeight(aFlags, sizes, aDesiredSize, + mBoundingMetrics); + dxOver += shiftX; + dxBase += shiftX; + dxUnder += shiftX; + // Add padding+border. auto borderPadding = GetBorderPaddingForPlace(aFlags); InflateReflowAndBoundingMetrics(borderPadding, aDesiredSize, @@ -719,3 +727,10 @@ nsresult nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget, } return NS_OK; } + +bool nsMathMLmunderoverFrame::IsMathContentBoxHorizontallyCentered() const { + bool subsupDisplay = + NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && + StyleFont()->mMathStyle == StyleMathStyle::Compact; + return !subsupDisplay; +} diff --git a/layout/mathml/nsMathMLmunderoverFrame.h b/layout/mathml/nsMathMLmunderoverFrame.h index 39de194177304..74e561e3ef2a5 100644 --- a/layout/mathml/nsMathMLmunderoverFrame.h +++ b/layout/mathml/nsMathMLmunderoverFrame.h @@ -58,6 +58,8 @@ class nsMathMLmunderoverFrame final : public nsMathMLContainerFrame, virtual ~nsMathMLmunderoverFrame(); private: + bool IsMathContentBoxHorizontallyCentered() const final; + // Helper to set the "increment script level" flag on the element belonging // to a child frame given by aChildIndex. // diff --git a/testing/web-platform/meta/mathml/presentation-markup/fractions/frac-bar-003.html.ini b/testing/web-platform/meta/mathml/presentation-markup/fractions/frac-bar-003.html.ini deleted file mode 100644 index cb8fdddf30e3b..0000000000000 --- a/testing/web-platform/meta/mathml/presentation-markup/fractions/frac-bar-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[frac-bar-003.html] - expected: FAIL diff --git a/testing/web-platform/meta/mathml/presentation-markup/spaces/mspace-width-height-001.html.ini b/testing/web-platform/meta/mathml/presentation-markup/spaces/mspace-width-height-001.html.ini deleted file mode 100644 index e3a885f287ba2..0000000000000 --- a/testing/web-platform/meta/mathml/presentation-markup/spaces/mspace-width-height-001.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[mspace-width-height-001.html] - [width attribute + width property] - expected: FAIL - - [height/depth attributes + height property] - expected: FAIL - - [height attribute + height property] - expected: FAIL - - [depth attribute + height property] - expected: FAIL diff --git a/testing/web-platform/meta/mathml/relations/css-styling/display-2.html.ini b/testing/web-platform/meta/mathml/relations/css-styling/display-2.html.ini index 36307d8db761c..0ad2a6eaabcf1 100644 --- a/testing/web-platform/meta/mathml/relations/css-styling/display-2.html.ini +++ b/testing/web-platform/meta/mathml/relations/css-styling/display-2.html.ini @@ -4,10 +4,10 @@ expected: FAIL [list display inside display block] - expected: FAIL + expected: [PASS, FAIL] [flexbox display (math)] - expected: FAIL + expected: [PASS, FAIL] [block display with column width (math)] expected: FAIL diff --git a/testing/web-platform/meta/mathml/relations/css-styling/width-height-001.html.ini b/testing/web-platform/meta/mathml/relations/css-styling/width-height-001.html.ini deleted file mode 100644 index 1ef59a2119004..0000000000000 --- a/testing/web-platform/meta/mathml/relations/css-styling/width-height-001.html.ini +++ /dev/null @@ -1,144 +0,0 @@ -[width-height-001.html] - [width and height properties on maction] - expected: FAIL - - [inline-size and block-size properties on maction] - expected: FAIL - - [width and height properties on menclose] - expected: FAIL - - [inline-size and block-size properties on menclose] - expected: FAIL - - [width and height properties on merror] - expected: FAIL - - [inline-size and block-size properties on merror] - expected: FAIL - - [width and height properties on mfrac] - expected: FAIL - - [inline-size and block-size properties on mfrac] - expected: FAIL - - [width and height properties on mi] - expected: FAIL - - [inline-size and block-size properties on mi] - expected: FAIL - - [width and height properties on mmultiscripts] - expected: FAIL - - [inline-size and block-size properties on mmultiscripts] - expected: FAIL - - [width and height properties on mn] - expected: FAIL - - [inline-size and block-size properties on mn] - expected: FAIL - - [width and height properties on mo] - expected: FAIL - - [inline-size and block-size properties on mo] - expected: FAIL - - [width and height properties on mover] - expected: FAIL - - [inline-size and block-size properties on mover] - expected: FAIL - - [width and height properties on mpadded] - expected: FAIL - - [inline-size and block-size properties on mpadded] - expected: FAIL - - [width and height properties on mphantom] - expected: FAIL - - [inline-size and block-size properties on mphantom] - expected: FAIL - - [width and height properties on mroot] - expected: FAIL - - [inline-size and block-size properties on mroot] - expected: FAIL - - [width and height properties on mrow] - expected: FAIL - - [inline-size and block-size properties on mrow] - expected: FAIL - - [width and height properties on ms] - expected: FAIL - - [inline-size and block-size properties on ms] - expected: FAIL - - [width and height properties on mspace] - expected: FAIL - - [inline-size and block-size properties on mspace] - expected: FAIL - - [width and height properties on msqrt] - expected: FAIL - - [inline-size and block-size properties on msqrt] - expected: FAIL - - [width and height properties on mstyle] - expected: FAIL - - [inline-size and block-size properties on mstyle] - expected: FAIL - - [width and height properties on msub] - expected: FAIL - - [inline-size and block-size properties on msub] - expected: FAIL - - [width and height properties on msubsup] - expected: FAIL - - [inline-size and block-size properties on msubsup] - expected: FAIL - - [width and height properties on msup] - expected: FAIL - - [inline-size and block-size properties on msup] - expected: FAIL - - [width and height properties on mtext] - expected: FAIL - - [inline-size and block-size properties on mtext] - expected: FAIL - - [width and height properties on munder] - expected: FAIL - - [inline-size and block-size properties on munder] - expected: FAIL - - [width and height properties on munderover] - expected: FAIL - - [inline-size and block-size properties on munderover] - expected: FAIL - - [width and height properties on semantics] - expected: FAIL - - [inline-size and block-size properties on semantics] - expected: FAIL diff --git a/testing/web-platform/meta/mathml/relations/css-styling/width-height-002.html.ini b/testing/web-platform/meta/mathml/relations/css-styling/width-height-002.html.ini deleted file mode 100644 index d3eb160860f94..0000000000000 --- a/testing/web-platform/meta/mathml/relations/css-styling/width-height-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[width-height-002.html] - expected: FAIL diff --git a/testing/web-platform/meta/mathml/relations/css-styling/width-height-003.html.ini b/testing/web-platform/meta/mathml/relations/css-styling/width-height-003.html.ini deleted file mode 100644 index 5cb8938fd85de..0000000000000 --- a/testing/web-platform/meta/mathml/relations/css-styling/width-height-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[width-height-003.html] - expected: FAIL diff --git a/testing/web-platform/meta/mathml/relations/css-styling/width-height-005.html.ini b/testing/web-platform/meta/mathml/relations/css-styling/width-height-005.html.ini new file mode 100644 index 0000000000000..998cbcca6d999 --- /dev/null +++ b/testing/web-platform/meta/mathml/relations/css-styling/width-height-005.html.ini @@ -0,0 +1,6 @@ +[width-height-005.html] + [RTL mmultiscripts] + expected: FAIL # Bug 1909417 + + [RTL mmultiscripts (horizontal overflow)] + expected: FAIL # Bug 1909417 diff --git a/testing/web-platform/tests/mathml/relations/css-styling/width-height-001.html b/testing/web-platform/tests/mathml/relations/css-styling/width-height-001.html index 2deedc3f0b84d..57cbc1b0ab278 100644 --- a/testing/web-platform/tests/mathml/relations/css-styling/width-height-001.html +++ b/testing/web-platform/tests/mathml/relations/css-styling/width-height-001.html @@ -4,7 +4,7 @@ width, height, inline-size and block-size - + @@ -30,6 +30,7 @@ document.body.insertAdjacentHTML("beforeend", `
${MathMLFragments[tag]}
`); let div = document.body.lastElementChild; let element = FragmentHelper.element(div.firstElementChild); + FragmentHelper.forceNonEmptyDescendants(element); test(function() { assert_true(MathMLFeatureDetection[`has_${tag}`](), `${tag} is supported`); @@ -49,6 +50,35 @@ assert_approx_equals(box.height, 700, epsilon, "height"); }, `inline-size and block-size properties on ${tag}`); + // Test that if we specify a size smaller than the content, then + // it is used too. Note that we skip mtable, which follows CSS + // tables rules and behave differently in that case. + if (tag != "mtable") { + test(function() { + assert_true(MathMLFeatureDetection[`has_${tag}`](), `${tag} is supported`); + var style = `width: 2px; height: 1px;`; + element.setAttribute("style", style); + let box = element.getBoundingClientRect(); + assert_approx_equals(box.width, 2, epsilon, "width"); + assert_approx_equals(box.height, 1, epsilon, "height"); + }, `width and height properties on ${tag} (content overflowing)`); + } + + div.style = "display: none;"; // Hide the div after measurement. + + document.body.insertAdjacentHTML("beforeend", `
${MathMLFragments[tag]}
`); + let shrinkWrapDiv = document.body.lastElementChild.firstElementChild; + element = FragmentHelper.element(shrinkWrapDiv.firstElementChild); + FragmentHelper.forceNonEmptyDescendants(element); + + test(function() { + assert_true(MathMLFeatureDetection[`has_${tag}`](), `${tag} is supported`); + var style = `width: 300px;`; + element.setAttribute("style", style); + let box = shrinkWrapDiv.getBoundingClientRect(); + assert_approx_equals(box.width, 300, epsilon); + }, `width property on ${tag} (preferred width)`); + div.style = "display: none;"; // Hide the div after measurement. } diff --git a/testing/web-platform/tests/mathml/relations/css-styling/width-height-004.html b/testing/web-platform/tests/mathml/relations/css-styling/width-height-004.html index 10ece249ca0b5..e26ebe9682328 100644 --- a/testing/web-platform/tests/mathml/relations/css-styling/width-height-004.html +++ b/testing/web-platform/tests/mathml/relations/css-styling/width-height-004.html @@ -20,7 +20,6 @@ } [data-name] { width: 7em; - height: 3em; border: 1px solid blue; } @@ -64,6 +63,18 @@ X + + + XXXXXXXXXXXX + XXXXXXXXXXXX + + + + + XXXXXXXXXXXX + XXXXXXXXXXXX + +
@@ -79,6 +90,18 @@ X + + + XXXXXXXXXXXX + XXXXXXXXXXXX + + + + + XXXXXXXXXXXX + XXXXXXXXXXXX + +
@@ -94,6 +117,18 @@ X + + + XXXXXXXXXXXX + XXXXXXXXXXXX + + + + + XXXXXXXXXXXX + XXXXXXXXXXXX + +
@@ -109,6 +144,18 @@ X + + + XXXXXXXXXXXX + XXXXXXXXXXXX + + + + + XXXXXXXXXXXX + XXXXXXXXXXXX + +
@@ -126,6 +173,20 @@ X + + + XXXXXXXXXXXX + XXXXXXXXXXXX + XXXXXXXXXXXX + + + + + XXXXXXXXXXXX + XXXXXXXXXXXX + XXXXXXXXXXXX + +
diff --git a/testing/web-platform/tests/mathml/relations/css-styling/width-height-005.html b/testing/web-platform/tests/mathml/relations/css-styling/width-height-005.html new file mode 100644 index 0000000000000..a6ea8d82deb90 --- /dev/null +++ b/testing/web-platform/tests/mathml/relations/css-styling/width-height-005.html @@ -0,0 +1,541 @@ + + + + +content position with width/height + + + + + + + + + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + + + + + X + X + + + + + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + X + X + + + + + X + X + X + + X + X + + + + + X + X + X + + X + X + + +
+ +
+ + + X + X + X + + X + X + + + + + X + X + X + + X + X + + + + + X + X + X + + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ +
+ + + X + X + X + + + + + X + X + X + + + + + X + X + X + + +
+ + + diff --git a/testing/web-platform/tests/mathml/relations/css-styling/width-height-006.html b/testing/web-platform/tests/mathml/relations/css-styling/width-height-006.html new file mode 100644 index 0000000000000..d5427051974a0 --- /dev/null +++ b/testing/web-platform/tests/mathml/relations/css-styling/width-height-006.html @@ -0,0 +1,406 @@ + + + + +content position with width/height + + + + + + + + + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + + + + + + X + X + + + + + + X + X + + +
+ +
+ + + + X + X + + + + + + X + X + + + + + + X + X + + +
+ +
+ + + + X + X + + + + + + X + X + + + + + + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + + + + + + X + X + + + + + + X + X + + +
+ +
+ + + + X + X + + + + + + X + X + + + + + + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + X + + X + X + + + + + + X + X + X + + X + X + + + + + + X + X + X + + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ +
+ + + + X + X + X + + + + + + X + X + X + + + + + + X + X + X + + +
+ + +