Skip to content
Permalink
Browse files
Don't apply aspect ratio scaling to gradient background images that d…
…on't have a natural aspect ratio

https://bugs.webkit.org/show_bug.cgi?id=247298
<rdar://101661731>

Reviewed by Simon Fraser.

If we use a gradient as a background image, and set one of the background size dimension to auto, we currently scale that dimension by the same amount as the other axis to preserve the aspect ratio.

Gradients have no natural dimensions (and thus no natural aspect ratio) - https://w3c.github.io/csswg-drafts/css-images/#gradients.

Background sizing should fall back to using 100% (for the case where we have one size, and auto), if there's no natural aspect ratio or dimensions - https://w3c.github.io/csswg-drafts/css-backgrounds/#background-size

* LayoutTests/TestExpectations:
* Source/WebCore/display/css/DisplayFillLayerImageGeometry.cpp:
(WebCore::Display::calculateImageIntrinsicDimensions):
(WebCore::Display::calculateFillTileSize):
* Source/WebCore/rendering/BackgroundPainter.cpp:
(WebCore::BackgroundPainter::calculateFillTileSize):
* Source/WebCore/rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::calculateImageIntrinsicDimensions const):
* Source/WebCore/rendering/style/StyleGeneratedImage.h:
* Source/WebCore/rendering/style/StyleImage.h:
(WebCore::StyleImage::imageHasNaturalDimensions const):

Canonical link: https://commits.webkit.org/256256@main
  • Loading branch information
mattwoodrow committed Nov 2, 2022
1 parent 809586a commit 759576401a3d3175f5f17ea8756f36423b147a51
Show file tree
Hide file tree
Showing 8 changed files with 13 additions and 11 deletions.
@@ -4162,8 +4162,6 @@ webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/css-bord
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/first-letter-space-not-selected.html [ ImageOnlyFailure ]

webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-attachment-fixed-inside-transform-1.html [ ImageOnlyFailure ]
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-size-041.html [ ImageOnlyFailure ]
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-size-042.html [ ImageOnlyFailure ]
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-size-043.html [ ImageOnlyFailure ]
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-size-044.html [ ImageOnlyFailure ]
webkit.org/b/206753 imported/w3c/web-platform-tests/css/css-backgrounds/background-size-percentage-root.html [ ImageOnlyFailure Pass ]
@@ -15,7 +15,7 @@
padding: 50px;
-webkit-mask-image: linear-gradient(45deg, black, transparent 100%);
-webkit-mask-source-type: alpha;
-webkit-mask-size: 200px auto;
-webkit-mask-size: 200px 200px;
-webkit-mask-repeat: repeat;
-webkit-mask-origin: border-box;
-webkit-mask-clip: border-box;
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=191000-212333" />
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=191000-212750" />
<style>
#back {
width: 1000px;
@@ -16,7 +16,7 @@
padding: 50px;
-webkit-mask-image: linear-gradient(45deg, white, black);
-webkit-mask-source-type: luminance;
-webkit-mask-size: 200px auto;
-webkit-mask-size: 200px 200px;
-webkit-mask-repeat: repeat;
-webkit-mask-origin: border-box;
-webkit-mask-clip: border-box;
@@ -91,7 +91,7 @@ static inline LayoutSize resolveAgainstIntrinsicRatio(LayoutSize size, const Lay
static LayoutSize calculateImageIntrinsicDimensions(StyleImage* image, LayoutSize positioningAreaSize)
{
// A generated image without a fixed size, will always return the container size as intrinsic size.
if (image->isGeneratedImage() && image->usesImageContainerSize())
if (!image->imageHasNaturalDimensions())
return LayoutSize(positioningAreaSize.width(), positioningAreaSize.height());

// FIXME: Call computeIntrinsicDimensions().
@@ -168,11 +168,12 @@ static LayoutSize calculateFillTileSize(const FillLayer& fillLayer, LayoutSize p

// If one of the values is auto we have to use the appropriate
// scale to maintain our aspect ratio.
bool hasNaturalAspectRatio = image && image->imageHasNaturalDimensions();
if (layerWidth.isAuto() && !layerHeight.isAuto()) {
if (imageIntrinsicSize.height())
if (hasNaturalAspectRatio && imageIntrinsicSize.height())
tileSize.setWidth(imageIntrinsicSize.width() * tileSize.height() / imageIntrinsicSize.height());
} else if (!layerWidth.isAuto() && layerHeight.isAuto()) {
if (imageIntrinsicSize.width())
if (hasNaturalAspectRatio && imageIntrinsicSize.width())
tileSize.setHeight(imageIntrinsicSize.height() * tileSize.width() / imageIntrinsicSize.width());
} else if (layerWidth.isAuto() && layerHeight.isAuto()) {
// If both width and height are auto, use the image's intrinsic size.
@@ -723,11 +723,12 @@ LayoutSize BackgroundPainter::calculateFillTileSize(const RenderBoxModelObject&

// If one of the values is auto we have to use the appropriate
// scale to maintain our aspect ratio.
bool hasNaturalAspectRatio = image && image->imageHasNaturalDimensions();
if (layerWidth.isAuto() && !layerHeight.isAuto()) {
if (imageIntrinsicSize.height())
if (hasNaturalAspectRatio && imageIntrinsicSize.height())
tileSize.setWidth(imageIntrinsicSize.width() * tileSize.height() / imageIntrinsicSize.height());
} else if (!layerWidth.isAuto() && layerHeight.isAuto()) {
if (imageIntrinsicSize.width())
if (hasNaturalAspectRatio && imageIntrinsicSize.width())
tileSize.setHeight(imageIntrinsicSize.height() * tileSize.width() / imageIntrinsicSize.width());
} else if (layerWidth.isAuto() && layerHeight.isAuto()) {
// If both width and height are auto, use the image's intrinsic size.
@@ -711,7 +711,7 @@ static inline LayoutSize resolveAgainstIntrinsicRatio(const LayoutSize& size, co
LayoutSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const LayoutSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const
{
// A generated image without a fixed size, will always return the container size as intrinsic size.
if (image->isGeneratedImage() && image->usesImageContainerSize())
if (!image->imageHasNaturalDimensions())
return LayoutSize(positioningAreaSize.width(), positioningAreaSize.height());

Length intrinsicWidth;
@@ -56,6 +56,7 @@ class StyleGeneratedImage : public StyleImage {
bool imageHasRelativeHeight() const final { return !m_fixedSize; }
bool usesImageContainerSize() const final { return !m_fixedSize; }
void setContainerContextForRenderer(const RenderElement&, const FloatSize& containerSize, float) final { m_containerSize = containerSize; }
bool imageHasNaturalDimensions() const final { return !usesImageContainerSize(); }

void addClient(RenderElement&) final;
void removeClient(RenderElement&) final;
@@ -74,6 +74,7 @@ class StyleImage : public RefCounted<StyleImage> {
virtual bool imageHasRelativeWidth() const = 0;
virtual bool imageHasRelativeHeight() const = 0;
virtual float imageScaleFactor() const { return 1; }
virtual bool imageHasNaturalDimensions() const { return true; }

// Image.
virtual RefPtr<Image> image(const RenderElement*, const FloatSize&) const = 0;

0 comments on commit 7595764

Please sign in to comment.