Background images can incorrectly repeat with sub-pixel layout
authorleviw@chromium.org <leviw@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Oct 2012 17:18:12 +0000 (17:18 +0000)
committerleviw@chromium.org <leviw@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Oct 2012 17:18:12 +0000 (17:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=94622

Reviewed by Emil A Eklund.

Source/WebCore:

Attempting to better match author expectations when painting tiled background images. When under
the effects of zoom with sub-pixel layout enabled, the drawn size of a rendered element can
differ depending on its location. This change looks at the size of the scaled tiled background
image size, and either ceils or floors that value depending on if tiling that value will
result in us being one pixel or less short of covering the background size. This is a heuristic,
as sub-pixel/zooming isn't specced.

Test: fast/sub-pixel/scaled-background-image.html

* rendering/RenderBoxModelObject.cpp:
(WebCore::applySubPixelHeuristicForTileSize):
(WebCore):
(WebCore::RenderBoxModelObject::calculateFillTileSize):

LayoutTests:

* fast/sub-pixel/scaled-background-image-expected.html: Added.
* fast/sub-pixel/scaled-background-image.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@132731 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/sub-pixel/scaled-background-image-expected.html [new file with mode: 0644]
LayoutTests/fast/sub-pixel/scaled-background-image.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBoxModelObject.cpp

index c46f44b..58883ef 100644 (file)
@@ -1,3 +1,13 @@
+2012-10-27  Levi Weintraub  <leviw@chromium.org>
+
+        Background images can incorrectly repeat with sub-pixel layout
+        https://bugs.webkit.org/show_bug.cgi?id=94622
+
+        Reviewed by Emil A Eklund.
+
+        * fast/sub-pixel/scaled-background-image-expected.html: Added.
+        * fast/sub-pixel/scaled-background-image.html: Added.
+
 2012-10-26  Balazs Kelemen  <kbalazs@webkit.org>
 
         [Qt] Pixel tests need rebaseline
diff --git a/LayoutTests/fast/sub-pixel/scaled-background-image-expected.html b/LayoutTests/fast/sub-pixel/scaled-background-image-expected.html
new file mode 100644 (file)
index 0000000..bb95f16
--- /dev/null
@@ -0,0 +1,18 @@
+<html>
+<head>
+<style type="text/css">
+.norepeat {
+    background: url(../images/resources/exif-orientation-7-rl.jpg);
+       border: 5px solid black;
+       margin: 5px;
+       background-size: 124px 63px;
+       width: 124px;
+    height: 63px;
+}
+</style>
+<body>
+<div class="norepeat"></div>
+<p>This tests that we don't tile background images that are sufficiently close to the renderer size. The background image
+above should not repeat. See <a href="https://bugs.webkit.org/show_bug.cgi?id=94622">bug 94622</a>.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/sub-pixel/scaled-background-image.html b/LayoutTests/fast/sub-pixel/scaled-background-image.html
new file mode 100644 (file)
index 0000000..5e3fc65
--- /dev/null
@@ -0,0 +1,19 @@
+<html>
+<head>
+<style type="text/css">
+.norepeat {
+    background: url(../images/resources/exif-orientation-7-rl.jpg);
+       zoom: 1.25;
+       background-size: 99px 50px;
+       border: 4px solid black;
+       margin: 4px;
+       width: 99px;
+    height: 50px;
+}
+</style>
+<body>
+<div class="norepeat"></div>
+<p>This tests that we don't tile background images that are sufficiently close to the renderer size. The background image
+above should not repeat. See <a href="https://bugs.webkit.org/show_bug.cgi?id=94622">bug 94622</a>.</p>
+</body>
+</html>
index 03bb64b..0511933 100644 (file)
@@ -1,3 +1,24 @@
+2012-10-27  Levi Weintraub  <leviw@chromium.org>
+
+        Background images can incorrectly repeat with sub-pixel layout
+        https://bugs.webkit.org/show_bug.cgi?id=94622
+
+        Reviewed by Emil A Eklund.
+
+        Attempting to better match author expectations when painting tiled background images. When under
+        the effects of zoom with sub-pixel layout enabled, the drawn size of a rendered element can
+        differ depending on its location. This change looks at the size of the scaled tiled background
+        image size, and either ceils or floors that value depending on if tiling that value will
+        result in us being one pixel or less short of covering the background size. This is a heuristic,
+        as sub-pixel/zooming isn't specced.
+
+        Test: fast/sub-pixel/scaled-background-image.html
+
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::applySubPixelHeuristicForTileSize):
+        (WebCore):
+        (WebCore::RenderBoxModelObject::calculateFillTileSize):
+
 2012-10-27  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r132725.
index fd6390a..3ee8827 100644 (file)
@@ -1046,6 +1046,12 @@ IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* imag
     return positioningAreaSize;
 }
 
+static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize)
+{
+    tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tileSize.width().ceil() : tileSize.width().floor());
+    tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? tileSize.height().ceil() : tileSize.height().floor());
+}
+
 IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, const IntSize& positioningAreaSize) const
 {
     StyleImage* image = fillLayer->image();
@@ -1056,37 +1062,38 @@ IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer,
     RenderView* renderView = view();
     switch (type) {
         case SizeLength: {
-            int w = positioningAreaSize.width();
-            int h = positioningAreaSize.height();
+            LayoutSize tileSize = positioningAreaSize;
 
             Length layerWidth = fillLayer->size().size.width();
             Length layerHeight = fillLayer->size().size.height();
 
             if (layerWidth.isFixed())
-                w = layerWidth.value();
+                tileSize.setWidth(layerWidth.value());
             else if (layerWidth.isPercent() || layerHeight.isViewportPercentage())
-                w = valueForLength(layerWidth, positioningAreaSize.width(), renderView);
+                tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.width(), renderView));
             
             if (layerHeight.isFixed())
-                h = layerHeight.value();
+                tileSize.setHeight(layerHeight.value());
             else if (layerHeight.isPercent() || layerHeight.isViewportPercentage())
-                h = valueForLength(layerHeight, positioningAreaSize.height(), renderView);
-            
+                tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.height(), renderView));
+
+            applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize);
+
             // If one of the values is auto we have to use the appropriate
             // scale to maintain our aspect ratio.
             if (layerWidth.isAuto() && !layerHeight.isAuto()) {
                 if (imageIntrinsicSize.height())
-                    w = imageIntrinsicSize.width() * h / imageIntrinsicSize.height();        
+                    tileSize.setWidth(imageIntrinsicSize.width() * tileSize.height() / imageIntrinsicSize.height());
             } else if (!layerWidth.isAuto() && layerHeight.isAuto()) {
                 if (imageIntrinsicSize.width())
-                    h = imageIntrinsicSize.height() * w / 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.
-                w = imageIntrinsicSize.width();
-                h = imageIntrinsicSize.height();
+                tileSize = imageIntrinsicSize;
             }
             
-            return IntSize(max(0, w), max(0, h));
+            tileSize.clampNegativeToZero();
+            return flooredIntSize(tileSize);
         }
         case SizeNone: {
             // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any.