From 232f987cf45aad65d20e79d283f14c72771c9bc8 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 31 Jul 2020 13:01:18 -0700 Subject: Issue #1619 - Convert Intrinsic Ratio to Float https://bugzilla.mozilla.org/show_bug.cgi?id=1547792 Aspect Ratio handling simplified by using floating point integers: - Multiplication of value (or inverse value) to a known side for Scaling - No unequal equal values such as "4/3" vs "8/6" vs "20/15" - Truly "Empty" aspect ratios, even if one dimension is not 0 --- layout/generic/AspectRatio.h | 81 +++++++++++++++++++++++++++++++++ layout/generic/moz.build | 1 + layout/generic/nsFlexContainerFrame.cpp | 31 ++++++------- layout/generic/nsFrame.cpp | 77 +++++++++++++++++-------------- layout/generic/nsFrame.h | 4 +- layout/generic/nsHTMLCanvasFrame.cpp | 30 ++++-------- layout/generic/nsHTMLCanvasFrame.h | 2 +- layout/generic/nsIFrame.h | 14 +++--- layout/generic/nsImageFrame.cpp | 13 +++--- layout/generic/nsImageFrame.h | 4 +- layout/generic/nsLineLayout.cpp | 2 +- layout/generic/nsSubDocumentFrame.cpp | 4 +- layout/generic/nsSubDocumentFrame.h | 2 +- layout/generic/nsVideoFrame.cpp | 18 ++++---- layout/generic/nsVideoFrame.h | 2 +- 15 files changed, 182 insertions(+), 103 deletions(-) create mode 100644 layout/generic/AspectRatio.h (limited to 'layout/generic') diff --git a/layout/generic/AspectRatio.h b/layout/generic/AspectRatio.h new file mode 100644 index 000000000..0056c0620 --- /dev/null +++ b/layout/generic/AspectRatio.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_AspectRatio_h +#define mozilla_AspectRatio_h + +/* The aspect ratio of a box, in a "width / height" format. */ + +#include "mozilla/Attributes.h" +#include "nsCoord.h" +#include +#include + +namespace mozilla { + +struct AspectRatio { + AspectRatio() : mRatio(0.0f) {} + explicit AspectRatio(float aRatio) : mRatio(std::max(aRatio, 0.0f)) {} + + static AspectRatio FromSize(float aWidth, float aHeight) { + if (aWidth == 0.0f || aHeight == 0.0f) { + return AspectRatio(); + } + return AspectRatio(aWidth / aHeight); + } + + static AspectRatio FromSize(nsSize aSize) { + return FromSize(aSize.width, aSize.height); + } + + static AspectRatio FromSize(nsIntSize aSize) { + return FromSize(aSize.width, aSize.height); + } + + explicit operator bool() const { return mRatio != 0.0f; } + + nscoord ApplyTo(nscoord aCoord) const { + MOZ_DIAGNOSTIC_ASSERT(*this); + return NSCoordSaturatingNonnegativeMultiply(aCoord, mRatio); + } + + float ApplyToFloat(float aFloat) const { + MOZ_DIAGNOSTIC_ASSERT(*this); + return mRatio * aFloat; + } + + // Inverts the ratio, in order to get the height / width ratio. + MOZ_MUST_USE AspectRatio Inverted() const { + if (!*this) { + return AspectRatio(); + } + // Clamp to a small epsilon, in case mRatio is absurdly large & produces + // 0.0f in the division here (so that valid ratios always generate other + // valid ratios when inverted). + return AspectRatio( + std::max(std::numeric_limits::epsilon(), 1.0f / mRatio)); + } + + bool operator==(const AspectRatio& aOther) const { + return mRatio == aOther.mRatio; + } + + bool operator!=(const AspectRatio& aOther) const { + return !(*this == aOther); + } + + bool operator<(const AspectRatio& aOther) const { + return mRatio < aOther.mRatio; + } + + private: + // 0.0f represents no aspect ratio. + float mRatio; +}; + +} // namespace mozilla + +#endif // mozilla_AspectRatio_h diff --git a/layout/generic/moz.build b/layout/generic/moz.build index ad186ef7a..b830470a3 100644 --- a/layout/generic/moz.build +++ b/layout/generic/moz.build @@ -109,6 +109,7 @@ EXPORTS += [ ] EXPORTS.mozilla += [ + 'AspectRatio.h', 'CSSAlignUtils.h', 'ReflowInput.h', 'ReflowOutput.h', diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 69200117b..a76097e1e 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -557,8 +557,8 @@ public: return mFlexShrink * mFlexBaseSize; } - const nsSize& IntrinsicRatio() const { return mIntrinsicRatio; } - bool HasIntrinsicRatio() const { return mIntrinsicRatio != nsSize(); } + const AspectRatio IntrinsicRatio() const { return mIntrinsicRatio; } + bool HasIntrinsicRatio() const { return !!mIntrinsicRatio; } // Getters for margin: // =================== @@ -756,7 +756,7 @@ protected: const float mFlexGrow; const float mFlexShrink; - const nsSize mIntrinsicRatio; + const AspectRatio mIntrinsicRatio; const nsMargin mBorderPadding; nsMargin mMargin; // non-const because we need to resolve auto margins @@ -1520,22 +1520,20 @@ CrossSizeToUseWithRatio(const FlexItem& aFlexItem, } // Convenience function; returns a main-size, given a cross-size and an -// intrinsic ratio. The intrinsic ratio must not have 0 in its cross-axis -// component (or else we'll divide by 0). +// intrinsic ratio. The caller is responsible for ensuring that the passed-in +// intrinsic ratio is not zero. static nscoord MainSizeFromAspectRatio(nscoord aCrossSize, - const nsSize& aIntrinsicRatio, + const AspectRatio& aIntrinsicRatio, const FlexboxAxisTracker& aAxisTracker) { - MOZ_ASSERT(aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0, + MOZ_ASSERT(aIntrinsicRatio, "Invalid ratio; will divide by 0! Caller should've checked..."); + AspectRatio ratio = aAxisTracker.IsMainAxisHorizontal() + ? aIntrinsicRatio + : aIntrinsicRatio.Inverted(); - if (aAxisTracker.IsCrossAxisHorizontal()) { - // cross axis horiz --> aCrossSize is a width. Converting to height. - return NSCoordMulDiv(aCrossSize, aIntrinsicRatio.height, aIntrinsicRatio.width); - } - // cross axis vert --> aCrossSize is a height. Converting to width. - return NSCoordMulDiv(aCrossSize, aIntrinsicRatio.width, aIntrinsicRatio.height); + return ratio.ApplyTo(aCrossSize); } // Partially resolves "min-[width|height]:auto" and returns the resulting value. @@ -1584,7 +1582,7 @@ PartiallyResolveAutoMinSize(const FlexItem& aFlexItem, // * if the item has an intrinsic aspect ratio, the width (height) calculated // from the aspect ratio and any definite size constraints in the opposite // dimension. - if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) { + if (aFlexItem.IntrinsicRatio()) { // We have a usable aspect ratio. (not going to divide by 0) const bool useMinSizeIfCrossSizeIsIndefinite = true; nscoord crossSizeToUseWithRatio = @@ -1617,7 +1615,7 @@ ResolveAutoFlexBasisFromRatio(FlexItem& aFlexItem, // - a definite cross size // then the flex base size is calculated from its inner cross size and the // flex item’s intrinsic aspect ratio. - if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) { + if (aFlexItem.IntrinsicRatio()) { // We have a usable aspect ratio. (not going to divide by 0) const bool useMinSizeIfCrossSizeIsIndefinite = false; nscoord crossSizeToUseWithRatio = @@ -1693,8 +1691,7 @@ nsFlexContainerFrame:: // (We'll consider that later, if we need to.) resolvedMinSize = PartiallyResolveAutoMinSize(aFlexItem, aItemReflowInput, aAxisTracker); - if (resolvedMinSize > 0 && - aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) == 0) { + if (resolvedMinSize > 0 && !aFlexItem.IntrinsicRatio()) { // We don't have a usable aspect ratio, so we need to consider our // min-content size as another candidate min-size, which we'll have to // min() with the current resolvedMinSize. diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index dd7933b03..afbd57f52 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4641,10 +4641,10 @@ nsFrame::GetIntrinsicSize() return IntrinsicSize(); // default is width/height set to eStyleUnit_None } -/* virtual */ nsSize +/* virtual */ AspectRatio nsFrame::GetIntrinsicRatio() { - return nsSize(0, 0); + return AspectRatio(); } /* virtual */ @@ -4658,7 +4658,7 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext, const LogicalSize& aPadding, ComputeSizeFlags aFlags) { - MOZ_ASSERT(GetIntrinsicRatio() == nsSize(0,0), + MOZ_ASSERT(!GetIntrinsicRatio(), "Please override this method and call " "nsFrame::ComputeSizeWithIntrinsicDimensions instead."); LogicalSize result = ComputeAutoSize(aRenderingContext, aWM, @@ -4914,13 +4914,15 @@ LogicalSize nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingContext, WritingMode aWM, const IntrinsicSize& aIntrinsicSize, - nsSize aIntrinsicRatio, + const AspectRatio& aIntrinsicRatio, const LogicalSize& aCBSize, const LogicalSize& aMargin, const LogicalSize& aBorder, const LogicalSize& aPadding, ComputeSizeFlags aFlags) { + auto logicalRatio = + aWM.IsVertical() ? aIntrinsicRatio.Inverted() : aIntrinsicRatio; const nsStylePosition* stylePos = StylePosition(); const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM); const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM); @@ -5181,10 +5183,6 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte intrinsicBSize = 0; } - NS_ASSERTION(aIntrinsicRatio.width >= 0 && aIntrinsicRatio.height >= 0, - "Intrinsic ratio has a negative component!"); - LogicalSize logicalRatio(aWM, aIntrinsicRatio); - // Now calculate the used values for iSize and bSize: if (isAutoISize) { @@ -5198,9 +5196,29 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte if (hasIntrinsicISize) { tentISize = intrinsicISize; - } else if (hasIntrinsicBSize && logicalRatio.BSize(aWM) > 0) { - tentISize = NSCoordMulDiv(intrinsicBSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); - } else if (logicalRatio.ISize(aWM) > 0) { + } else if (hasIntrinsicBSize && logicalRatio) { + // (dholbert) + // This is wrong -- this ApplyTo call (and probably every ApplyTo call + // in this function) would only be valid if we're in a horizontal + // writing mode. It's not valid in a vertical writing mode. If this + // doesn't break tests, that's a bit concerning, and I think it means + // we're missing some test coverage. (That, or I'm misreading things.) + // + // aIntrinsicRatio is stored in terms of physical axes (width/height), + // either of which could be I vs. B axis. So any sort of + // aIntrinsicRatio.ApplyTo(someBSize) operation will be + // potentially-bogus. + // + // You probably want to bring back a logicalRatio variable + // (like the one we used to have here), but now with type AspectRatio. + // It would be equal to either aIntrinsicRatio or + // aIntrinsicRatio.Invert() depending on whether aWM is horizontal or + // vertical. (And hopefully having logical in its name would be a + // reminder that it's in terms of Inline/Block and can be used for + // these sorts of ApplyTo(intrinsicBSize) operations. + tentISize = logicalRatio.ApplyTo(intrinsicBSize); + } else if (logicalRatio) { tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar? if (tentISize < 0) tentISize = 0; } else { @@ -5217,8 +5235,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte if (hasIntrinsicBSize) { tentBSize = intrinsicBSize; - } else if (logicalRatio.ISize(aWM) > 0) { - tentBSize = NSCoordMulDiv(tentISize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); + } else if (logicalRatio) { + tentBSize = logicalRatio.Inverted().ApplyTo(tentISize); } else { tentBSize = nsPresContext::CSSPixelsToAppUnits(150); } @@ -5229,46 +5247,39 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte stretchB = (stretchI == eStretch ? eStretch : eStretchPreservingRatio); } - if (aIntrinsicRatio != nsSize(0, 0)) { + if (logicalRatio) { if (stretchI == eStretch) { tentISize = iSize; // * / 'stretch' if (stretchB == eStretch) { tentBSize = bSize; // 'stretch' / 'stretch' - } else if (stretchB == eStretchPreservingRatio && logicalRatio.ISize(aWM) > 0) { + } else if (stretchB == eStretchPreservingRatio) { // 'normal' / 'stretch' - tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); + tentBSize = logicalRatio.Inverted().ApplyTo(iSize); } } else if (stretchB == eStretch) { tentBSize = bSize; // 'stretch' / * (except 'stretch') - if (stretchI == eStretchPreservingRatio && logicalRatio.BSize(aWM) > 0) { + if (stretchI == eStretchPreservingRatio) { // 'stretch' / 'normal' - tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); + tentISize = logicalRatio.ApplyTo(bSize); } } else if (stretchI == eStretchPreservingRatio) { tentISize = iSize; // * (except 'stretch') / 'normal' - if (logicalRatio.ISize(aWM) > 0) { - tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); - } + tentBSize = logicalRatio.Inverted().ApplyTo(iSize); if (stretchB == eStretchPreservingRatio && tentBSize > bSize) { // Stretch within the CB size with preserved intrinsic ratio. tentBSize = bSize; // 'normal' / 'normal' - if (logicalRatio.BSize(aWM) > 0) { - tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); - } + tentISize = logicalRatio.ApplyTo(bSize); } } else if (stretchB == eStretchPreservingRatio) { tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch') - if (logicalRatio.BSize(aWM) > 0) { - tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); - } + tentISize = logicalRatio.ApplyTo(bSize); } } // ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when applying // the min/max-size. We don't want that when we have 'stretch' in either // axis because tentISize/tentBSize is likely not according to ratio now. - if (aIntrinsicRatio != nsSize(0, 0) && - stretchI != eStretch && stretchB != eStretch) { + if (logicalRatio && stretchI != eStretch && stretchB != eStretch) { nsSize autoSize = nsLayoutUtils:: ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize, maxISize, maxBSize, @@ -5289,8 +5300,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte // 'auto' iSize, non-'auto' bSize bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize); if (stretchI != eStretch) { - if (logicalRatio.BSize(aWM) > 0) { - iSize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); + if (logicalRatio) { + iSize = logicalRatio.ApplyTo(bSize); } else if (hasIntrinsicISize) { if (!((aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) && intrinsicISize > iSize)) { @@ -5309,8 +5320,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte // non-'auto' iSize, 'auto' bSize iSize = NS_CSS_MINMAX(iSize, minISize, maxISize); if (stretchB != eStretch) { - if (logicalRatio.ISize(aWM) > 0) { - bSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); + if (logicalRatio) { + bSize = logicalRatio.Inverted().ApplyTo(iSize); } else if (hasIntrinsicBSize) { if (!((aFlags & ComputeSizeFlags::eBClampMarginBoxMinSize) && intrinsicBSize > bSize)) { diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 439e39856..d75555fec 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -264,7 +264,7 @@ public: IntrinsicISizeOffsetData IntrinsicISizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override; - virtual nsSize GetIntrinsicRatio() override; + virtual mozilla::AspectRatio GetIntrinsicRatio() override; virtual mozilla::LogicalSize ComputeSize(nsRenderingContext* aRenderingContext, @@ -285,7 +285,7 @@ public: nsRenderingContext* aRenderingContext, mozilla::WritingMode aWM, const mozilla::IntrinsicSize& aIntrinsicSize, - nsSize aIntrinsicRatio, + const mozilla::AspectRatio& aIntrinsicRatio, const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder, diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index f86ec1136..032b95e5b 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -44,21 +44,6 @@ IntrinsicSizeFromCanvasSize(const nsIntSize& aCanvasSizeInPx) return intrinsicSize; } -/* Helper for our nsIFrame::GetIntrinsicRatio() impl. Takes the result of - * "GetCanvasSize()" as a parameter, which may help avoid redundant - * indirect calls to GetCanvasSize(). - * - * @param aCanvasSizeInPx The canvas's size in CSS pixels, as returned - * by GetCanvasSize(). - * @return The canvas's intrinsic ratio, as a nsSize. - */ -static nsSize -IntrinsicRatioFromCanvasSize(const nsIntSize& aCanvasSizeInPx) -{ - return nsSize(nsPresContext::CSSPixelsToAppUnits(aCanvasSizeInPx.width), - nsPresContext::CSSPixelsToAppUnits(aCanvasSizeInPx.height)); -} - class nsDisplayCanvas : public nsDisplayItem { public: nsDisplayCanvas(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) @@ -92,7 +77,7 @@ public: // Need intrinsic size & ratio, for ComputeObjectDestRect: nsIntSize canvasSize = f->GetCanvasSize(); IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSize); - nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSize); + AspectRatio intrinsicRatio = AspectRatio::FromSize(canvasSize); const nsRect destRect = nsLayoutUtils::ComputeObjectDestRect(constraintRect, @@ -211,10 +196,15 @@ nsHTMLCanvasFrame::GetIntrinsicSize() return IntrinsicSizeFromCanvasSize(GetCanvasSize()); } -/* virtual */ nsSize +/* virtual */ AspectRatio nsHTMLCanvasFrame::GetIntrinsicRatio() { - return IntrinsicRatioFromCanvasSize(GetCanvasSize()); +/* + if (StyleDisplay()->IsContainSize()) { + return AspectRatio(); + } + */ + return AspectRatio::FromSize(GetCanvasSize()); } /* virtual */ @@ -234,7 +224,7 @@ nsHTMLCanvasFrame::ComputeSize(nsRenderingContext *aRenderingContext, intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.width)); intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.height)); - nsSize intrinsicRatio = GetIntrinsicRatio(); // won't actually be used + AspectRatio intrinsicRatio = GetIntrinsicRatio(); return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM, intrinsicSize, intrinsicRatio, @@ -340,7 +330,7 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder, return nullptr; IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx); - nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx); + AspectRatio intrinsicRatio = AspectRatio::FromSize(canvasSizeInPx); nsRect dest = nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, intrinsicRatio, diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h index b2d159627..8432ad224 100644 --- a/layout/generic/nsHTMLCanvasFrame.h +++ b/layout/generic/nsHTMLCanvasFrame.h @@ -58,7 +58,7 @@ public: virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override; - virtual nsSize GetIntrinsicRatio() override; + virtual mozilla::AspectRatio GetIntrinsicRatio() override; virtual mozilla::LogicalSize ComputeSize(nsRenderingContext *aRenderingContext, diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index dfe83bcbe..d54ddc2b5 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -27,6 +27,7 @@ #include "FrameProperties.h" #include "LayoutConstants.h" #include "mozilla/layout/FrameChildList.h" +#include "mozilla/AspectRatio.h" #include "mozilla/Maybe.h" #include "mozilla/WritingModes.h" #include "nsDirection.h" @@ -2063,15 +2064,14 @@ public: virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0; /** - * Get the intrinsic ratio of this element, or nsSize(0,0) if it has - * no intrinsic ratio. The intrinsic ratio is the ratio of the - * height/width of a box with an intrinsic size or the intrinsic - * aspect ratio of a scalable vector image without an intrinsic size. + * Get the intrinsic ratio of this element, or a default-constructed + * AspectRatio if it has no intrinsic ratio. * - * Either one of the sides may be zero, indicating a zero or infinite - * ratio. + * The intrinsic ratio is the ratio of the width/height of a box with an + * intrinsic size or the intrinsic aspect ratio of a scalable vector image + * without an intrinsic size. */ - virtual nsSize GetIntrinsicRatio() = 0; + virtual mozilla::AspectRatio GetIntrinsicRatio() = 0; /** * Bit-flags to pass to ComputeSize in |aFlags| parameter. diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index b96af66b5..365b7810b 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -138,7 +138,6 @@ NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame) nsImageFrame::nsImageFrame(nsStyleContext* aContext) : nsAtomicContainerFrame(aContext), mComputedSize(0, 0), - mIntrinsicRatio(0, 0), mDisplayingIcon(false), mFirstFrameComplete(false), mReflowCallbackPosted(false), @@ -325,11 +324,11 @@ nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage) if (!aImage) return false; - nsSize oldIntrinsicRatio = mIntrinsicRatio; + AspectRatio oldIntrinsicRatio = mIntrinsicRatio; // Set intrinsic ratio to match aImage's reported intrinsic ratio. if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio))) - mIntrinsicRatio.SizeTo(0, 0); + mIntrinsicRatio = AspectRatio(); return mIntrinsicRatio != oldIntrinsicRatio; } @@ -557,7 +556,7 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) // Have to size to 0,0 so that GetDesiredSize recalculates the size. mIntrinsicSize.width.SetCoordValue(0); mIntrinsicSize.height.SetCoordValue(0); - mIntrinsicRatio.SizeTo(0, 0); + mIntrinsicRatio = AspectRatio(); intrinsicSizeChanged = true; } @@ -672,7 +671,7 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest, // Have to size to 0,0 so that GetDesiredSize recalculates the size mIntrinsicSize.width.SetCoordValue(0); mIntrinsicSize.height.SetCoordValue(0); - mIntrinsicRatio.SizeTo(0, 0); + mIntrinsicRatio = AspectRatio(); } if (mState & IMAGE_GOTINITIALREFLOW) { // do nothing if we haven't gotten the initial reflow yet @@ -808,7 +807,7 @@ nsImageFrame::EnsureIntrinsicSizeAndRatio() ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH))); mIntrinsicSize.width.SetCoordValue(edgeLengthToUse); mIntrinsicSize.height.SetCoordValue(edgeLengthToUse); - mIntrinsicRatio.SizeTo(1, 1); + mIntrinsicRatio = AspectRatio(1.0f); } } } @@ -932,7 +931,7 @@ nsImageFrame::GetIntrinsicSize() return mIntrinsicSize; } -/* virtual */ nsSize +/* virtual */ AspectRatio nsImageFrame::GetIntrinsicRatio() { return mIntrinsicRatio; diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 59af1be32..2414d89df 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -86,7 +86,7 @@ public: virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override; - virtual nsSize GetIntrinsicRatio() override; + virtual mozilla::AspectRatio GetIntrinsicRatio() override; virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput, @@ -333,7 +333,7 @@ private: nsCOMPtr mPrevImage; nsSize mComputedSize; mozilla::IntrinsicSize mIntrinsicSize; - nsSize mIntrinsicRatio; + mozilla::AspectRatio mIntrinsicRatio; bool mDisplayingIcon; bool mFirstFrameComplete; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 6a15a9cfa..60e4e8c96 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -784,7 +784,7 @@ IsPercentageAware(const nsIFrame* aFrame) // is calculated from the constraint equation used for // block-level, non-replaced elements in normal flow. nsIFrame *f = const_cast(aFrame); - if (f->GetIntrinsicRatio() != nsSize(0, 0) && + if (f->GetIntrinsicRatio() && // Some percents are treated like 'auto', so check != coord pos->mHeight.GetUnit() != eStyleUnit_Coord) { const IntrinsicSize &intrinsicSize = f->GetIntrinsicSize(); diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index fd9a7d32c..31d04a335 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -671,7 +671,7 @@ nsSubDocumentFrame::GetIntrinsicSize() return nsAtomicContainerFrame::GetIntrinsicSize(); } -/* virtual */ nsSize +/* virtual */ AspectRatio nsSubDocumentFrame::GetIntrinsicRatio() { nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame(); @@ -771,7 +771,7 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext, // Size & position the view according to 'object-fit' & 'object-position'. nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame(); IntrinsicSize intrinsSize; - nsSize intrinsRatio; + AspectRatio intrinsRatio; if (subDocRoot) { intrinsSize = subDocRoot->GetIntrinsicSize(); intrinsRatio = subDocRoot->GetIntrinsicRatio(); diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index 93d908dcc..907d33710 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -51,7 +51,7 @@ public: virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override; - virtual nsSize GetIntrinsicRatio() override; + virtual mozilla::AspectRatio GetIntrinsicRatio() override; virtual mozilla::LogicalSize ComputeAutoSize(nsRenderingContext* aRenderingContext, diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index cea209cb5..6bd6395a3 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -217,12 +217,10 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder, // Convert video size from pixel units into app units, to get an aspect-ratio // (which has to be represented as a nsSize) and an IntrinsicSize that we // can pass to ComputeObjectRenderRect. - nsSize aspectRatio(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.width), - nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.height)); + auto aspectRatio = AspectRatio::FromSize(videoSizeInPx); IntrinsicSize intrinsicSize; - intrinsicSize.width.SetCoordValue(aspectRatio.width); - intrinsicSize.height.SetCoordValue(aspectRatio.height); - + intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.width)); + intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.height)); nsRect dest = nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, aspectRatio, @@ -533,7 +531,9 @@ nsVideoFrame::ComputeSize(nsRenderingContext *aRenderingContext, intrinsicSize.height.SetCoordValue(size.height); // Only video elements have an intrinsic ratio. - nsSize intrinsicRatio = HasVideoElement() ? size : nsSize(0, 0); + auto intrinsicRatio = HasVideoElement() + ? AspectRatio::FromSize(size) + : AspectRatio(); return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM, intrinsicSize, intrinsicRatio, @@ -557,14 +557,14 @@ nscoord nsVideoFrame::GetPrefISize(nsRenderingContext *aRenderingContext) return result; } -nsSize nsVideoFrame::GetIntrinsicRatio() +AspectRatio nsVideoFrame::GetIntrinsicRatio() { if (!HasVideoElement()) { // Audio elements have no intrinsic ratio. - return nsSize(0, 0); + return AspectRatio(); } - return GetVideoIntrinsicSize(nullptr); + return AspectRatio::FromSize(GetVideoIntrinsicSize(nullptr)); } bool nsVideoFrame::ShouldDisplayPoster() diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h index d624ae6b9..f52cd8277 100644 --- a/layout/generic/nsVideoFrame.h +++ b/layout/generic/nsVideoFrame.h @@ -56,7 +56,7 @@ public: /* get the size of the video's display */ nsSize GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext); - virtual nsSize GetIntrinsicRatio() override; + virtual mozilla::AspectRatio GetIntrinsicRatio() override; virtual mozilla::LogicalSize ComputeSize(nsRenderingContext *aRenderingContext, mozilla::WritingMode aWritingMode, -- cgit v1.2.3