diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 98a4628dd301..4b842e155d79 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -54,6 +54,7 @@ #include "mozilla/dom/ImageTracker.h" #include "mozilla/dom/PageLoadEventUtils.h" #include "mozilla/dom/ReferrerInfo.h" +#include "mozilla/dom/ResponsiveImageSelector.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/intl/LocaleService.h" #include "mozilla/intl/Locale.h" @@ -1275,6 +1276,66 @@ already_AddRefed nsImageLoadingContent::RecognizeCurrentImageText( return domPromise.forget(); } +CSSIntSize nsImageLoadingContent::NaturalSize() { + if (!mCurrentRequest) { + return {}; + } + + nsCOMPtr image; + mCurrentRequest->GetImage(getter_AddRefs(image)); + if (!image) { + return {}; + } + + mozilla::image::ImageIntrinsicSize intrinsicSize; + nsresult rv = image->GetIntrinsicSize(&intrinsicSize); + if (NS_FAILED(rv)) { + return {}; + } + + CSSIntSize size; // defaults to 0,0 + if (!StaticPrefs::image_natural_size_fallback_enabled()) { + size.width = intrinsicSize.mWidth.valueOr(0); + size.height = intrinsicSize.mHeight.valueOr(0); + } else { + // Fallback case, for web-compatibility! + // See https://github.com/whatwg/html/issues/11287 and bug 1935269. + // If we lack an intrinsic size in either axis, then use the fallback size, + // unless we can transfer the size through the aspect ratio. + // (And if we *only* have an intrinsic aspect ratio, use the fallback width + // and transfer that through the aspect ratio to produce a height.) + size.width = intrinsicSize.mWidth.valueOr(kFallbackIntrinsicWidthInPixels); + size.height = + intrinsicSize.mHeight.valueOr(kFallbackIntrinsicHeightInPixels); + AspectRatio ratio = image->GetIntrinsicRatio(); + if (ratio) { + if (!intrinsicSize.mHeight) { + // Compute the height from the width & ratio. (Note that the width we + // use here might be kFallbackIntrinsicWidthInPixels, and that's fine.) + size.height = ratio.Inverted().ApplyTo(size.width); + } else if (!intrinsicSize.mWidth) { + // Compute the width from the height & ratio. + size.width = ratio.ApplyTo(size.height); + } + } + } + + ImageResolution resolution = image->GetResolution(); + // NOTE(emilio): What we implement here matches the image-set() spec, but it's + // unclear whether this is the right thing to do, see + // https://github.com/whatwg/html/pull/5574#issuecomment-826335244. + if (auto* image = HTMLImageElement::FromNode(AsContent())) { + if (auto* sel = image->GetResponsiveImageSelector()) { + float density = sel->GetSelectedImageDensity(); + MOZ_ASSERT(density >= 0.0); + resolution.ScaleBy(density); + } + } + + resolution.ApplyTo(size.width, size.height); + return size; +} + CSSIntSize nsImageLoadingContent::GetWidthHeightForImage() { Element* element = AsContent()->AsElement(); if (nsIFrame* frame = element->GetPrimaryFrame(FlushType::Layout)) { diff --git a/dom/base/nsImageLoadingContent.h b/dom/base/nsImageLoadingContent.h index 3b090c245682..06e029b78c43 100644 --- a/dom/base/nsImageLoadingContent.h +++ b/dom/base/nsImageLoadingContent.h @@ -239,6 +239,12 @@ class nsImageLoadingContent : public nsIImageLoadingContent { virtual mozilla::dom::FetchPriority GetFetchPriorityForImage() const; + /** + * Get the natural size of the current request, as defined here: + * https://html.spec.whatwg.org/multipage/images.html#preferred-density-corrected-dimensions + */ + mozilla::CSSIntSize NaturalSize(); + /** * Get width and height of the current request, using given image request if * attributes are unset. diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 124aa331de26..06fb2ce1ff5e 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -612,64 +612,6 @@ uint32_t HTMLImageElement::Height() { return GetWidthHeightForImage().height; } uint32_t HTMLImageElement::Width() { return GetWidthHeightForImage().width; } -CSSIntSize HTMLImageElement::NaturalSize() { - if (!mCurrentRequest) { - return {}; - } - - nsCOMPtr image; - mCurrentRequest->GetImage(getter_AddRefs(image)); - if (!image) { - return {}; - } - - mozilla::image::ImageIntrinsicSize intrinsicSize; - nsresult rv = image->GetIntrinsicSize(&intrinsicSize); - if (NS_FAILED(rv)) { - return {}; - } - - CSSIntSize size; // defaults to 0,0 - if (!StaticPrefs::image_natural_size_fallback_enabled()) { - size.width = intrinsicSize.mWidth.valueOr(0); - size.height = intrinsicSize.mHeight.valueOr(0); - } else { - // Fallback case, for web-compatibility! - // See https://github.com/whatwg/html/issues/11287 and bug 1935269. - // If we lack an intrinsic size in either axis, then use the fallback size, - // unless we can transfer the size through the aspect ratio. - // (And if we *only* have an intrinsic aspect ratio, use the fallback width - // and transfer that through the aspect ratio to produce a height.) - size.width = intrinsicSize.mWidth.valueOr(kFallbackIntrinsicWidthInPixels); - size.height = - intrinsicSize.mHeight.valueOr(kFallbackIntrinsicHeightInPixels); - AspectRatio ratio = image->GetIntrinsicRatio(); - if (ratio) { - if (!intrinsicSize.mHeight) { - // Compute the height from the width & ratio. (Note that the width we - // use here might be kFallbackIntrinsicWidthInPixels, and that's fine.) - size.height = ratio.Inverted().ApplyTo(size.width); - } else if (!intrinsicSize.mWidth) { - // Compute the width from the height & ratio. - size.width = ratio.ApplyTo(size.height); - } - } - } - - ImageResolution resolution = image->GetResolution(); - // NOTE(emilio): What we implement here matches the image-set() spec, but it's - // unclear whether this is the right thing to do, see - // https://github.com/whatwg/html/pull/5574#issuecomment-826335244. - if (mResponsiveSelector) { - float density = mResponsiveSelector->GetSelectedImageDensity(); - MOZ_ASSERT(density >= 0.0); - resolution.ScaleBy(density); - } - - resolution.ApplyTo(size.width, size.height); - return size; -} - nsresult HTMLImageElement::CopyInnerTo(HTMLImageElement* aDest) { MOZ_TRY(nsGenericHTMLElement::CopyInnerTo(aDest)); diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index e9d14575d18e..ba94e1ad1efc 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -94,7 +94,6 @@ class HTMLImageElement final : public nsGenericHTMLElement, SetUnsignedIntAttr(nsGkAtoms::height, aHeight, 0, aError); } - CSSIntSize NaturalSize(); uint32_t NaturalHeight() { return NaturalSize().height; } uint32_t NaturalWidth() { return NaturalSize().width; }