summaryrefslogtreecommitdiff
path: root/layout/base/nsCSSRendering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/nsCSSRendering.cpp')
-rw-r--r--layout/base/nsCSSRendering.cpp78
1 files changed, 46 insertions, 32 deletions
diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
index 9a827546f..e6e3b5f6f 100644
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -3546,10 +3546,10 @@ ComputeDrawnSizeForBackground(const CSSSizeOrRatio& aIntrinsicSize,
imageSize.width = ComputeRoundedSize(imageSize.width, aBgPositioningArea.width);
if (!isRepeatRoundInBothDimensions &&
aLayerSize.mHeightType == nsStyleImageLayers::Size::DimensionType::eAuto) {
- // Restore intrinsic rato
- if (aIntrinsicSize.mRatio.width) {
- float scale = float(aIntrinsicSize.mRatio.height) / aIntrinsicSize.mRatio.width;
- imageSize.height = NSCoordSaturatingNonnegativeMultiply(imageSize.width, scale);
+ // Restore intrinsic ratio
+ if (aIntrinsicSize.mRatio) {
+ imageSize.height =
+ aIntrinsicSize.mRatio.Inverted().ApplyTo(imageSize.width);
}
}
}
@@ -3560,10 +3560,9 @@ ComputeDrawnSizeForBackground(const CSSSizeOrRatio& aIntrinsicSize,
imageSize.height = ComputeRoundedSize(imageSize.height, aBgPositioningArea.height);
if (!isRepeatRoundInBothDimensions &&
aLayerSize.mWidthType == nsStyleImageLayers::Size::DimensionType::eAuto) {
- // Restore intrinsic rato
- if (aIntrinsicSize.mRatio.height) {
- float scale = float(aIntrinsicSize.mRatio.width) / aIntrinsicSize.mRatio.height;
- imageSize.width = NSCoordSaturatingNonnegativeMultiply(imageSize.height, scale);
+ // Restore intrinsic ratio
+ if (aIntrinsicSize.mRatio) {
+ imageSize.width = aIntrinsicSize.mRatio.ApplyTo(imageSize.height);
}
}
}
@@ -5264,17 +5263,11 @@ CSSSizeOrRatio::ComputeConcreteSize() const
return nsSize(mWidth, mHeight);
}
if (mHasWidth) {
- nscoord height = NSCoordSaturatingNonnegativeMultiply(
- mWidth,
- double(mRatio.height) / mRatio.width);
- return nsSize(mWidth, height);
+ return nsSize(mWidth, mRatio.Inverted().ApplyTo(mWidth));
}
MOZ_ASSERT(mHasHeight);
- nscoord width = NSCoordSaturatingNonnegativeMultiply(
- mHeight,
- double(mRatio.width) / mRatio.height);
- return nsSize(width, mHeight);
+ return nsSize(mRatio.ApplyTo(mHeight), mHeight);
}
CSSSizeOrRatio
@@ -5379,9 +5372,7 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
if (aSpecifiedSize.mHasWidth) {
nscoord height;
if (aIntrinsicSize.HasRatio()) {
- height = NSCoordSaturatingNonnegativeMultiply(
- aSpecifiedSize.mWidth,
- double(aIntrinsicSize.mRatio.height) / aIntrinsicSize.mRatio.width);
+ height = aIntrinsicSize.mRatio.Inverted().ApplyTo(aSpecifiedSize.mWidth);
} else if (aIntrinsicSize.mHasHeight) {
height = aIntrinsicSize.mHeight;
} else {
@@ -5393,9 +5384,7 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
MOZ_ASSERT(aSpecifiedSize.mHasHeight);
nscoord width;
if (aIntrinsicSize.HasRatio()) {
- width = NSCoordSaturatingNonnegativeMultiply(
- aSpecifiedSize.mHeight,
- double(aIntrinsicSize.mRatio.width) / aIntrinsicSize.mRatio.height);
+ width = aIntrinsicSize.mRatio.ApplyTo(aSpecifiedSize.mHeight);
} else if (aIntrinsicSize.mHasWidth) {
width = aIntrinsicSize.mWidth;
} else {
@@ -5406,32 +5395,57 @@ nsImageRenderer::ComputeConcreteSize(const CSSSizeOrRatio& aSpecifiedSize,
/* static */ nsSize
nsImageRenderer::ComputeConstrainedSize(const nsSize& aConstrainingSize,
- const nsSize& aIntrinsicRatio,
+ const AspectRatio& aIntrinsicRatio,
FitType aFitType)
{
- if (aIntrinsicRatio.width <= 0 && aIntrinsicRatio.height <= 0) {
+ if (!aIntrinsicRatio) {
return aConstrainingSize;
}
- float scaleX = double(aConstrainingSize.width) / aIntrinsicRatio.width;
- float scaleY = double(aConstrainingSize.height) / aIntrinsicRatio.height;
+ // Suppose we're doing a "contain" fit. If the image's aspect ratio has a
+ // "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;
- if ((aFitType == CONTAIN) == (scaleX < scaleY)) {
+ if ((aFitType == CONTAIN) == (constraintWidth < hypotheticalWidth)) {
size.width = aConstrainingSize.width;
- size.height = NSCoordSaturatingNonnegativeMultiply(
- aIntrinsicRatio.height, scaleX);
+ size.height = aIntrinsicRatio.Inverted().ApplyTo(aConstrainingSize.width);
// If we're reducing the size by less than one css pixel, then just use the
// constraining size.
if (aFitType == CONTAIN && aConstrainingSize.height - size.height < nsPresContext::AppUnitsPerCSSPixel()) {
size.height = aConstrainingSize.height;
}
} else {
- size.width = NSCoordSaturatingNonnegativeMultiply(
- aIntrinsicRatio.width, scaleY);
+ size.height = aConstrainingSize.height;
+ size.width = aIntrinsicRatio.ApplyTo(aConstrainingSize.height);
if (aFitType == CONTAIN && aConstrainingSize.width - size.width < nsPresContext::AppUnitsPerCSSPixel()) {
size.width = aConstrainingSize.width;
}
- size.height = aConstrainingSize.height;
}
return size;
}