Convert Intrinsic Ratio from nsSize to Float.

This commit is contained in:
Fedor 2020-09-09 17:28:33 +03:00
parent 27db95eea0
commit ad2f81519e
33 changed files with 361 additions and 229 deletions

View File

@ -242,13 +242,13 @@ ClippedImage::GetIntrinsicSize(nsSize* aSize)
} }
NS_IMETHODIMP NS_IMETHODIMP
ClippedImage::GetIntrinsicRatio(nsSize* aRatio) ClippedImage::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
if (!ShouldClip()) { if (!ShouldClip()) {
return InnerImage()->GetIntrinsicRatio(aRatio); return InnerImage()->GetIntrinsicRatio(aRatio);
} }
*aRatio = nsSize(mClip.width, mClip.height); *aRatio = AspectRatio::FromSize(mClip.width, mClip.height);
return NS_OK; return NS_OK;
} }

View File

@ -35,7 +35,7 @@ public:
NS_IMETHOD GetWidth(int32_t* aWidth) override; NS_IMETHOD GetWidth(int32_t* aWidth) override;
NS_IMETHOD GetHeight(int32_t* aHeight) override; NS_IMETHOD GetHeight(int32_t* aHeight) override;
NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override;
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override; NS_IMETHOD GetIntrinsicRatio(AspectRatio* aRatio) override;
NS_IMETHOD_(already_AddRefed<SourceSurface>) NS_IMETHOD_(already_AddRefed<SourceSurface>)
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override; GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
NS_IMETHOD_(already_AddRefed<SourceSurface>) NS_IMETHOD_(already_AddRefed<SourceSurface>)

View File

@ -136,10 +136,10 @@ DynamicImage::GetIntrinsicSize(nsSize* aSize)
} }
NS_IMETHODIMP NS_IMETHODIMP
DynamicImage::GetIntrinsicRatio(nsSize* aSize) DynamicImage::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
IntSize intSize(mDrawable->Size()); auto size = mDrawable->Size();
*aSize = nsSize(intSize.width, intSize.height); *aRatio = AspectRatio::FromSize(size);
return NS_OK; return NS_OK;
} }

View File

@ -146,9 +146,9 @@ ImageWrapper::GetIntrinsicSize(nsSize* aSize)
} }
NS_IMETHODIMP NS_IMETHODIMP
ImageWrapper::GetIntrinsicRatio(nsSize* aSize) ImageWrapper::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
return mInnerImage->GetIntrinsicRatio(aSize); return mInnerImage->GetIntrinsicRatio(aRatio);
} }
NS_IMETHODIMP_(Orientation) NS_IMETHODIMP_(Orientation)

View File

@ -59,12 +59,12 @@ OrientedImage::GetIntrinsicSize(nsSize* aSize)
} }
NS_IMETHODIMP NS_IMETHODIMP
OrientedImage::GetIntrinsicRatio(nsSize* aRatio) OrientedImage::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
nsresult rv = InnerImage()->GetIntrinsicRatio(aRatio); nsresult rv = InnerImage()->GetIntrinsicRatio(aRatio);
if (mOrientation.SwapsWidthAndHeight()) { if (mOrientation.SwapsWidthAndHeight()) {
swap(aRatio->width, aRatio->height); *aRatio = aRatio->Inverted();
} }
return rv; return rv;

View File

@ -31,7 +31,7 @@ public:
NS_IMETHOD GetWidth(int32_t* aWidth) override; NS_IMETHOD GetWidth(int32_t* aWidth) override;
NS_IMETHOD GetHeight(int32_t* aHeight) override; NS_IMETHOD GetHeight(int32_t* aHeight) override;
NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override;
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override; NS_IMETHOD GetIntrinsicRatio(AspectRatio* aRatio) override;
NS_IMETHOD_(already_AddRefed<SourceSurface>) NS_IMETHOD_(already_AddRefed<SourceSurface>)
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override; GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
NS_IMETHOD_(already_AddRefed<SourceSurface>) NS_IMETHOD_(already_AddRefed<SourceSurface>)

View File

@ -240,13 +240,14 @@ RasterImage::GetIntrinsicSize(nsSize* aSize)
//****************************************************************************** //******************************************************************************
NS_IMETHODIMP NS_IMETHODIMP
RasterImage::GetIntrinsicRatio(nsSize* aRatio) RasterImage::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
if (mError) { if (mError) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
*aRatio = nsSize(mSize.width, mSize.height); *aRatio = AspectRatio::FromSize(mSize);
return NS_OK; return NS_OK;
} }

View File

@ -628,7 +628,7 @@ VectorImage::GetIntrinsicSize(nsSize* aSize)
//****************************************************************************** //******************************************************************************
NS_IMETHODIMP NS_IMETHODIMP
VectorImage::GetIntrinsicRatio(nsSize* aRatio) VectorImage::GetIntrinsicRatio(AspectRatio* aRatio)
{ {
if (mError || !mIsFullyLoaded) { if (mError || !mIsFullyLoaded) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

View File

@ -12,6 +12,7 @@
#include "gfxMatrix.h" #include "gfxMatrix.h"
#include "gfxRect.h" #include "gfxRect.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/AspectRatio.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "nsRect.h" #include "nsRect.h"
@ -55,6 +56,7 @@ native SamplingFilter(mozilla::gfx::SamplingFilter);
native nsIntRectByVal(nsIntRect); native nsIntRectByVal(nsIntRect);
[ref] native nsIntSize(nsIntSize); [ref] native nsIntSize(nsIntSize);
native nsSize(nsSize); native nsSize(nsSize);
native AspectRatio(mozilla::AspectRatio);
[ptr] native nsIFrame(nsIFrame); [ptr] native nsIFrame(nsIFrame);
native TempRefImageContainer(already_AddRefed<mozilla::layers::ImageContainer>); native TempRefImageContainer(already_AddRefed<mozilla::layers::ImageContainer>);
[ref] native ImageRegion(mozilla::image::ImageRegion); [ref] native ImageRegion(mozilla::image::ImageRegion);
@ -101,7 +103,7 @@ interface imgIContainer : nsISupports
* The (dimensionless) intrinsic ratio of this image. In the case of any * The (dimensionless) intrinsic ratio of this image. In the case of any
* error, an exception will be thrown. * error, an exception will be thrown.
*/ */
[noscript] readonly attribute nsSize intrinsicRatio; [noscript] readonly attribute AspectRatio intrinsicRatio;
/** /**
* Given a size at which this image will be displayed, and the drawing * Given a size at which this image will be displayed, and the drawing

View File

@ -3546,10 +3546,10 @@ ComputeDrawnSizeForBackground(const CSSSizeOrRatio& aIntrinsicSize,
imageSize.width = ComputeRoundedSize(imageSize.width, aBgPositioningArea.width); imageSize.width = ComputeRoundedSize(imageSize.width, aBgPositioningArea.width);
if (!isRepeatRoundInBothDimensions && if (!isRepeatRoundInBothDimensions &&
aLayerSize.mHeightType == nsStyleImageLayers::Size::DimensionType::eAuto) { aLayerSize.mHeightType == nsStyleImageLayers::Size::DimensionType::eAuto) {
// Restore intrinsic rato // Restore intrinsic ratio
if (aIntrinsicSize.mRatio.width) { if (aIntrinsicSize.mRatio) {
float scale = float(aIntrinsicSize.mRatio.height) / aIntrinsicSize.mRatio.width; imageSize.height =
imageSize.height = NSCoordSaturatingNonnegativeMultiply(imageSize.width, scale); aIntrinsicSize.mRatio.Inverted().ApplyTo(imageSize.width);
} }
} }
} }
@ -3560,10 +3560,9 @@ ComputeDrawnSizeForBackground(const CSSSizeOrRatio& aIntrinsicSize,
imageSize.height = ComputeRoundedSize(imageSize.height, aBgPositioningArea.height); imageSize.height = ComputeRoundedSize(imageSize.height, aBgPositioningArea.height);
if (!isRepeatRoundInBothDimensions && if (!isRepeatRoundInBothDimensions &&
aLayerSize.mWidthType == nsStyleImageLayers::Size::DimensionType::eAuto) { aLayerSize.mWidthType == nsStyleImageLayers::Size::DimensionType::eAuto) {
// Restore intrinsic rato // Restore intrinsic ratio
if (aIntrinsicSize.mRatio.height) { if (aIntrinsicSize.mRatio) {
float scale = float(aIntrinsicSize.mRatio.width) / aIntrinsicSize.mRatio.height; imageSize.width = aIntrinsicSize.mRatio.ApplyTo(imageSize.height);
imageSize.width = NSCoordSaturatingNonnegativeMultiply(imageSize.height, scale);
} }
} }
} }
@ -5264,17 +5263,11 @@ CSSSizeOrRatio::ComputeConcreteSize() const
return nsSize(mWidth, mHeight); return nsSize(mWidth, mHeight);
} }
if (mHasWidth) { if (mHasWidth) {
nscoord height = NSCoordSaturatingNonnegativeMultiply( return nsSize(mWidth, mRatio.Inverted().ApplyTo(mWidth));
mWidth,
double(mRatio.height) / mRatio.width);
return nsSize(mWidth, height);
} }
MOZ_ASSERT(mHasHeight); MOZ_ASSERT(mHasHeight);
nscoord width = NSCoordSaturatingNonnegativeMultiply( return nsSize(mRatio.ApplyTo(mHeight), mHeight);
mHeight,
double(mRatio.width) / mRatio.height);
return nsSize(width, mHeight);
} }
CSSSizeOrRatio CSSSizeOrRatio
@ -5297,6 +5290,16 @@ nsImageRenderer::ComputeIntrinsicSize()
if (haveHeight) { if (haveHeight) {
result.SetHeight(nsPresContext::CSSPixelsToAppUnits(imageIntSize.height)); result.SetHeight(nsPresContext::CSSPixelsToAppUnits(imageIntSize.height));
} }
if (!haveHeight && haveWidth && result.mRatio) {
nscoord intrinsicHeight =
result.mRatio.Inverted().ApplyTo(imageIntSize.width);
result.SetHeight(nsPresContext::CSSPixelsToAppUnits(intrinsicHeight));
} else if (haveHeight && !haveWidth && result.mRatio) {
nscoord intrinsicWidth = result.mRatio.ApplyTo(imageIntSize.height);
result.SetWidth(nsPresContext::CSSPixelsToAppUnits(intrinsicWidth));
}
break; break;
} }
case eStyleImageType_Element: case eStyleImageType_Element:
@ -5379,9 +5382,7 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
if (aSpecifiedSize.mHasWidth) { if (aSpecifiedSize.mHasWidth) {
nscoord height; nscoord height;
if (aIntrinsicSize.HasRatio()) { if (aIntrinsicSize.HasRatio()) {
height = NSCoordSaturatingNonnegativeMultiply( height = aIntrinsicSize.mRatio.Inverted().ApplyTo(aSpecifiedSize.mWidth);
aSpecifiedSize.mWidth,
double(aIntrinsicSize.mRatio.height) / aIntrinsicSize.mRatio.width);
} else if (aIntrinsicSize.mHasHeight) { } else if (aIntrinsicSize.mHasHeight) {
height = aIntrinsicSize.mHeight; height = aIntrinsicSize.mHeight;
} else { } else {
@ -5393,9 +5394,7 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
MOZ_ASSERT(aSpecifiedSize.mHasHeight); MOZ_ASSERT(aSpecifiedSize.mHasHeight);
nscoord width; nscoord width;
if (aIntrinsicSize.HasRatio()) { if (aIntrinsicSize.HasRatio()) {
width = NSCoordSaturatingNonnegativeMultiply( width = aIntrinsicSize.mRatio.ApplyTo(aSpecifiedSize.mHeight);
aSpecifiedSize.mHeight,
double(aIntrinsicSize.mRatio.width) / aIntrinsicSize.mRatio.height);
} else if (aIntrinsicSize.mHasWidth) { } else if (aIntrinsicSize.mHasWidth) {
width = aIntrinsicSize.mWidth; width = aIntrinsicSize.mWidth;
} else { } else {
@ -5406,32 +5405,57 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
/* static */ nsSize /* static */ nsSize
nsImageRenderer::ComputeConstrainedSize(const nsSize& aConstrainingSize, nsImageRenderer::ComputeConstrainedSize(const nsSize& aConstrainingSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
FitType aFitType) FitType aFitType)
{ {
if (aIntrinsicRatio.width <= 0 && aIntrinsicRatio.height <= 0) { if (!aIntrinsicRatio) {
return aConstrainingSize; return aConstrainingSize;
} }
float scaleX = double(aConstrainingSize.width) / aIntrinsicRatio.width; // Suppose we're doing a "contain" fit. If the image's aspect ratio has a
float scaleY = double(aConstrainingSize.height) / aIntrinsicRatio.height; // "fatter" shape than the constraint area, then we need to use the
// constraint area's full width, and we need to use the aspect ratio to
// produce a height. ON the other hand, if the aspect ratio is "skinnier", we
// use the constraint area's full height, and we use the aspect ratio to
// produce a width. (If instead we're doing a "cover" fit, then it can easily
// be seen that we should do precisely the opposite.)
//
// This is equivalent to the more descriptive alternative:
//
// AspectRatio::FromSize(aConstrainingSize) < aIntrinsicRatio
//
// But gracefully handling the case where one of the two dimensions from
// aConstrainingSize is zero. This is easy to prove since:
//
// aConstrainingSize.width / aConstrainingSize.height < aIntrinsicRatio
//
// Is trivially equivalent to:
//
// aIntrinsicRatio.width < aIntrinsicRatio * aConstrainingSize.height
//
// For the cases where height is not zero.
//
// We use float math here to avoid losing precision for very lareg backgrounds
// since we use saturating nscoord math otherwise.
const float constraintWidth = float(aConstrainingSize.width);
const float hypotheticalWidth =
aIntrinsicRatio.ApplyToFloat(aConstrainingSize.height);
nsSize size; nsSize size;
if ((aFitType == CONTAIN) == (scaleX < scaleY)) { if ((aFitType == CONTAIN) == (constraintWidth < hypotheticalWidth)) {
size.width = aConstrainingSize.width; size.width = aConstrainingSize.width;
size.height = NSCoordSaturatingNonnegativeMultiply( size.height = aIntrinsicRatio.Inverted().ApplyTo(aConstrainingSize.width);
aIntrinsicRatio.height, scaleX);
// If we're reducing the size by less than one css pixel, then just use the // If we're reducing the size by less than one css pixel, then just use the
// constraining size. // constraining size.
if (aFitType == CONTAIN && aConstrainingSize.height - size.height < nsPresContext::AppUnitsPerCSSPixel()) { if (aFitType == CONTAIN && aConstrainingSize.height - size.height < nsPresContext::AppUnitsPerCSSPixel()) {
size.height = aConstrainingSize.height; size.height = aConstrainingSize.height;
} }
} else { } else {
size.width = NSCoordSaturatingNonnegativeMultiply( size.height = aConstrainingSize.height;
aIntrinsicRatio.width, scaleY); size.width = aIntrinsicRatio.ApplyTo(aConstrainingSize.height);
if (aFitType == CONTAIN && aConstrainingSize.width - size.width < nsPresContext::AppUnitsPerCSSPixel()) { if (aFitType == CONTAIN && aConstrainingSize.width - size.width < nsPresContext::AppUnitsPerCSSPixel()) {
size.width = aConstrainingSize.width; size.width = aConstrainingSize.width;
} }
size.height = aConstrainingSize.height;
} }
return size; return size;
} }

View File

@ -17,6 +17,7 @@
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsStyleStruct.h" #include "nsStyleStruct.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "mozilla/AspectRatio.h"
class gfxDrawable; class gfxDrawable;
class nsStyleContext; class nsStyleContext;
@ -41,8 +42,7 @@ class ImageContainer;
struct CSSSizeOrRatio struct CSSSizeOrRatio
{ {
CSSSizeOrRatio() CSSSizeOrRatio()
: mRatio(0, 0) : mHasWidth(false)
, mHasWidth(false)
, mHasHeight(false) {} , mHasHeight(false) {}
bool CanComputeConcreteSize() const bool CanComputeConcreteSize() const
@ -50,12 +50,12 @@ struct CSSSizeOrRatio
return mHasWidth + mHasHeight + HasRatio() >= 2; return mHasWidth + mHasHeight + HasRatio() >= 2;
} }
bool IsConcrete() const { return mHasWidth && mHasHeight; } bool IsConcrete() const { return mHasWidth && mHasHeight; }
bool HasRatio() const { return mRatio.width > 0 && mRatio.height > 0; } bool HasRatio() const { return !!mRatio; }
bool IsEmpty() const bool IsEmpty() const
{ {
return (mHasWidth && mWidth <= 0) || return (mHasWidth && mWidth <= 0) ||
(mHasHeight && mHeight <= 0) || (mHasHeight && mHeight <= 0) ||
mRatio.width <= 0 || mRatio.height <= 0; !mRatio;
} }
// CanComputeConcreteSize must return true when ComputeConcreteSize is // CanComputeConcreteSize must return true when ComputeConcreteSize is
@ -67,7 +67,7 @@ struct CSSSizeOrRatio
mWidth = aWidth; mWidth = aWidth;
mHasWidth = true; mHasWidth = true;
if (mHasHeight) { if (mHasHeight) {
mRatio = nsSize(mWidth, mHeight); mRatio = AspectRatio::FromSize(mWidth, mHeight);
} }
} }
void SetHeight(nscoord aHeight) void SetHeight(nscoord aHeight)
@ -75,7 +75,7 @@ struct CSSSizeOrRatio
mHeight = aHeight; mHeight = aHeight;
mHasHeight = true; mHasHeight = true;
if (mHasWidth) { if (mHasWidth) {
mRatio = nsSize(mWidth, mHeight); mRatio = AspectRatio::FromSize(mWidth, mHeight);
} }
} }
void SetSize(const nsSize& aSize) void SetSize(const nsSize& aSize)
@ -84,16 +84,16 @@ struct CSSSizeOrRatio
mHeight = aSize.height; mHeight = aSize.height;
mHasWidth = true; mHasWidth = true;
mHasHeight = true; mHasHeight = true;
mRatio = aSize; mRatio = AspectRatio::FromSize(mWidth, mHeight);
} }
void SetRatio(const nsSize& aRatio) void SetRatio(const AspectRatio& aRatio)
{ {
MOZ_ASSERT(!mHasWidth || !mHasHeight, MOZ_ASSERT(!mHasWidth || !mHasHeight,
"Probably shouldn't be setting a ratio if we have a concrete size"); "Probably shouldn't be setting a ratio if we have a concrete size");
mRatio = aRatio; mRatio = aRatio;
} }
nsSize mRatio; AspectRatio mRatio;
nscoord mWidth; nscoord mWidth;
nscoord mHeight; nscoord mHeight;
bool mHasWidth; bool mHasWidth;
@ -184,11 +184,9 @@ public:
/** /**
* Compute the size of the rendered image using either the 'cover' or * Compute the size of the rendered image using either the 'cover' or
* 'contain' constraints (aFitType). * 'contain' constraints (aFitType).
* aIntrinsicRatio may be an invalid ratio, that is one or both of its
* dimensions can be less than or equal to zero.
*/ */
static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize, static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize,
const nsSize& aIntrinsicRatio, const mozilla::AspectRatio& aIntrinsicRatio,
FitType aFitType); FitType aFitType);
/** /**
* Compute the size of the rendered image (the concrete size) where no cover/ * Compute the size of the rendered image (the concrete size) where no cover/

View File

@ -3966,7 +3966,7 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
enum ObjectDimensionType { eWidth, eHeight }; enum ObjectDimensionType { eWidth, eHeight };
static nscoord static nscoord
ComputeMissingDimension(const nsSize& aDefaultObjectSize, ComputeMissingDimension(const nsSize& aDefaultObjectSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
const Maybe<nscoord>& aSpecifiedWidth, const Maybe<nscoord>& aSpecifiedWidth,
const Maybe<nscoord>& aSpecifiedHeight, const Maybe<nscoord>& aSpecifiedHeight,
ObjectDimensionType aDimensionToCompute) ObjectDimensionType aDimensionToCompute)
@ -3977,21 +3977,15 @@ ComputeMissingDimension(const nsSize& aDefaultObjectSize,
// 1. "If the object has an intrinsic aspect ratio, the missing dimension of // 1. "If the object has an intrinsic aspect ratio, the missing dimension of
// the concrete object size is calculated using the intrinsic aspect // the concrete object size is calculated using the intrinsic aspect
// ratio and the present dimension." // ratio and the present dimension."
if (aIntrinsicRatio.width > 0 && aIntrinsicRatio.height > 0) { if (aIntrinsicRatio) {
// Fill in the missing dimension using the intrinsic aspect ratio. // Fill in the missing dimension using the intrinsic aspect ratio.
nscoord knownDimensionSize;
float ratio;
if (aDimensionToCompute == eWidth) { if (aDimensionToCompute == eWidth) {
knownDimensionSize = *aSpecifiedHeight; return aIntrinsicRatio.ApplyTo(*aSpecifiedHeight);
ratio = aIntrinsicRatio.width / aIntrinsicRatio.height;
} else {
knownDimensionSize = *aSpecifiedWidth;
ratio = aIntrinsicRatio.height / aIntrinsicRatio.width;
} }
return NSCoordSaturatingNonnegativeMultiply(knownDimensionSize, ratio); return aIntrinsicRatio.Inverted().ApplyTo(*aSpecifiedWidth);
} }
// 2. "Otherwise, if the missing dimension is present in the objects // 2. "Otherwise, if the missing dimension is present in the object's
// intrinsic dimensions, [...]" // intrinsic dimensions, [...]"
// NOTE: *Skipping* this case, because we already know it's not true -- we're // NOTE: *Skipping* this case, because we already know it's not true -- we're
// in this function because the missing dimension is *not* present in // in this function because the missing dimension is *not* present in
@ -4029,7 +4023,7 @@ ComputeMissingDimension(const nsSize& aDefaultObjectSize,
static Maybe<nsSize> static Maybe<nsSize>
MaybeComputeObjectFitNoneSize(const nsSize& aDefaultObjectSize, MaybeComputeObjectFitNoneSize(const nsSize& aDefaultObjectSize,
const IntrinsicSize& aIntrinsicSize, const IntrinsicSize& aIntrinsicSize,
const nsSize& aIntrinsicRatio) const AspectRatio& aIntrinsicRatio)
{ {
// "If the object has an intrinsic height or width, its size is resolved as // "If the object has an intrinsic height or width, its size is resolved as
// if its intrinsic dimensions were given as the specified size." // if its intrinsic dimensions were given as the specified size."
@ -4076,15 +4070,13 @@ MaybeComputeObjectFitNoneSize(const nsSize& aDefaultObjectSize,
static nsSize static nsSize
ComputeConcreteObjectSize(const nsSize& aConstraintSize, ComputeConcreteObjectSize(const nsSize& aConstraintSize,
const IntrinsicSize& aIntrinsicSize, const IntrinsicSize& aIntrinsicSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
uint8_t aObjectFit) uint8_t aObjectFit)
{ {
// Handle default behavior (filling the container) w/ fast early return. // Handle default behavior (filling the container) w/ fast early return.
// (Also: if there's no valid intrinsic ratio, then we have the "fill" // (Also: if there's no valid intrinsic ratio, then we have the "fill"
// behavior & just use the constraint size.) // behavior & just use the constraint size.)
if (MOZ_LIKELY(aObjectFit == NS_STYLE_OBJECT_FIT_FILL) || if (MOZ_LIKELY(aObjectFit == NS_STYLE_OBJECT_FIT_FILL) || !aIntrinsicRatio) {
aIntrinsicRatio.width == 0 ||
aIntrinsicRatio.height == 0) {
return aConstraintSize; return aConstraintSize;
} }
@ -4171,7 +4163,7 @@ HasInitialObjectFitAndPosition(const nsStylePosition* aStylePos)
/* static */ nsRect /* static */ nsRect
nsLayoutUtils::ComputeObjectDestRect(const nsRect& aConstraintRect, nsLayoutUtils::ComputeObjectDestRect(const nsRect& aConstraintRect,
const IntrinsicSize& aIntrinsicSize, const IntrinsicSize& aIntrinsicSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
const nsStylePosition* aStylePos, const nsStylePosition* aStylePos,
nsPoint* aAnchorPoint) nsPoint* aAnchorPoint)
{ {
@ -5092,10 +5084,12 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
styleMinBSize.GetCoordValue() == 0)) || styleMinBSize.GetCoordValue() == 0)) ||
styleMaxBSize.GetUnit() != eStyleUnit_None) { styleMaxBSize.GetUnit() != eStyleUnit_None) {
nsSize ratio(aFrame->GetIntrinsicRatio()); AspectRatio ratio = aFrame->GetIntrinsicRatio();
nscoord ratioISize = (horizontalAxis ? ratio.width : ratio.height); if (ratio) {
nscoord ratioBSize = (horizontalAxis ? ratio.height : ratio.width); // Convert 'ratio' if necessary, so that it's storing ISize/BSize:
if (ratioBSize != 0) { if (!horizontalAxis) {
ratio = ratio.Inverted();
}
AddStateBitToAncestors(aFrame, AddStateBitToAncestors(aFrame,
NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE); NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
@ -5111,14 +5105,14 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
(aPercentageBasis.isNothing() && (aPercentageBasis.isNothing() &&
GetPercentBSize(styleBSize, aFrame, horizontalAxis, h))) { GetPercentBSize(styleBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing); h = std::max(0, h - bSizeTakenByBoxSizing);
result = NSCoordMulDiv(h, ratioISize, ratioBSize); result = ratio.ApplyTo(h);
} }
if (GetDefiniteSize(styleMaxBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) || if (GetDefiniteSize(styleMaxBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) ||
(aPercentageBasis.isNothing() && (aPercentageBasis.isNothing() &&
GetPercentBSize(styleMaxBSize, aFrame, horizontalAxis, h))) { GetPercentBSize(styleMaxBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing); h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord maxISize = NSCoordMulDiv(h, ratioISize, ratioBSize); nscoord maxISize = ratio.ApplyTo(h);
if (maxISize < result) { if (maxISize < result) {
result = maxISize; result = maxISize;
} }
@ -5131,7 +5125,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
(aPercentageBasis.isNothing() && (aPercentageBasis.isNothing() &&
GetPercentBSize(styleMinBSize, aFrame, horizontalAxis, h))) { GetPercentBSize(styleMinBSize, aFrame, horizontalAxis, h))) {
h = std::max(0, h - bSizeTakenByBoxSizing); h = std::max(0, h - bSizeTakenByBoxSizing);
nscoord minISize = NSCoordMulDiv(h, ratioISize, ratioBSize); nscoord minISize = ratio.ApplyTo(h);
if (minISize > result) { if (minISize > result) {
result = minISize; result = minISize;
} }
@ -6594,12 +6588,12 @@ nsLayoutUtils::DrawSingleImage(gfxContext& aContext,
/* static */ void /* static */ void
nsLayoutUtils::ComputeSizeForDrawing(imgIContainer *aImage, nsLayoutUtils::ComputeSizeForDrawing(imgIContainer *aImage,
CSSIntSize& aImageSize, /*outparam*/ CSSIntSize& aImageSize, /*outparam*/
nsSize& aIntrinsicRatio, /*outparam*/ AspectRatio& aIntrinsicRatio, /*outparam*/
bool& aGotWidth, /*outparam*/ bool& aGotWidth, /*outparam*/
bool& aGotHeight /*outparam*/) bool& aGotHeight /*outparam*/)
{ {
aGotWidth = NS_SUCCEEDED(aImage->GetWidth(&aImageSize.width)); aGotWidth = NS_SUCCEEDED(aImage->GetWidth(&aImageSize.width));
aGotHeight = NS_SUCCEEDED(aImage->GetHeight(&aImageSize.height)); aGotHeight = NS_SUCCEEDED(aImage->GetHeight(&aImageSize.height));
bool gotRatio = NS_SUCCEEDED(aImage->GetIntrinsicRatio(&aIntrinsicRatio)); bool gotRatio = NS_SUCCEEDED(aImage->GetIntrinsicRatio(&aIntrinsicRatio));
if (!(aGotWidth && aGotHeight) && !gotRatio) { if (!(aGotWidth && aGotHeight) && !gotRatio) {
@ -6607,7 +6601,7 @@ nsLayoutUtils::ComputeSizeForDrawing(imgIContainer *aImage,
// decoded) and should return zero size. // decoded) and should return zero size.
aGotWidth = aGotHeight = true; aGotWidth = aGotHeight = true;
aImageSize = CSSIntSize(0, 0); aImageSize = CSSIntSize(0, 0);
aIntrinsicRatio = nsSize(0, 0); aIntrinsicRatio = AspectRatio();
} }
} }
@ -6616,7 +6610,7 @@ nsLayoutUtils::ComputeSizeForDrawingWithFallback(imgIContainer* aImage,
const nsSize& aFallbackSize) const nsSize& aFallbackSize)
{ {
CSSIntSize imageSize; CSSIntSize imageSize;
nsSize imageRatio; AspectRatio imageRatio;
bool gotHeight, gotWidth; bool gotHeight, gotWidth;
ComputeSizeForDrawing(aImage, imageSize, imageRatio, gotWidth, gotHeight); ComputeSizeForDrawing(aImage, imageSize, imageRatio, gotWidth, gotHeight);
@ -6624,19 +6618,13 @@ nsLayoutUtils::ComputeSizeForDrawingWithFallback(imgIContainer* aImage,
// intrinsic ratio of the image. // intrinsic ratio of the image.
if (gotWidth != gotHeight) { if (gotWidth != gotHeight) {
if (!gotWidth) { if (!gotWidth) {
if (imageRatio.height != 0) { if (imageRatio) {
imageSize.width = imageSize.width = imageRatio.ApplyTo(imageSize.height);
NSCoordSaturatingNonnegativeMultiply(imageSize.height,
float(imageRatio.width) /
float(imageRatio.height));
gotWidth = true; gotWidth = true;
} }
} else { } else {
if (imageRatio.width != 0) { if (imageRatio) {
imageSize.height = imageSize.height = imageRatio.Inverted().ApplyTo(imageSize.width);
NSCoordSaturatingNonnegativeMultiply(imageSize.width,
float(imageRatio.height) /
float(imageRatio.width));
gotHeight = true; gotHeight = true;
} }
} }

View File

@ -65,6 +65,7 @@ struct nsStyleImageOrientation;
struct nsOverflowAreas; struct nsOverflowAreas;
namespace mozilla { namespace mozilla {
struct aspectRatio;
enum class CSSPseudoElementType : uint8_t; enum class CSSPseudoElementType : uint8_t;
class EventListenerManager; class EventListenerManager;
class SVGImageContext; class SVGImageContext;
@ -126,6 +127,7 @@ enum class RelativeTo {
*/ */
class nsLayoutUtils class nsLayoutUtils
{ {
typedef mozilla::AspectRatio AspectRatio;
typedef mozilla::dom::DOMRectList DOMRectList; typedef mozilla::dom::DOMRectList DOMRectList;
typedef mozilla::layers::Layer Layer; typedef mozilla::layers::Layer Layer;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters; typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
@ -1217,7 +1219,7 @@ public:
*/ */
static nsRect ComputeObjectDestRect(const nsRect& aConstraintRect, static nsRect ComputeObjectDestRect(const nsRect& aConstraintRect,
const IntrinsicSize& aIntrinsicSize, const IntrinsicSize& aIntrinsicSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
const nsStylePosition* aStylePos, const nsStylePosition* aStylePos,
nsPoint* aAnchorPoint = nullptr); nsPoint* aAnchorPoint = nullptr);
@ -1837,7 +1839,7 @@ public:
*/ */
static void ComputeSizeForDrawing(imgIContainer* aImage, static void ComputeSizeForDrawing(imgIContainer* aImage,
CSSIntSize& aImageSize, CSSIntSize& aImageSize,
nsSize& aIntrinsicRatio, AspectRatio& aIntrinsicRatio,
bool& aGotWidth, bool& aGotWidth,
bool& aGotHeight); bool& aGotHeight);

View File

@ -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 <algorithm>
#include <limits>
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<float>::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

View File

@ -109,6 +109,7 @@ EXPORTS += [
] ]
EXPORTS.mozilla += [ EXPORTS.mozilla += [
'AspectRatio.h',
'CSSAlignUtils.h', 'CSSAlignUtils.h',
'ReflowInput.h', 'ReflowInput.h',
'ReflowOutput.h', 'ReflowOutput.h',

View File

@ -557,8 +557,8 @@ public:
return mFlexShrink * mFlexBaseSize; return mFlexShrink * mFlexBaseSize;
} }
const nsSize& IntrinsicRatio() const { return mIntrinsicRatio; } const AspectRatio IntrinsicRatio() const { return mIntrinsicRatio; }
bool HasIntrinsicRatio() const { return mIntrinsicRatio != nsSize(); } bool HasIntrinsicRatio() const { return !!mIntrinsicRatio; }
// Getters for margin: // Getters for margin:
// =================== // ===================
@ -756,7 +756,7 @@ protected:
const float mFlexGrow; const float mFlexGrow;
const float mFlexShrink; const float mFlexShrink;
const nsSize mIntrinsicRatio; const AspectRatio mIntrinsicRatio;
const nsMargin mBorderPadding; const nsMargin mBorderPadding;
nsMargin mMargin; // non-const because we need to resolve auto margins 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 // 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 // intrinsic ratio. The caller is responsible for ensuring that the passed-in
// component (or else we'll divide by 0). // intrinsic ratio is not zero.
static nscoord static nscoord
MainSizeFromAspectRatio(nscoord aCrossSize, MainSizeFromAspectRatio(nscoord aCrossSize,
const nsSize& aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
const FlexboxAxisTracker& aAxisTracker) const FlexboxAxisTracker& aAxisTracker)
{ {
MOZ_ASSERT(aAxisTracker.GetCrossComponent(aIntrinsicRatio) != 0, MOZ_ASSERT(aIntrinsicRatio,
"Invalid ratio; will divide by 0! Caller should've checked..."); "Invalid ratio; will divide by 0! Caller should've checked...");
AspectRatio ratio = aAxisTracker.IsMainAxisHorizontal() ?
aIntrinsicRatio :
aIntrinsicRatio.Inverted();
if (aAxisTracker.IsCrossAxisHorizontal()) { return ratio.ApplyTo(aCrossSize);
// 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);
} }
// Partially resolves "min-[width|height]:auto" and returns the resulting value. // 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 // * if the item has an intrinsic aspect ratio, the width (height) calculated
// from the aspect ratio and any definite size constraints in the opposite // from the aspect ratio and any definite size constraints in the opposite
// dimension. // dimension.
if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) { if (aFlexItem.IntrinsicRatio()) {
// We have a usable aspect ratio. (not going to divide by 0) // We have a usable aspect ratio. (not going to divide by 0)
const bool useMinSizeIfCrossSizeIsIndefinite = true; const bool useMinSizeIfCrossSizeIsIndefinite = true;
nscoord crossSizeToUseWithRatio = nscoord crossSizeToUseWithRatio =
@ -1617,7 +1615,7 @@ ResolveAutoFlexBasisFromRatio(FlexItem& aFlexItem,
// - a definite cross size // - a definite cross size
// then the flex base size is calculated from its inner cross size and the // then the flex base size is calculated from its inner cross size and the
// flex items intrinsic aspect ratio. // flex items intrinsic aspect ratio.
if (aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) != 0) { if (aFlexItem.IntrinsicRatio()) {
// We have a usable aspect ratio. (not going to divide by 0) // We have a usable aspect ratio. (not going to divide by 0)
const bool useMinSizeIfCrossSizeIsIndefinite = false; const bool useMinSizeIfCrossSizeIsIndefinite = false;
nscoord crossSizeToUseWithRatio = nscoord crossSizeToUseWithRatio =
@ -1693,8 +1691,7 @@ nsFlexContainerFrame::
// (We'll consider that later, if we need to.) // (We'll consider that later, if we need to.)
resolvedMinSize = PartiallyResolveAutoMinSize(aFlexItem, aItemReflowInput, resolvedMinSize = PartiallyResolveAutoMinSize(aFlexItem, aItemReflowInput,
aAxisTracker); aAxisTracker);
if (resolvedMinSize > 0 && if (resolvedMinSize > 0 && !aFlexItem.IntrinsicRatio()) {
aAxisTracker.GetCrossComponent(aFlexItem.IntrinsicRatio()) == 0) {
// We don't have a usable aspect ratio, so we need to consider our // 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-content size as another candidate min-size, which we'll have to
// min() with the current resolvedMinSize. // min() with the current resolvedMinSize.

View File

@ -4641,10 +4641,10 @@ nsFrame::GetIntrinsicSize()
return IntrinsicSize(); // default is width/height set to eStyleUnit_None return IntrinsicSize(); // default is width/height set to eStyleUnit_None
} }
/* virtual */ nsSize /* virtual */ AspectRatio
nsFrame::GetIntrinsicRatio() nsFrame::GetIntrinsicRatio()
{ {
return nsSize(0, 0); return AspectRatio();
} }
/* virtual */ /* virtual */
@ -4658,7 +4658,7 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
const LogicalSize& aPadding, const LogicalSize& aPadding,
ComputeSizeFlags aFlags) ComputeSizeFlags aFlags)
{ {
MOZ_ASSERT(GetIntrinsicRatio() == nsSize(0,0), MOZ_ASSERT(!GetIntrinsicRatio(),
"Please override this method and call " "Please override this method and call "
"nsFrame::ComputeSizeWithIntrinsicDimensions instead."); "nsFrame::ComputeSizeWithIntrinsicDimensions instead.");
LogicalSize result = ComputeAutoSize(aRenderingContext, aWM, LogicalSize result = ComputeAutoSize(aRenderingContext, aWM,
@ -4914,13 +4914,15 @@ LogicalSize
nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingContext, nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingContext,
WritingMode aWM, WritingMode aWM,
const IntrinsicSize& aIntrinsicSize, const IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio, const AspectRatio& aIntrinsicRatio,
const LogicalSize& aCBSize, const LogicalSize& aCBSize,
const LogicalSize& aMargin, const LogicalSize& aMargin,
const LogicalSize& aBorder, const LogicalSize& aBorder,
const LogicalSize& aPadding, const LogicalSize& aPadding,
ComputeSizeFlags aFlags) ComputeSizeFlags aFlags)
{ {
auto logicalRatio =
aWM.IsVertical() ? aIntrinsicRatio.Inverted() : aIntrinsicRatio;
const nsStylePosition* stylePos = StylePosition(); const nsStylePosition* stylePos = StylePosition();
const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM); const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM); const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
@ -5181,10 +5183,6 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
intrinsicBSize = 0; 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: // Now calculate the used values for iSize and bSize:
if (isAutoISize) { if (isAutoISize) {
@ -5198,9 +5196,9 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
if (hasIntrinsicISize) { if (hasIntrinsicISize) {
tentISize = intrinsicISize; tentISize = intrinsicISize;
} else if (hasIntrinsicBSize && logicalRatio.BSize(aWM) > 0) { } else if (hasIntrinsicBSize && logicalRatio) {
tentISize = NSCoordMulDiv(intrinsicBSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); tentISize = logicalRatio.ApplyTo(intrinsicBSize);
} else if (logicalRatio.ISize(aWM) > 0) { } else if (logicalRatio) {
tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar? tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar?
if (tentISize < 0) tentISize = 0; if (tentISize < 0) tentISize = 0;
} else { } else {
@ -5217,8 +5215,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
if (hasIntrinsicBSize) { if (hasIntrinsicBSize) {
tentBSize = intrinsicBSize; tentBSize = intrinsicBSize;
} else if (logicalRatio.ISize(aWM) > 0) { } else if (logicalRatio) {
tentBSize = NSCoordMulDiv(tentISize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); tentBSize = logicalRatio.Inverted().ApplyTo(tentISize);
} else { } else {
tentBSize = nsPresContext::CSSPixelsToAppUnits(150); tentBSize = nsPresContext::CSSPixelsToAppUnits(150);
} }
@ -5229,46 +5227,39 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
stretchB = (stretchI == eStretch ? eStretch : eStretchPreservingRatio); stretchB = (stretchI == eStretch ? eStretch : eStretchPreservingRatio);
} }
if (aIntrinsicRatio != nsSize(0, 0)) { if (logicalRatio) {
if (stretchI == eStretch) { if (stretchI == eStretch) {
tentISize = iSize; // * / 'stretch' tentISize = iSize; // * / 'stretch'
if (stretchB == eStretch) { if (stretchB == eStretch) {
tentBSize = bSize; // 'stretch' / 'stretch' tentBSize = bSize; // 'stretch' / 'stretch'
} else if (stretchB == eStretchPreservingRatio && logicalRatio.ISize(aWM) > 0) { } else if (stretchB == eStretchPreservingRatio) {
// 'normal' / 'stretch' // 'normal' / 'stretch'
tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
} }
} else if (stretchB == eStretch) { } else if (stretchB == eStretch) {
tentBSize = bSize; // 'stretch' / * (except 'stretch') tentBSize = bSize; // 'stretch' / * (except 'stretch')
if (stretchI == eStretchPreservingRatio && logicalRatio.BSize(aWM) > 0) { if (stretchI == eStretchPreservingRatio) {
// 'stretch' / 'normal' // 'stretch' / 'normal'
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); tentISize = logicalRatio.ApplyTo(bSize);
} }
} else if (stretchI == eStretchPreservingRatio) { } else if (stretchI == eStretchPreservingRatio) {
tentISize = iSize; // * (except 'stretch') / 'normal' tentISize = iSize; // * (except 'stretch') / 'normal'
if (logicalRatio.ISize(aWM) > 0) { tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
tentBSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM));
}
if (stretchB == eStretchPreservingRatio && tentBSize > bSize) { if (stretchB == eStretchPreservingRatio && tentBSize > bSize) {
// Stretch within the CB size with preserved intrinsic ratio. // Stretch within the CB size with preserved intrinsic ratio.
tentBSize = bSize; // 'normal' / 'normal' tentBSize = bSize; // 'normal' / 'normal'
if (logicalRatio.BSize(aWM) > 0) { tentISize = logicalRatio.ApplyTo(bSize);
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
} }
} else if (stretchB == eStretchPreservingRatio) { } else if (stretchB == eStretchPreservingRatio) {
tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch') tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch')
if (logicalRatio.BSize(aWM) > 0) { tentISize = logicalRatio.ApplyTo(bSize);
tentISize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM));
}
} }
} }
// ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when applying // ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when applying
// the min/max-size. We don't want that when we have 'stretch' in either // 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. // axis because tentISize/tentBSize is likely not according to ratio now.
if (aIntrinsicRatio != nsSize(0, 0) && if (logicalRatio && stretchI != eStretch && stretchB != eStretch) {
stretchI != eStretch && stretchB != eStretch) {
nsSize autoSize = nsLayoutUtils:: nsSize autoSize = nsLayoutUtils::
ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize, ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize,
maxISize, maxBSize, maxISize, maxBSize,
@ -5289,8 +5280,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
// 'auto' iSize, non-'auto' bSize // 'auto' iSize, non-'auto' bSize
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize); bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
if (stretchI != eStretch) { if (stretchI != eStretch) {
if (logicalRatio.BSize(aWM) > 0) { if (logicalRatio) {
iSize = NSCoordMulDiv(bSize, logicalRatio.ISize(aWM), logicalRatio.BSize(aWM)); iSize = logicalRatio.ApplyTo(bSize);
} else if (hasIntrinsicISize) { } else if (hasIntrinsicISize) {
if (!((aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) && if (!((aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) &&
intrinsicISize > iSize)) { intrinsicISize > iSize)) {
@ -5309,8 +5300,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
// non-'auto' iSize, 'auto' bSize // non-'auto' iSize, 'auto' bSize
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize); iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
if (stretchB != eStretch) { if (stretchB != eStretch) {
if (logicalRatio.ISize(aWM) > 0) { if (logicalRatio) {
bSize = NSCoordMulDiv(iSize, logicalRatio.BSize(aWM), logicalRatio.ISize(aWM)); bSize = logicalRatio.Inverted().ApplyTo(iSize);
} else if (hasIntrinsicBSize) { } else if (hasIntrinsicBSize) {
if (!((aFlags & ComputeSizeFlags::eBClampMarginBoxMinSize) && if (!((aFlags & ComputeSizeFlags::eBClampMarginBoxMinSize) &&
intrinsicBSize > bSize)) { intrinsicBSize > bSize)) {

View File

@ -264,7 +264,7 @@ public:
IntrinsicISizeOffsetData IntrinsicISizeOffsetData
IntrinsicISizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override; IntrinsicISizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual mozilla::LogicalSize virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext* aRenderingContext, ComputeSize(nsRenderingContext* aRenderingContext,
@ -285,7 +285,7 @@ public:
nsRenderingContext* aRenderingContext, nsRenderingContext* aRenderingContext,
mozilla::WritingMode aWM, mozilla::WritingMode aWM,
const mozilla::IntrinsicSize& aIntrinsicSize, const mozilla::IntrinsicSize& aIntrinsicSize,
nsSize aIntrinsicRatio, const mozilla::AspectRatio& aIntrinsicRatio,
const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aCBSize,
const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorder, const mozilla::LogicalSize& aBorder,

View File

@ -44,21 +44,6 @@ IntrinsicSizeFromCanvasSize(const nsIntSize& aCanvasSizeInPx)
return intrinsicSize; 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 { class nsDisplayCanvas : public nsDisplayItem {
public: public:
nsDisplayCanvas(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) nsDisplayCanvas(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
@ -92,7 +77,7 @@ public:
// Need intrinsic size & ratio, for ComputeObjectDestRect: // Need intrinsic size & ratio, for ComputeObjectDestRect:
nsIntSize canvasSize = f->GetCanvasSize(); nsIntSize canvasSize = f->GetCanvasSize();
IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSize); IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSize);
nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSize); AspectRatio intrinsicRatio = AspectRatio::FromSize(canvasSize);
const nsRect destRect = const nsRect destRect =
nsLayoutUtils::ComputeObjectDestRect(constraintRect, nsLayoutUtils::ComputeObjectDestRect(constraintRect,
@ -211,10 +196,16 @@ nsHTMLCanvasFrame::GetIntrinsicSize()
return IntrinsicSizeFromCanvasSize(GetCanvasSize()); return IntrinsicSizeFromCanvasSize(GetCanvasSize());
} }
/* virtual */ nsSize /* virtual */ AspectRatio
nsHTMLCanvasFrame::GetIntrinsicRatio() nsHTMLCanvasFrame::GetIntrinsicRatio()
{ {
return IntrinsicRatioFromCanvasSize(GetCanvasSize()); // When 'contain: size' is implemented, make sure to check for it.
/*
if (StyleDisplay()->IsContainSize()) {
return AspectRatio();
}
*/
return AspectRatio::FromSize(GetCanvasSize());
} }
/* virtual */ /* virtual */
@ -234,7 +225,7 @@ nsHTMLCanvasFrame::ComputeSize(nsRenderingContext *aRenderingContext,
intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.width)); intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.width));
intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.height)); intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.height));
nsSize intrinsicRatio = GetIntrinsicRatio(); // won't actually be used AspectRatio intrinsicRatio = GetIntrinsicRatio();
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM, return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, intrinsicRatio, intrinsicSize, intrinsicRatio,
@ -340,7 +331,7 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
return nullptr; return nullptr;
IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx); IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx); AspectRatio intrinsicRatio = AspectRatio::FromSize(canvasSizeInPx);
nsRect dest = nsRect dest =
nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, intrinsicRatio, nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, intrinsicRatio,

View File

@ -58,7 +58,7 @@ public:
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual mozilla::LogicalSize virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext *aRenderingContext, ComputeSize(nsRenderingContext *aRenderingContext,

View File

@ -27,6 +27,7 @@
#include "FrameProperties.h" #include "FrameProperties.h"
#include "LayoutConstants.h" #include "LayoutConstants.h"
#include "mozilla/layout/FrameChildList.h" #include "mozilla/layout/FrameChildList.h"
#include "mozilla/AspectRatio.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/WritingModes.h" #include "mozilla/WritingModes.h"
#include "nsDirection.h" #include "nsDirection.h"
@ -2063,15 +2064,14 @@ public:
virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0; virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
/** /**
* Get the intrinsic ratio of this element, or nsSize(0,0) if it has * Get the intrinsic ratio of this element, or a default-constructed
* no intrinsic ratio. The intrinsic ratio is the ratio of the * AspectRatio if it has no intrinsic ratio.
* height/width of a box with an intrinsic size or the intrinsic
* aspect ratio of a scalable vector image without an intrinsic size.
* *
* Either one of the sides may be zero, indicating a zero or infinite * The intrinsic ratio is the ratio of the width/height of a box with an
* ratio. * 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. * Bit-flags to pass to ComputeSize in |aFlags| parameter.

View File

@ -138,7 +138,6 @@ NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
nsImageFrame::nsImageFrame(nsStyleContext* aContext) : nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
nsAtomicContainerFrame(aContext), nsAtomicContainerFrame(aContext),
mComputedSize(0, 0), mComputedSize(0, 0),
mIntrinsicRatio(0, 0),
mDisplayingIcon(false), mDisplayingIcon(false),
mFirstFrameComplete(false), mFirstFrameComplete(false),
mReflowCallbackPosted(false), mReflowCallbackPosted(false),
@ -325,11 +324,11 @@ nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage)
if (!aImage) if (!aImage)
return false; return false;
nsSize oldIntrinsicRatio = mIntrinsicRatio; AspectRatio oldIntrinsicRatio = mIntrinsicRatio;
// Set intrinsic ratio to match aImage's reported intrinsic ratio. // Set intrinsic ratio to match aImage's reported intrinsic ratio.
if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio))) if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio)))
mIntrinsicRatio.SizeTo(0, 0); mIntrinsicRatio = AspectRatio();
return mIntrinsicRatio != oldIntrinsicRatio; 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. // Have to size to 0,0 so that GetDesiredSize recalculates the size.
mIntrinsicSize.width.SetCoordValue(0); mIntrinsicSize.width.SetCoordValue(0);
mIntrinsicSize.height.SetCoordValue(0); mIntrinsicSize.height.SetCoordValue(0);
mIntrinsicRatio.SizeTo(0, 0); mIntrinsicRatio = AspectRatio();
intrinsicSizeChanged = true; intrinsicSizeChanged = true;
} }
@ -672,7 +671,7 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest,
// Have to size to 0,0 so that GetDesiredSize recalculates the size // Have to size to 0,0 so that GetDesiredSize recalculates the size
mIntrinsicSize.width.SetCoordValue(0); mIntrinsicSize.width.SetCoordValue(0);
mIntrinsicSize.height.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 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))); ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH)));
mIntrinsicSize.width.SetCoordValue(edgeLengthToUse); mIntrinsicSize.width.SetCoordValue(edgeLengthToUse);
mIntrinsicSize.height.SetCoordValue(edgeLengthToUse); mIntrinsicSize.height.SetCoordValue(edgeLengthToUse);
mIntrinsicRatio.SizeTo(1, 1); mIntrinsicRatio = AspectRatio(1.0f);
} }
} }
} }
@ -932,7 +931,7 @@ nsImageFrame::GetIntrinsicSize()
return mIntrinsicSize; return mIntrinsicSize;
} }
/* virtual */ nsSize /* virtual */ AspectRatio
nsImageFrame::GetIntrinsicRatio() nsImageFrame::GetIntrinsicRatio()
{ {
return mIntrinsicRatio; return mIntrinsicRatio;

View File

@ -86,7 +86,7 @@ public:
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual void Reflow(nsPresContext* aPresContext, virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput, const ReflowInput& aReflowInput,
@ -333,7 +333,7 @@ private:
nsCOMPtr<imgIContainer> mPrevImage; nsCOMPtr<imgIContainer> mPrevImage;
nsSize mComputedSize; nsSize mComputedSize;
mozilla::IntrinsicSize mIntrinsicSize; mozilla::IntrinsicSize mIntrinsicSize;
nsSize mIntrinsicRatio; mozilla::AspectRatio mIntrinsicRatio;
bool mDisplayingIcon; bool mDisplayingIcon;
bool mFirstFrameComplete; bool mFirstFrameComplete;

View File

@ -784,7 +784,7 @@ IsPercentageAware(const nsIFrame* aFrame)
// is calculated from the constraint equation used for // is calculated from the constraint equation used for
// block-level, non-replaced elements in normal flow. // block-level, non-replaced elements in normal flow.
nsIFrame *f = const_cast<nsIFrame*>(aFrame); nsIFrame *f = const_cast<nsIFrame*>(aFrame);
if (f->GetIntrinsicRatio() != nsSize(0, 0) && if (f->GetIntrinsicRatio() &&
// Some percents are treated like 'auto', so check != coord // Some percents are treated like 'auto', so check != coord
pos->mHeight.GetUnit() != eStyleUnit_Coord) { pos->mHeight.GetUnit() != eStyleUnit_Coord) {
const IntrinsicSize &intrinsicSize = f->GetIntrinsicSize(); const IntrinsicSize &intrinsicSize = f->GetIntrinsicSize();

View File

@ -671,7 +671,7 @@ nsSubDocumentFrame::GetIntrinsicSize()
return nsAtomicContainerFrame::GetIntrinsicSize(); return nsAtomicContainerFrame::GetIntrinsicSize();
} }
/* virtual */ nsSize /* virtual */ AspectRatio
nsSubDocumentFrame::GetIntrinsicRatio() nsSubDocumentFrame::GetIntrinsicRatio()
{ {
nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame(); nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
@ -771,7 +771,7 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
// Size & position the view according to 'object-fit' & 'object-position'. // Size & position the view according to 'object-fit' & 'object-position'.
nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame(); nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
IntrinsicSize intrinsSize; IntrinsicSize intrinsSize;
nsSize intrinsRatio; AspectRatio intrinsRatio;
if (subDocRoot) { if (subDocRoot) {
intrinsSize = subDocRoot->GetIntrinsicSize(); intrinsSize = subDocRoot->GetIntrinsicSize();
intrinsRatio = subDocRoot->GetIntrinsicRatio(); intrinsRatio = subDocRoot->GetIntrinsicRatio();

View File

@ -51,7 +51,7 @@ public:
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual mozilla::LogicalSize virtual mozilla::LogicalSize
ComputeAutoSize(nsRenderingContext* aRenderingContext, ComputeAutoSize(nsRenderingContext* aRenderingContext,

View File

@ -217,12 +217,10 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
// Convert video size from pixel units into app units, to get an aspect-ratio // 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 // (which has to be represented as a nsSize) and an IntrinsicSize that we
// can pass to ComputeObjectRenderRect. // can pass to ComputeObjectRenderRect.
nsSize aspectRatio(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.width), auto aspectRatio = AspectRatio::FromSize(videoSizeInPx);
nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.height));
IntrinsicSize intrinsicSize; IntrinsicSize intrinsicSize;
intrinsicSize.width.SetCoordValue(aspectRatio.width); intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.width));
intrinsicSize.height.SetCoordValue(aspectRatio.height); intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(videoSizeInPx.height));
nsRect dest = nsLayoutUtils::ComputeObjectDestRect(area, nsRect dest = nsLayoutUtils::ComputeObjectDestRect(area,
intrinsicSize, intrinsicSize,
aspectRatio, aspectRatio,
@ -533,7 +531,9 @@ nsVideoFrame::ComputeSize(nsRenderingContext *aRenderingContext,
intrinsicSize.height.SetCoordValue(size.height); intrinsicSize.height.SetCoordValue(size.height);
// Only video elements have an intrinsic ratio. // 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, return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
intrinsicSize, intrinsicRatio, intrinsicSize, intrinsicRatio,
@ -557,14 +557,14 @@ nscoord nsVideoFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
return result; return result;
} }
nsSize nsVideoFrame::GetIntrinsicRatio() AspectRatio nsVideoFrame::GetIntrinsicRatio()
{ {
if (!HasVideoElement()) { if (!HasVideoElement()) {
// Audio elements have no intrinsic ratio. // Audio elements have no intrinsic ratio.
return nsSize(0, 0); return AspectRatio();
} }
return GetVideoIntrinsicSize(nullptr); return AspectRatio::FromSize(GetVideoIntrinsicSize(nullptr));
} }
bool nsVideoFrame::ShouldDisplayPoster() bool nsVideoFrame::ShouldDisplayPoster()

View File

@ -56,7 +56,7 @@ public:
/* get the size of the video's display */ /* get the size of the video's display */
nsSize GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext); nsSize GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext);
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual mozilla::LogicalSize virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext *aRenderingContext, ComputeSize(nsRenderingContext *aRenderingContext,
mozilla::WritingMode aWritingMode, mozilla::WritingMode aWritingMode,

View File

@ -2731,7 +2731,7 @@ nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImag
} }
if (imgContainer) { if (imgContainer) {
CSSIntSize imageSize; CSSIntSize imageSize;
nsSize imageRatio; AspectRatio imageRatio;
bool hasWidth, hasHeight; bool hasWidth, hasHeight;
nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio, nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
hasWidth, hasHeight); hasWidth, hasHeight);
@ -2744,7 +2744,7 @@ nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImag
// If the image has an intrinsic ratio, rendering will depend on frame // If the image has an intrinsic ratio, rendering will depend on frame
// size when background-size is all auto. // size when background-size is all auto.
if (imageRatio != nsSize(0, 0)) { if (imageRatio) {
return mWidthType == mHeightType; return mWidthType == mHeightType;
} }

View File

@ -232,28 +232,38 @@ nsSVGOuterSVGFrame::GetIntrinsicSize()
return intrinsicSize; return intrinsicSize;
} }
/* virtual */ nsSize /* virtual */ AspectRatio
nsSVGOuterSVGFrame::GetIntrinsicRatio() nsSVGOuterSVGFrame::GetIntrinsicRatio()
{ {
// 2020-07-14 (RealityRipple) Firefox Uses a new IsReplacedAndContainSize(this)
// function call [Line 96-99 on trunk].
/*
static inline bool IsReplacedAndContainSize(const nsSVGOuterSVGFrame* aFrame) {
return aFrame->GetContent->GetParent() &&
aFrame->StyleDisplay()->IsContainSize();
}
*/
// but since contain: size doesn't exist in Pale Moon yet...
/*
if (IsReplacedAndContainSize(this)) {
return AspectRatio();
}
*/
// We only have an intrinsic size/ratio if our width and height attributes // We only have an intrinsic size/ratio if our width and height attributes
// are both specified and set to non-percentage values, or we have a viewBox // are both specified and set to non-percentage values, or we have a viewBox
// rect: http://www.w3.org/TR/SVGMobile12/coords.html#IntrinsicSizing // rect: http://www.w3.org/TR/SVGMobile12/coords.html#IntrinsicSizing
// Unfortunately we have to return the ratio as two nscoords whereas what
// we have are two floats. Using app units allows for some floating point
// values to work but really small or large numbers will fail.
SVGSVGElement *content = static_cast<SVGSVGElement*>(mContent); SVGSVGElement *content = static_cast<SVGSVGElement*>(mContent);
nsSVGLength2 &width = content->mLengthAttributes[SVGSVGElement::ATTR_WIDTH]; nsSVGLength2 &width = content->mLengthAttributes[SVGSVGElement::ATTR_WIDTH];
nsSVGLength2 &height = content->mLengthAttributes[SVGSVGElement::ATTR_HEIGHT]; nsSVGLength2 &height = content->mLengthAttributes[SVGSVGElement::ATTR_HEIGHT];
if (!width.IsPercentage() && !height.IsPercentage()) { if (!width.IsPercentage() && !height.IsPercentage()) {
nsSize ratio( return AspectRatio::FromSize(width.GetAnimValue(content),
nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(content)), height.GetAnimValue(content));
nsPresContext::CSSPixelsToAppUnits(height.GetAnimValue(content)));
if (ratio.width < 0) {
ratio.width = 0;
}
if (ratio.height < 0) {
ratio.height = 0;
}
return ratio;
} }
SVGViewElement* viewElement = content->GetCurrentViewElement(); SVGViewElement* viewElement = content->GetCurrentViewElement();
@ -267,17 +277,7 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio()
} }
if (viewbox) { if (viewbox) {
float viewBoxWidth = viewbox->width; return AspectRatio::FromSize(viewbox->width, viewbox->height);
float viewBoxHeight = viewbox->height;
if (viewBoxWidth < 0.0f) {
viewBoxWidth = 0.0f;
}
if (viewBoxHeight < 0.0f) {
viewBoxHeight = 0.0f;
}
return nsSize(nsPresContext::CSSPixelsToAppUnits(viewBoxWidth),
nsPresContext::CSSPixelsToAppUnits(viewBoxHeight));
} }
return nsSVGDisplayContainerFrame::GetIntrinsicRatio(); return nsSVGDisplayContainerFrame::GetIntrinsicRatio();

View File

@ -42,7 +42,7 @@ public:
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override; virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override; virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override; virtual mozilla::AspectRatio GetIntrinsicRatio() override;
virtual mozilla::LogicalSize virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext *aRenderingContext, ComputeSize(nsRenderingContext *aRenderingContext,

View File

@ -402,12 +402,12 @@ nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext,
// Determine dest rect based on intrinsic size & ratio, along with // Determine dest rect based on intrinsic size & ratio, along with
// 'object-fit' & 'object-position' properties: // 'object-fit' & 'object-position' properties:
IntrinsicSize intrinsicSize; IntrinsicSize intrinsicSize;
nsSize intrinsicRatio; AspectRatio intrinsicRatio;
if (mIntrinsicSize.width > 0 && mIntrinsicSize.height > 0) { if (mIntrinsicSize.width > 0 && mIntrinsicSize.height > 0) {
// Image has a valid size; use it as intrinsic size & ratio. // Image has a valid size; use it as intrinsic size & ratio.
intrinsicSize.width.SetCoordValue(mIntrinsicSize.width); intrinsicSize.width.SetCoordValue(mIntrinsicSize.width);
intrinsicSize.height.SetCoordValue(mIntrinsicSize.height); intrinsicSize.height.SetCoordValue(mIntrinsicSize.height);
intrinsicRatio = mIntrinsicSize; intrinsicRatio = AspectRatio::FromSize(mIntrinsicSize);
} else { } else {
// Image doesn't have a (valid) intrinsic size. // Image doesn't have a (valid) intrinsic size.
// Try to look up intrinsic ratio and use that at least. // Try to look up intrinsic ratio and use that at least.

View File

@ -0,0 +1,57 @@
<!doctype html>
<title>Frame width and height attributes as they apply in a vertical writing mode</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#horiz
{
writing-mode: horizontal-tb;
display: inline-block;
}
#vert
{
writing-mode: vertical-rl;
display: inline-block;
}
object
{
border: 1px solid red;
margin: 5px;
}
</style>
<div id="horiz">
<object data="/images/green.png" width=300></object>
<object data="/images/green.png" height=50></object>
</div>
<div id="vert">
<object data="/images/green.png" width=300></object>
<object data="/images/green.png" height=50></object>
</div>
<script>
let t = async_test("Frame width and height attributes as they apply in a vertical writing mode");
function assert_dimensions(obj, expectedX, expectedY) {
assert_equals(getComputedStyle(obj).width, expectedX);
assert_equals(getComputedStyle(obj).height, expectedY);
}
t.step(function() {
var obj = document.createElement('object');
obj.width = 133;
obj.data = '/images/blue.png';
document.getElementById('horiz').appendChild(obj);
obj = document.createElement('object');
obj.width = 133;
obj.data = '/images/blue.png';
document.getElementById('vert').appendChild(obj);
});
onload = t.step_func_done(function() {
let objects = document.querySelectorAll("object");
assert_dimensions(objects[0], '300px', '150px');
assert_dimensions(objects[1], '100px', '50px');
assert_dimensions(objects[2], '133px', '106px');
assert_dimensions(objects[3], '300px', '150px');
assert_dimensions(objects[4], '100px', '50px');
assert_dimensions(objects[5], '133px', '106px');
});
</script>