From 5d4df42dc706daaf1dabb8613cc7f0419221c7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 16 May 2018 19:39:16 +0200 Subject: [PATCH] Bug 1149357: Make nsImageFrame::mIntrinsicSize account for density. r=dholbert Only doing it in ComputeSize (via GetNaturalSize) is unsound, and the rest of the users of mIntrinsicSize definitely do need scaling accounted for. Move the adjustment to nsImageFrame for two reasons: * Prevents adding more dependencies from nsIImageLoadingContent, which otherwise would need to go away anyway in bug 215083. * Avoids having to duplicate the image orientation logic, since mImage is already an OrientedImage if needed. MozReview-Commit-ID: EA0n0TctZhN --- dom/html/HTMLImageElement.h | 5 ++ layout/generic/nsImageFrame.cpp | 70 ++++++++----------- .../image/image-srcset-isize-ref.html | 25 +++++++ layout/reftests/image/image-srcset-isize.html | 41 +++++++++++ layout/reftests/image/reftest.list | 1 + 5 files changed, 103 insertions(+), 39 deletions(-) create mode 100644 layout/reftests/image/image-srcset-isize-ref.html create mode 100644 layout/reftests/image/image-srcset-isize.html diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index f1251f920057..1f1a8be3081f 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -43,6 +43,11 @@ public: virtual bool Draggable() const override; + ResponsiveImageSelector* GetResponsiveImageSelector() + { + return mResponsiveSelector.get(); + } + // Element virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 18ee3f3eacc3..9b0930d8cc8b 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -18,6 +18,8 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Helpers.h" #include "mozilla/gfx/PathHelpers.h" +#include "mozilla/dom/HTMLImageElement.h" +#include "mozilla/dom/ResponsiveImageSelector.h" #include "mozilla/layers/WebRenderLayerManager.h" #include "mozilla/MouseEvents.h" #include "mozilla/Unused.h" @@ -294,6 +296,33 @@ nsImageFrame::Init(nsIContent* aContent, } } +static void +ScaleIntrinsicSizeForDensity(nsIContent& aContent, nsSize& aSize) +{ + auto* image = HTMLImageElement::FromNode(aContent); + if (!image) { + return; + } + + ResponsiveImageSelector* selector = image->GetResponsiveImageSelector(); + if (!selector) { + return; + } + + double density = selector->GetSelectedImageDensity(); + MOZ_ASSERT(density > 0.0); + if (density == 1.0) { + return; + } + + if (aSize.width != -1) { + aSize.width = NSToCoordRound(double(aSize.width) / density); + } + if (aSize.height != -1) { + aSize.height = NSToCoordRound(double(aSize.height) / density); + } +} + bool nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage) { @@ -307,6 +336,7 @@ nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage) // Set intrinsic size to match aImage's reported intrinsic width & height. nsSize intrinsicSize; if (NS_SUCCEEDED(aImage->GetIntrinsicSize(&intrinsicSize))) { + ScaleIntrinsicSizeForDensity(*mContent, intrinsicSize); // If the image has no intrinsic width, intrinsicSize.width will be -1, and // we can leave mIntrinsicSize.width at its default value of eStyleUnit_None. // Otherwise we use intrinsicSize.width. Height works the same way. @@ -859,46 +889,8 @@ nsImageFrame::ComputeSize(gfxContext *aRenderingContext, ComputeSizeFlags aFlags) { EnsureIntrinsicSizeAndRatio(); - - nsCOMPtr imageLoader = do_QueryInterface(mContent); - NS_ASSERTION(imageLoader, "No content node??"); - mozilla::IntrinsicSize intrinsicSize(mIntrinsicSize); - - // XXX(seth): We may sometimes find ourselves in the situation where we have - // mImage, but imageLoader's current request does not have a size yet. - // This can happen when we load an image speculatively from cache, it fails - // to validate, and the new image load hasn't fired SIZE_AVAILABLE yet. In - // this situation we should always use mIntrinsicSize, because - // GetNaturalWidth/Height will return 0, so we check CurrentRequestHasSize() - // below. See bug 1019840. We will fix this in bug 1141395. - - // Content may override our default dimensions. This is termed as overriding - // the intrinsic size by the spec, but all other consumers of mIntrinsic* - // values are being used to refer to the real/true size of the image data. - if (imageLoader && imageLoader->CurrentRequestHasSize() && mImage && - intrinsicSize.width.GetUnit() == eStyleUnit_Coord && - intrinsicSize.height.GetUnit() == eStyleUnit_Coord) { - uint32_t width; - uint32_t height; - if (NS_SUCCEEDED(imageLoader->GetNaturalWidth(&width)) && - NS_SUCCEEDED(imageLoader->GetNaturalHeight(&height))) { - nscoord appWidth = nsPresContext::CSSPixelsToAppUnits((int32_t)width); - nscoord appHeight = nsPresContext::CSSPixelsToAppUnits((int32_t)height); - // If this image is rotated, we'll need to transpose the natural - // width/height. - bool coordFlip; - if (StyleVisibility()->mImageOrientation.IsFromImage()) { - coordFlip = mImage->GetOrientation().SwapsWidthAndHeight(); - } else { - coordFlip = StyleVisibility()->mImageOrientation.SwapsWidthAndHeight(); - } - intrinsicSize.width.SetCoordValue(coordFlip ? appHeight : appWidth); - intrinsicSize.height.SetCoordValue(coordFlip ? appWidth : appHeight); - } - } - return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM, - intrinsicSize, mIntrinsicRatio, + mIntrinsicSize, mIntrinsicRatio, aCBSize, aMargin, aBorder, aPadding, aFlags); } diff --git a/layout/reftests/image/image-srcset-isize-ref.html b/layout/reftests/image/image-srcset-isize-ref.html new file mode 100644 index 000000000000..8dd146f4805e --- /dev/null +++ b/layout/reftests/image/image-srcset-isize-ref.html @@ -0,0 +1,25 @@ + + +CSS Test Reference + + +
+
+ +
+
+ Should see me right by the side of the image. +
+
+ diff --git a/layout/reftests/image/image-srcset-isize.html b/layout/reftests/image/image-srcset-isize.html new file mode 100644 index 000000000000..2189c2bee996 --- /dev/null +++ b/layout/reftests/image/image-srcset-isize.html @@ -0,0 +1,41 @@ + + +CSS Test: srcset intrinsic size isn't confused + + + + +
+
+ +
+
+ Should see me right by the side of the image. +
+
+ diff --git a/layout/reftests/image/reftest.list b/layout/reftests/image/reftest.list index d7b7344b9efa..812fc8aecdae 100644 --- a/layout/reftests/image/reftest.list +++ b/layout/reftests/image/reftest.list @@ -118,6 +118,7 @@ fuzzy(1,1) == image-orientation-background.html?90&flip image-orientation-r == image-srcset-default-1x.html image-srcset-default-1x-ref.html == image-srcset-default-src-2x.html image-srcset-default-src-2x-ref.html == image-srcset-default-src-1x.html image-srcset-default-src-1x-ref.html +== image-srcset-isize.html image-srcset-isize-ref.html == image-srcset-orientation-2x.html image-srcset-orientation-2x-ref.html == image-srcset-orientation-1x.html image-srcset-orientation-1x-ref.html == image-srcset-svg-3x.html image-srcset-svg-3x-ref.html