Bug 1667501 - Add an nsIFrame::IsFrameOfType bit to say whether frames support aspect-ratio. r=TYLin

aspect-ratio applies to all elements except inline boxes and internal ruby or
table boxes. So we should return false for inline frames, table internal frames
(i.e. except nsTableFrame and nsTableWrapperFrame), and ruby internal frames.

Also, we can drop ComputeSizeFlags::SkipAspectRatio because this frame
bit can replace this flag.

Note: it seems nsRubyBaseContainerFrame and nsRubyTextContainerFrame are
inline, so we return false for them.

This will be very useful when computing the intrinsic size because
IntrinsicForAxis() computes the intrinsic size for all descendant frames and
some of descendants may not support aspect-ratio. It's pretty hard to achieve
this by just adding a flag for this function.

Differential Revision: https://phabricator.services.mozilla.com/D104296
This commit is contained in:
Boris Chiou 2021-02-11 00:19:58 +00:00
parent b9d992a73c
commit 156c710d50
12 changed files with 35 additions and 32 deletions

View File

@ -76,14 +76,6 @@ enum class ComputeSizeFlag : uint8_t {
* https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
*/
IApplyAutoMinSize, // only has an effect when eShrinkWrap is false
/**
* Indicates that we shouldn't take aspect ratio into account.
* This flag is only used to ignore aspect-ratio when computing intrinsic
* sizes in ComputeISizeValue(). (For now, only internal table boxes use this
* flag.)
*/
SkipAspectRatio,
};
using ComputeSizeFlags = mozilla::EnumSet<ComputeSizeFlag>;

View File

@ -5947,10 +5947,11 @@ AspectRatio nsIFrame::GetAspectRatio() const {
// Per spec, 'aspect-ratio' property applies to all elements except inline
// boxes and internal ruby or table boxes.
// https://drafts.csswg.org/css-sizing-4/#aspect-ratio
//
// Bug 1667501: If any caller is used for the elements supporting and not
// supporting 'aspect-ratio', we may need to add explicit exclusion to early
// return here.
// For those frame types that don't support aspect-ratio, they must not have
// the natural ratio, so this early return is fine.
if (!IsFrameOfType(eSupportsAspectRatio)) {
return AspectRatio();
}
const StyleAspectRatio& aspectRatio = StylePosition()->mAspectRatio;
// If aspect-ratio is zero or infinite, it's a degenerate ratio and behaves
@ -6385,9 +6386,10 @@ nscoord nsIFrame::ShrinkWidthToFit(gfxContext* aRenderingContext,
Maybe<nscoord> nsIFrame::ComputeInlineSizeFromAspectRatio(
WritingMode aWM, const LogicalSize& aCBSize,
const LogicalSize& aContentEdgeToBoxSizing, ComputeSizeFlags aFlags) const {
// FIXME: Bug 1670151: Use GetAspectRatio() to cover replaced elements.
// FIXME: Bug 1670151: Use GetAspectRatio() to cover replaced elements (and
// then we can drop the check of eSupportsAspectRatio).
const AspectRatio aspectRatio = StylePosition()->mAspectRatio.ToLayoutRatio();
if (aFlags.contains(ComputeSizeFlag::SkipAspectRatio) || !aspectRatio) {
if (!IsFrameOfType(eSupportsAspectRatio) || !aspectRatio) {
return Nothing();
}

View File

@ -3297,6 +3297,9 @@ class nsIFrame : public nsQueryFrame {
// other).
eSupportsContainLayoutAndPaint = 1 << 12,
// Does this frame class support `aspect-ratio` property.
eSupportsAspectRatio = 1 << 13,
// These are to allow nsIFrame::Init to assert that IsFrameOfType
// implementations all call the base class method. They are only
// meaningful in DEBUG builds.
@ -3317,7 +3320,8 @@ class nsIFrame : public nsQueryFrame {
nsIFrame::eDEBUGAllFrames |
#endif
nsIFrame::eSupportsCSSTransforms |
nsIFrame::eSupportsContainLayoutAndPaint));
nsIFrame::eSupportsContainLayoutAndPaint |
nsIFrame::eSupportsAspectRatio));
}
/**

View File

@ -45,7 +45,8 @@ class nsInlineFrame : public nsContainerFrame {
#endif
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint)) {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint |
eSupportsAspectRatio)) {
return false;
}
return nsContainerFrame::IsFrameOfType(

View File

@ -237,7 +237,8 @@ void nsRubyBaseContainerFrame::AddInlinePrefISize(
/* virtual */
bool nsRubyBaseContainerFrame::IsFrameOfType(uint32_t aFlags) const {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint)) {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint |
eSupportsAspectRatio)) {
return false;
}
return nsContainerFrame::IsFrameOfType(aFlags &

View File

@ -47,7 +47,8 @@ nsresult nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const {
/* virtual */
bool nsRubyTextContainerFrame::IsFrameOfType(uint32_t aFlags) const {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint)) {
if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint |
eSupportsAspectRatio)) {
return false;
}
return nsContainerFrame::IsFrameOfType(aFlags);

View File

@ -172,11 +172,10 @@ static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
// it separately on the columns.
const LogicalSize zeroSize(aWM);
if (maxISize.ConvertsToLength() || maxISize.IsExtremumLength()) {
nscoord c =
aFrame
->ComputeISizeValue(aRenderingContext, aWM, zeroSize, zeroSize, 0,
maxISize, {ComputeSizeFlag::SkipAspectRatio})
.mISize;
nscoord c = aFrame
->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
zeroSize, 0, maxISize)
.mISize;
minCoord = std::min(c, minCoord);
prefCoord = std::min(c, prefCoord);
} else if (maxISize.ConvertsToPercentage()) {
@ -198,11 +197,10 @@ static CellISizeInfo GetISizeInfo(gfxContext* aRenderingContext,
}
}
if (minISize.ConvertsToLength() || minISize.IsExtremumLength()) {
nscoord c =
aFrame
->ComputeISizeValue(aRenderingContext, aWM, zeroSize, zeroSize, 0,
minISize, {ComputeSizeFlag::SkipAspectRatio})
.mISize;
nscoord c = aFrame
->ComputeISizeValue(aRenderingContext, aWM, zeroSize,
zeroSize, 0, minISize)
.mISize;
minCoord = std::max(c, minCoord);
prefCoord = std::max(c, prefCoord);
} else if (minISize.ConvertsToPercentage()) {

View File

@ -231,6 +231,10 @@ class nsTableCellFrame : public nsContainerFrame,
bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & eSupportsAspectRatio) {
return false;
}
return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart));
}

View File

@ -261,7 +261,7 @@ class nsTableColFrame final : public nsSplittableFrame {
nscoord GetFinalISize() { return mFinalISize; }
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & eSupportsContainLayoutAndPaint) {
if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) {
return false;
}

View File

@ -192,7 +192,7 @@ class nsTableColGroupFrame final : public nsContainerFrame {
BCPixelSize aPixelValue);
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & eSupportsContainLayoutAndPaint) {
if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) {
return false;
}

View File

@ -237,7 +237,7 @@ class nsTableRowFrame : public nsContainerFrame {
BCPixelSize aPixelValue);
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & eSupportsContainLayoutAndPaint) {
if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) {
return false;
}

View File

@ -305,7 +305,7 @@ class nsTableRowGroupFrame final : public nsContainerFrame,
virtual nsILineIterator* GetLineIterator() override { return this; }
virtual bool IsFrameOfType(uint32_t aFlags) const override {
if (aFlags & eSupportsContainLayoutAndPaint) {
if (aFlags & (eSupportsContainLayoutAndPaint | eSupportsAspectRatio)) {
return false;
}