Bug 1705877 - image-set() should influence intrinsic size of the image. r=dholbert,layout-reviewers

https://drafts.csswg.org/css-images-4/#image-set-notation has:

> [...] it also specifies the image’s natural resolution, overriding any other
> source of data that might supply a natural resolution.

Astounding that there was literally no WPT for this at all. I added three: one
for backgrounds, one for list-style-image, and one for `content`. Cursor is not
handled on this patch because that one requires a fair amount of extra work.

Differential Revision: https://phabricator.services.mozilla.com/D112474
This commit is contained in:
Emilio Cobos Álvarez 2021-04-19 19:55:27 +00:00
Родитель ca0d2c502e
Коммит 8e47e5abc2
18 изменённых файлов: 237 добавлений и 75 удалений

Просмотреть файл

@ -6322,13 +6322,13 @@ ImgDrawResult nsLayoutUtils::DrawSingleUnscaledImage(
/* static */
ImgDrawResult nsLayoutUtils::DrawSingleImage(
gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
const SamplingFilter aSamplingFilter, const nsRect& aDest,
float aResolution, SamplingFilter aSamplingFilter, const nsRect& aDest,
const nsRect& aDirty, const Maybe<SVGImageContext>& aSVGContext,
uint32_t aImageFlags, const nsPoint* aAnchorPoint,
const nsRect* aSourceArea) {
nscoord appUnitsPerCSSPixel = AppUnitsPerCSSPixel();
CSSIntSize pixelImageSize(
ComputeSizeForDrawingWithFallback(aImage, aDest.Size()));
ComputeSizeForDrawingWithFallback(aImage, aResolution, aDest.Size()));
if (pixelImageSize.width < 1 || pixelImageSize.height < 1) {
NS_ASSERTION(pixelImageSize.width >= 0 && pixelImageSize.height >= 0,
"Image width or height is negative");
@ -6369,7 +6369,8 @@ ImgDrawResult nsLayoutUtils::DrawSingleImage(
/* static */
void nsLayoutUtils::ComputeSizeForDrawing(
imgIContainer* aImage, /* outparam */ CSSIntSize& aImageSize,
imgIContainer* aImage, float aResolution,
/* outparam */ CSSIntSize& aImageSize,
/* outparam */ AspectRatio& aIntrinsicRatio,
/* outparam */ bool& aGotWidth,
/* outparam */ bool& aGotHeight) {
@ -6378,6 +6379,15 @@ void nsLayoutUtils::ComputeSizeForDrawing(
Maybe<AspectRatio> intrinsicRatio = aImage->GetIntrinsicRatio();
aIntrinsicRatio = intrinsicRatio.valueOr(AspectRatio());
if (aResolution != 0.0f && aResolution != 1.0f) {
if (aGotWidth) {
aImageSize.width = std::round(float(aImageSize.width) / aResolution);
}
if (aGotHeight) {
aImageSize.height = std::round(float(aImageSize.height) / aResolution);
}
}
if (!(aGotWidth && aGotHeight) && intrinsicRatio.isNothing()) {
// We hit an error (say, because the image failed to load or couldn't be
// decoded) and should return zero size.
@ -6388,11 +6398,12 @@ void nsLayoutUtils::ComputeSizeForDrawing(
/* static */
CSSIntSize nsLayoutUtils::ComputeSizeForDrawingWithFallback(
imgIContainer* aImage, const nsSize& aFallbackSize) {
imgIContainer* aImage, float aResolution, const nsSize& aFallbackSize) {
CSSIntSize imageSize;
AspectRatio imageRatio;
bool gotHeight, gotWidth;
ComputeSizeForDrawing(aImage, imageSize, imageRatio, gotWidth, gotHeight);
ComputeSizeForDrawing(aImage, aResolution, imageSize, imageRatio, gotWidth,
gotHeight);
// If we didn't get both width and height, try to compute them using the
// intrinsic ratio of the image.

Просмотреть файл

@ -1901,6 +1901,11 @@ class nsLayoutUtils {
* appropriate scale and transform for drawing in
* app units.
* @param aImage The image.
* @param aResolution The resolution specified by the author for the
* image, in dppx. This will affect the intrinsic
* size of the image (so e.g., if resolution is 2,
* and the image is 100x100, the intrinsic size of
* the image will be 50x50).
* @param aDest The area that the image should fill.
* @param aDirty Pixels outside this area may be skipped.
* @param aSVGContext Optionally provides an SVGImageContext.
@ -1922,7 +1927,7 @@ class nsLayoutUtils {
*/
static ImgDrawResult DrawSingleImage(
gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
const SamplingFilter aSamplingFilter, const nsRect& aDest,
float aResolution, SamplingFilter aSamplingFilter, const nsRect& aDest,
const nsRect& aDirty, const mozilla::Maybe<SVGImageContext>& aSVGContext,
uint32_t aImageFlags, const nsPoint* aAnchorPoint = nullptr,
const nsRect* aSourceArea = nullptr);
@ -1943,7 +1948,7 @@ class nsLayoutUtils {
* difference is that this one is simpler and is suited to places where we
* have less information about the frame tree.
*/
static void ComputeSizeForDrawing(imgIContainer* aImage,
static void ComputeSizeForDrawing(imgIContainer* aImage, float aResolution,
CSSIntSize& aImageSize,
AspectRatio& aIntrinsicRatio,
bool& aGotWidth, bool& aGotHeight);
@ -1957,7 +1962,7 @@ class nsLayoutUtils {
* dimensions, the corresponding dimension of aFallbackSize is used instead.
*/
static CSSIntSize ComputeSizeForDrawingWithFallback(
imgIContainer* aImage, const nsSize& aFallbackSize);
imgIContainer* aImage, float aResolution, const nsSize& aFallbackSize);
/**
* Given the image container, frame, and dest rect, determine the best fitting

Просмотреть файл

@ -781,12 +781,9 @@ void nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
if (RefPtr<imgIContainer> image = GetImage()) {
int32_t w = 0;
int32_t h = 0;
image->GetWidth(&w);
image->GetHeight(&h);
LogicalSize size(GetWritingMode(), CSSPixel::ToAppUnits(CSSIntSize(w, h)));
if (Maybe<CSSIntSize> intrinsicSize =
StyleList()->mListStyleImage.GetIntrinsicSize()) {
LogicalSize size(GetWritingMode(), CSSPixel::ToAppUnits(*intrinsicSize));
// auto size the image
finalSize.ISize(wm) = size.ISize(wm);
finalSize.BSize(wm) = size.BSize(wm);

Просмотреть файл

@ -398,11 +398,13 @@ void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
}
MOZ_RELEASE_ASSERT(contentIndex < styleContent->ContentCount());
MOZ_RELEASE_ASSERT(styleContent->ContentAt(contentIndex).IsImage());
auto& imageUrl = styleContent->ContentAt(contentIndex).AsImage();
MOZ_ASSERT(imageUrl.IsImageRequestType(),
const StyleImage& image = styleContent->ContentAt(contentIndex).AsImage();
MOZ_ASSERT(image.IsImageRequestType(),
"Content image should only parse url() type");
auto [finalImage, resolution] = image.FinalImageAndResolution();
Document* doc = PresContext()->Document();
if (imgRequestProxy* proxy = imageUrl.GetImageRequest()) {
if (imgRequestProxy* proxy = finalImage->GetImageRequest()) {
mContentURLRequestResolution = resolution;
proxy->Clone(mListener, doc, getter_AddRefs(mContentURLRequest));
SetupForContentURLRequest();
}
@ -454,6 +456,20 @@ void nsImageFrame::SetupForContentURLRequest() {
}
}
static void ScaleIntrinsicSizeForDensity(IntrinsicSize& aSize,
double aDensity) {
if (aDensity == 1.0) {
return;
}
if (aSize.width) {
aSize.width = Some(NSToCoordRound(double(*aSize.width) / aDensity));
}
if (aSize.height) {
aSize.height = Some(NSToCoordRound(double(*aSize.height) / aDensity));
}
}
static void ScaleIntrinsicSizeForDensity(nsIContent& aContent,
IntrinsicSize& aSize) {
auto* image = HTMLImageElement::FromNode(aContent);
@ -468,16 +484,7 @@ static void ScaleIntrinsicSizeForDensity(nsIContent& aContent,
double density = selector->GetSelectedImageDensity();
MOZ_ASSERT(density >= 0.0);
if (density == 1.0) {
return;
}
if (aSize.width) {
aSize.width = Some(NSToCoordRound(double(*aSize.width) / density));
}
if (aSize.height) {
aSize.height = Some(NSToCoordRound(double(*aSize.height) / density));
}
ScaleIntrinsicSizeForDensity(aSize, density);
}
static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
@ -496,6 +503,9 @@ static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
intrinsicSize.height = size.height == -1 ? Nothing() : Some(size.height);
if (aKind == nsImageFrame::Kind::ImageElement) {
ScaleIntrinsicSizeForDensity(*aFrame.GetContent(), intrinsicSize);
} else {
ScaleIntrinsicSizeForDensity(intrinsicSize,
aFrame.GetContentURLRequestResolution());
}
return intrinsicSize;
}
@ -1476,7 +1486,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedback(gfxContext& aRenderingContext,
nsRect dest(flushRight ? inner.XMost() - size : inner.x, inner.y, size,
size);
result = nsLayoutUtils::DrawSingleImage(
aRenderingContext, PresContext(), imgCon,
aRenderingContext, PresContext(), imgCon, /* aResolution = */ 1.0f,
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, aDirtyRect,
/* no SVGImageContext */ Nothing(), aFlags);
}
@ -2080,8 +2090,10 @@ ImgDrawResult nsImageFrame::PaintImage(gfxContext& aRenderingContext,
Maybe<SVGImageContext> svgContext;
SVGImageContext::MaybeStoreContextPaint(svgContext, this, aImage);
// We've already accounted for resolution via mIntrinsicSize, which influences
// the dest rect, so we don't need to worry about it here..
ImgDrawResult result = nsLayoutUtils::DrawSingleImage(
aRenderingContext, PresContext(), aImage,
aRenderingContext, PresContext(), aImage, /* aResolution = */ 1.0f,
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, aDirtyRect,
svgContext, flags, &anchorPoint);

Просмотреть файл

@ -103,6 +103,12 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
void SetupForContentURLRequest();
bool ShouldShowBrokenImageIcon() const;
// Get the resolution, in dppx, for the image that mContentURLRequest
// represents.
float GetContentURLRequestResolution() const {
return mContentURLRequestResolution;
}
#ifdef ACCESSIBILITY
mozilla::a11y::AccType AccessibleType() override;
#endif
@ -353,6 +359,7 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
// An image request created for content: url(..).
RefPtr<imgRequestProxy> mContentURLRequest;
float mContentURLRequestResolution = 1.0f;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgIContainer> mPrevImage;

Просмотреть файл

@ -50,8 +50,6 @@ nsSize CSSSizeOrRatio::ComputeConcreteSize() const {
nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame, const StyleImage* aImage,
uint32_t aFlags)
: mForFrame(aForFrame),
mImage(&aImage->FinalImage()),
mType(mImage->tag),
mImageContainer(nullptr),
mGradientData(nullptr),
mPaintServerFrame(nullptr),
@ -59,7 +57,12 @@ nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame, const StyleImage* aImage,
mSize(0, 0),
mFlags(aFlags),
mExtendMode(ExtendMode::CLAMP),
mMaskOp(StyleMaskMode::MatchSource) {}
mMaskOp(StyleMaskMode::MatchSource) {
auto pair = aImage->FinalImageAndResolution();
mImage = pair.first;
mType = mImage->tag;
mImageResolution = pair.second;
}
bool nsImageRenderer::PrepareImage() {
if (mImage->IsNone()) {
@ -198,14 +201,14 @@ CSSSizeOrRatio nsImageRenderer::ComputeIntrinsicSize() {
case StyleImage::Tag::Url: {
bool haveWidth, haveHeight;
CSSIntSize imageIntSize;
nsLayoutUtils::ComputeSizeForDrawing(
mImageContainer, imageIntSize, result.mRatio, haveWidth, haveHeight);
nsLayoutUtils::ComputeSizeForDrawing(mImageContainer, mImageResolution,
imageIntSize, result.mRatio,
haveWidth, haveHeight);
if (haveWidth) {
result.SetWidth(nsPresContext::CSSPixelsToAppUnits(imageIntSize.width));
result.SetWidth(CSSPixel::ToAppUnits(imageIntSize.width));
}
if (haveHeight) {
result.SetHeight(
nsPresContext::CSSPixelsToAppUnits(imageIntSize.height));
result.SetHeight(CSSPixel::ToAppUnits(imageIntSize.height));
}
// If we know the aspect ratio and one of the dimensions,
@ -937,8 +940,8 @@ ImgDrawResult nsImageRenderer::DrawBorderImageComponent(
if (!RequiresScaling(aFill, aHFill, aVFill, aUnitSize)) {
ImgDrawResult result = nsLayoutUtils::DrawSingleImage(
aRenderingContext, aPresContext, subImage, samplingFilter, aFill,
aDirtyRect,
aRenderingContext, aPresContext, subImage, mImageResolution,
samplingFilter, aFill, aDirtyRect,
/* no SVGImageContext */ Nothing(), drawFlags);
if (!mImage->IsComplete()) {
@ -1007,8 +1010,9 @@ ImgDrawResult nsImageRenderer::DrawShapeImage(nsPresContext* aPresContext,
// rendered pixel has an alpha that precisely matches the alpha of the
// closest pixel in the image.
return nsLayoutUtils::DrawSingleImage(
aRenderingContext, aPresContext, mImageContainer, SamplingFilter::POINT,
dest, dest, Nothing(), drawFlags, nullptr, nullptr);
aRenderingContext, aPresContext, mImageContainer, mImageResolution,
SamplingFilter::POINT, dest, dest, Nothing(), drawFlags, nullptr,
nullptr);
}
if (mImage->IsGradient()) {

Просмотреть файл

@ -299,6 +299,7 @@ class nsImageRenderer {
nsIFrame* mForFrame;
const mozilla::StyleImage* mImage;
float mImageResolution;
mozilla::StyleImage::Tag mType;
nsCOMPtr<imgIContainer> mImageContainer;
const mozilla::StyleGradient* mGradientData;

Просмотреть файл

@ -15,6 +15,7 @@
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/css/DocumentMatchingFunction.h"
#include "mozilla/css/SheetLoadData.h"
#include "mozilla/dom/Document.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/ComputedTimingFunction.h"
#include "mozilla/PreferenceSheet.h"

Просмотреть файл

@ -942,14 +942,25 @@ inline bool RestyleHint::DefinitelyRecascadesAllSubtree() const {
}
template <>
inline const StyleImage& StyleImage::FinalImage() const {
inline std::pair<const StyleImage*, float> StyleImage::FinalImageAndResolution()
const {
if (!IsImageSet()) {
return *this;
return {this, 1.0f};
}
auto& set = AsImageSet();
return set->items.AsSpan()[set->selected_index].image.FinalImage();
auto& selectedItem = set->items.AsSpan()[set->selected_index];
return {selectedItem.image.FinalImageAndResolution().first,
selectedItem.resolution._0};
}
template <>
inline const StyleImage& StyleImage::FinalImage() const {
return *FinalImageAndResolution().first;
}
template <>
Maybe<CSSIntSize> StyleImage::GetIntrinsicSize() const;
template <>
inline bool StyleImage::IsImageRequestType() const {
auto& finalImage = FinalImage();

Просмотреть файл

@ -1629,6 +1629,31 @@ void StyleImage::ResolveImage(Document& aDoc, const StyleImage* aOld) {
const_cast<StyleComputedImageUrl*>(url)->ResolveImage(aDoc, old);
}
template <>
Maybe<CSSIntSize> StyleImage::GetIntrinsicSize() const {
auto [finalImage, resolution] = FinalImageAndResolution();
imgRequestProxy* request = finalImage->GetImageRequest();
if (!request) {
return Nothing();
}
RefPtr<imgIContainer> image;
request->GetImage(getter_AddRefs(image));
if (!image) {
return Nothing();
}
// FIXME(emilio): Seems like this should be smarter about unspecified width /
// height, aspect ratio, etc, but this preserves the current behavior of our
// only caller for now...
int32_t w = 0, h = 0;
image->GetWidth(&w);
image->GetHeight(&h);
if (resolution != 0.0f && resolution != 1.0f) {
w = std::round(float(w) / resolution);
h = std::round(float(h) / resolution);
}
return Some(CSSIntSize{w, h});
}
// --------------------
// nsStyleImageLayers
//
@ -1882,8 +1907,11 @@ static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
CSSIntSize imageSize;
AspectRatio imageRatio;
bool hasWidth, hasHeight;
nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
hasWidth, hasHeight);
// We could bother getting the right resolution here but it doesn't matter
// since we ignore `imageSize`.
nsLayoutUtils::ComputeSizeForDrawing(imgContainer,
/* aResolution = */ 1.0f, imageSize,
imageRatio, hasWidth, hasHeight);
// If the image has a fixed width and height, rendering never depends on
// the frame size.

Просмотреть файл

@ -405,7 +405,7 @@ void SVGImageFrame::PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
// That method needs our image to have a fixed native width & height,
// and that's not always true for TYPE_VECTOR images.
aImgParams.result &= nsLayoutUtils::DrawSingleImage(
aContext, PresContext(), mImageContainer,
aContext, PresContext(), mImageContainer, /* aResolution = */ 1.0f,
nsLayoutUtils::GetSamplingFilterForFrame(this), destRect,
aDirtyRect ? dirtyRect : destRect, context, flags);
} else { // mImageContainer->GetType() == TYPE_RASTER

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsStyleConsts.h"
#include "nsStyleUtil.h"
#include "nsCOMPtr.h"
#include "nsLayoutUtils.h"
#include "nsPresContext.h"
#include "nsBoxLayoutState.h"
@ -239,6 +240,7 @@ void nsImageBoxFrame::UpdateImage() {
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
mUseSrcAttr = !src.IsEmpty();
if (mUseSrcAttr) {
mImageResolution = 1.0f;
nsContentPolicyType contentPolicyType;
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
uint64_t requestContextID = 0;
@ -267,10 +269,14 @@ void nsImageBoxFrame::UpdateImage() {
doc->ImageTracker()->Add(mImageRequest);
}
}
} else if (auto* styleRequest = GetRequestFromStyle()) {
} else if (auto* styleImage = GetImageFromStyle()) {
auto [finalImage, resolution] = styleImage->FinalImageAndResolution();
mImageResolution = resolution;
if (auto* styleRequest = finalImage->GetImageRequest()) {
styleRequest->SyncClone(mListener, mContent->GetComposedDoc(),
getter_AddRefs(mImageRequest));
}
}
if (!mImageRequest) {
// We have no image, so size to 0
@ -388,7 +394,7 @@ ImgDrawResult nsImageBoxFrame::PaintImage(gfxContext& aRenderingContext,
Maybe<SVGImageContext> svgContext;
SVGImageContext::MaybeStoreContextPaint(svgContext, this, imgCon);
return nsLayoutUtils::DrawSingleImage(
aRenderingContext, PresContext(), imgCon,
aRenderingContext, PresContext(), imgCon, mImageResolution,
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, dirty, svgContext,
aFlags, anchorPoint.ptrOr(nullptr), hasSubRect ? &mSubRect : nullptr);
}
@ -603,8 +609,9 @@ bool nsImageBoxFrame::CanOptimizeToImageLayer() {
return true;
}
imgRequestProxy* nsImageBoxFrame::GetRequestFromStyle() {
const nsStyleDisplay* disp = StyleDisplay();
const mozilla::StyleImage* nsImageBoxFrame::GetImageFromStyle(
const ComputedStyle& aStyle) {
const nsStyleDisplay* disp = aStyle.StyleDisplay();
if (disp->HasAppearance()) {
nsPresContext* pc = PresContext();
if (pc->Theme()->ThemeSupportsWidget(pc, this,
@ -612,7 +619,11 @@ imgRequestProxy* nsImageBoxFrame::GetRequestFromStyle() {
return nullptr;
}
}
return StyleList()->mListStyleImage.GetImageRequest();
auto& image = aStyle.StyleList()->mListStyleImage;
if (!image.IsImageRequestType()) {
return nullptr;
}
return &image;
}
/* virtual */
@ -623,26 +634,18 @@ void nsImageBoxFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
const nsStyleList* myList = StyleList();
mSubRect = myList->GetImageRegion(); // before |mSuppressStyleCheck| test!
if (mUseSrcAttr || mSuppressStyleCheck)
if (mUseSrcAttr || mSuppressStyleCheck) {
return; // No more work required, since the image isn't specified by style.
}
// If the image to use changes, we have a new image.
nsCOMPtr<nsIURI> oldURI, newURI;
if (mImageRequest) {
mImageRequest->GetURI(getter_AddRefs(oldURI));
}
if (auto* newImage = GetRequestFromStyle()) {
newImage->GetURI(getter_AddRefs(newURI));
}
bool equal;
if (newURI == oldURI || // handles null==null
(newURI && oldURI && NS_SUCCEEDED(newURI->Equals(oldURI, &equal)) &&
equal)) {
auto* oldImage = aOldStyle ? GetImageFromStyle(*aOldStyle) : nullptr;
auto* newImage = GetImageFromStyle();
if (newImage == oldImage ||
(newImage && oldImage && *oldImage == *newImage)) {
return;
}
UpdateImage();
} // DidSetComputedStyle
}
void nsImageBoxFrame::GetImageSize() {
if (mIntrinsicSize.width > 0 && mIntrinsicSize.height > 0) {
@ -796,12 +799,16 @@ void nsImageBoxFrame::OnSizeAvailable(imgIRequest* aRequest,
aImage->SetAnimationMode(PresContext()->ImageAnimationMode());
nscoord w, h;
int32_t w = 0, h = 0;
aImage->GetWidth(&w);
aImage->GetHeight(&h);
mIntrinsicSize.SizeTo(nsPresContext::CSSPixelsToAppUnits(w),
nsPresContext::CSSPixelsToAppUnits(h));
if (mImageResolution != 0.0f && mImageResolution != 1.0f) {
w = std::round(w / mImageResolution);
h = std::round(h / mImageResolution);
}
mIntrinsicSize.SizeTo(CSSPixel::ToAppUnits(w), CSSPixel::ToAppUnits(h));
if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
PresShell()->FrameNeedsReflow(this, IntrinsicDirty::StyleChange,

Просмотреть файл

@ -73,11 +73,15 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
#endif
/**
* Gets the image request to be loaded from the current style.
* Gets the image to be loaded from the current style. May be null if themed,
* or if not an url image.
*
* May be null if themed.
* TODO(emilio): Maybe support list-style-image: linear-gradient() etc?
*/
imgRequestProxy* GetRequestFromStyle();
const mozilla::StyleImage* GetImageFromStyle(const ComputedStyle&);
const mozilla::StyleImage* GetImageFromStyle() {
return GetImageFromStyle(*Style());
}
/**
* Update mUseSrcAttr from appropriate content attributes or from
@ -137,6 +141,7 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
nsSize mImageSize;
RefPtr<imgRequestProxy> mImageRequest;
float mImageResolution = 1.0f;
nsCOMPtr<imgINotificationObserver> mListener;
int32_t mLoadFlags;

Просмотреть файл

@ -790,6 +790,17 @@ renaming_overrides_prefixing = true
"GenericImage" = """
public:
// Returns the final image we've selected taken from the image-set, along with
// its resolution, or `this` and `1.0` if this image is not an image-set.
//
// The resolution is in dppx, and should be used to impact the intrinsic size
// of the image.
std::pair<const StyleGenericImage*, float> FinalImageAndResolution() const;
// Returns the intrinsic size of the image, if there's one, accounting for
// resolution as needed.
Maybe<CSSIntSize> GetIntrinsicSize() const;
// If this is an image-set(), the final image we've selected, otherwise it
// returns *this.
const StyleGenericImage& FinalImage() const;

Просмотреть файл

@ -0,0 +1,6 @@
<!doctype html>
<title>CSS Test Reference</title>
<style>
body { margin: 0 }
</style>
<img srcset="/images/green.png 0.5x">

Просмотреть файл

@ -0,0 +1,16 @@
<!doctype html>
<title>Image set resolution affects intrinsic size of the image</title>
<link rel="match" href="image-set-resolution-001-ref.html">
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1705877">
<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation">
<style>
body { margin: 0 }
div {
/* green.png is 100x50, should be 200x100 instead */
content: -webkit-image-set(url('/images/green.png') 0.5x);
content: image-set(url('/images/green.png') 0.5x);
}
</style>
<div></div>

Просмотреть файл

@ -0,0 +1,20 @@
<!doctype html>
<title>Image set resolution affects intrinsic size of the image</title>
<link rel="match" href="image-set-resolution-001-ref.html">
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1705877">
<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation">
<style>
body { margin: 0 }
div {
/* green.png is 100x50, should be 200x100 instead */
background-image: -webkit-image-set(url('/images/green.png') 0.5x);
background-image: image-set(url('/images/green.png') 0.5x);
background-repeat: no-repeat;
background-origin: 0 0;
width: 100vw;
height: 100vh;
}
</style>
<div></div>

Просмотреть файл

@ -0,0 +1,20 @@
<!doctype html>
<title>Image set resolution affects intrinsic size of the image</title>
<link rel="match" href="image-set-resolution-001-ref.html">
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1705877">
<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation">
<style>
body { margin: 0 }
ul, li { margin: 0; padding: 0 }
li {
list-style-position: inside;
/* green.png is 100x50, should be 200x100 instead */
list-style-image: -webkit-image-set(url('/images/green.png') 0.5x);
list-style-image: image-set(url('/images/green.png') 0.5x);
}
</style>
<ul>
<li></li>
</ul>