Source/WebCore: [CSS Masking] -webkit-mask-repeat: space does not work
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Aug 2013 12:58:10 +0000 (12:58 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 30 Aug 2013 12:58:10 +0000 (12:58 +0000)
Added the space option to background-repeat and -webkit-mask-repeat.
With the property value 'space', the background or mask image gets repeated as often as it fits within the background positioning
area. The repeated images are spaced equally to fill the unused area.
https://bugs.webkit.org/show_bug.cgi?id=119324

Patch by Andrei Parvu <parvu@adobe.com> on 2013-08-30
Reviewed by Dirk Schulze.

Tests: css3/background/background-repeat-space-border.html
       css3/background/background-repeat-space-content.html
       css3/background/background-repeat-space-padding.html
       css3/masking/mask-repeat-space-border.html
       css3/masking/mask-repeat-space-content.html
       css3/masking/mask-repeat-space-padding.html

* platform/graphics/GeneratorGeneratedImage.cpp:
(WebCore::GeneratorGeneratedImage::drawPattern): Passed the space values to the image buffer.
* platform/graphics/Image.cpp:
(WebCore::Image::drawTiled): Added the space values when computing the location of the tile.
* platform/graphics/Image.h: Added the space property.
(WebCore::Image::spaceSize):
(WebCore::Image::setSpaceSize):
* platform/graphics/ImageBuffer.h: Added the space property.
(WebCore::ImageBuffer::spaceSize):
(WebCore::ImageBuffer::setSpaceSize):
* platform/graphics/cg/ImageBufferCG.cpp: Passed the space values when copying an image.
(WebCore::ImageBuffer::copyImage):
* platform/graphics/cg/ImageCG.cpp: Added the space values when creating a platform pattern.
(WebCore::Image::drawPattern):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintFillLayerExtended): Computed the space values on x and y axis.
(WebCore::getSpace):
(WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): Pass the space values to the Image class.
* rendering/RenderBoxModelObject.h: Added the space property.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize):
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize):
* svg/graphics/SVGImage.cpp: Passed the space property to the created image.
(WebCore::SVGImage::drawPatternForContainer):
* svg/graphics/SVGImageForContainer.cpp: Passed the space property to the image property.
(WebCore::SVGImageForContainer::drawPattern):

LayoutTests: [CSS Masking] -webkit-mask-repeat: space does not work
Added tests to verify correct usage of background-repeat: space and mask-repeat: space.
Added one test for each possible mask/background clip: border, padding and content
https://bugs.webkit.org/show_bug.cgi?id=119324

Patch by Andrei Parvu <parvu@adobe.com> on 2013-08-30
Reviewed by Dirk Schulze.

* css3/background/background-repeat-space-border-expected.html: Added.
* css3/background/background-repeat-space-border.html: Added.
* css3/background/background-repeat-space-content-expected.html: Added.
* css3/background/background-repeat-space-content.html: Added.
* css3/background/background-repeat-space-padding-expected.html: Added.
* css3/background/background-repeat-space-padding.html: Added.
* css3/masking/mask-repeat-space-border-expected.html: Added.
* css3/masking/mask-repeat-space-border.html: Added.
* css3/masking/mask-repeat-space-content-expected.html: Added.
* css3/masking/mask-repeat-space-content.html: Added.
* css3/masking/mask-repeat-space-padding-expected.html: Added.
* css3/masking/mask-repeat-space-padding.html: Added.

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

25 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/background/background-repeat-space-border-expected.html [new file with mode: 0644]
LayoutTests/css3/background/background-repeat-space-border.html [new file with mode: 0644]
LayoutTests/css3/background/background-repeat-space-content-expected.html [new file with mode: 0644]
LayoutTests/css3/background/background-repeat-space-content.html [new file with mode: 0644]
LayoutTests/css3/background/background-repeat-space-padding-expected.html [new file with mode: 0644]
LayoutTests/css3/background/background-repeat-space-padding.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-border-expected.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-border.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-content-expected.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-content.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-padding-expected.html [new file with mode: 0644]
LayoutTests/css3/masking/mask-repeat-space-padding.html [new file with mode: 0644]
LayoutTests/css3/masking/resources/circle.svg [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
Source/WebCore/platform/graphics/Image.cpp
Source/WebCore/platform/graphics/Image.h
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
Source/WebCore/platform/graphics/cg/ImageCG.cpp
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderBoxModelObject.h
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImageForContainer.cpp

index 6080bb83bb2e45b2da8d0bca3137d4331bb44ee8..b1abae6f8f460ad8b534c85f582a79b4bdb8fdc5 100644 (file)
@@ -1,3 +1,25 @@
+2013-08-30  Andrei Parvu  <parvu@adobe.com>
+
+        [CSS Masking] -webkit-mask-repeat: space does not work
+        Added tests to verify correct usage of background-repeat: space and mask-repeat: space.
+        Added one test for each possible mask/background clip: border, padding and content
+        https://bugs.webkit.org/show_bug.cgi?id=119324
+
+        Reviewed by Dirk Schulze.
+
+        * css3/background/background-repeat-space-border-expected.html: Added.
+        * css3/background/background-repeat-space-border.html: Added.
+        * css3/background/background-repeat-space-content-expected.html: Added.
+        * css3/background/background-repeat-space-content.html: Added.
+        * css3/background/background-repeat-space-padding-expected.html: Added.
+        * css3/background/background-repeat-space-padding.html: Added.
+        * css3/masking/mask-repeat-space-border-expected.html: Added.
+        * css3/masking/mask-repeat-space-border.html: Added.
+        * css3/masking/mask-repeat-space-content-expected.html: Added.
+        * css3/masking/mask-repeat-space-content.html: Added.
+        * css3/masking/mask-repeat-space-padding-expected.html: Added.
+        * css3/masking/mask-repeat-space-padding.html: Added.
+
 2013-08-30  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r154826.
diff --git a/LayoutTests/css3/background/background-repeat-space-border-expected.html b/LayoutTests/css3/background/background-repeat-space-border-expected.html
new file mode 100644 (file)
index 0000000..e0f3238
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 500px;
+                height: 300px;
+                border: 50px solid transparent;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 151, sizeY = 128, spaceX = 32, spaceY = 58, width = 700, height = 500;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addBackground() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("url(resources/circle.png)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("main");
+
+                div.style.cssText += "background-image: " + urls.join(", ") + ";" +
+                                     "background-size: " + size.join(", ")  + ";" +
+                                     "background-position: " + position.join(", ") + ";" +
+                                     "background-repeat: no-repeat;" +
+                                     "background-origin: border-box;" +
+                                     "background-clip: border-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addBackground()">
+        <div id="main" />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/background/background-repeat-space-border.html b/LayoutTests/css3/background/background-repeat-space-border.html
new file mode 100644 (file)
index 0000000..8ae4704
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 500px;
+                height: 300px;
+                border: 50px solid transparent;
+                padding: 50px;
+                background-image: url("resources/circle.png");
+                background-size: 151px 128px;
+                background-repeat: space;
+                background-origin: border-box;
+                background-clip: border-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/background/background-repeat-space-content-expected.html b/LayoutTests/css3/background/background-repeat-space-content-expected.html
new file mode 100644 (file)
index 0000000..3303442
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 800px;
+                height: 400px;
+                border: 50px solid transparent;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 121, sizeY = 93, spaceX = 15, spaceY = 9, width = 800, height = 400;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addBackground() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("url(resources/circle.png)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("main");
+
+                div.style.cssText += "background-image: " + urls.join(", ") + ";" +
+                                     "background-size: " + size.join(", ")  + ";" +
+                                     "background-position: " + position.join(", ") + ";" +
+                                     "background-repeat: no-repeat;" +
+                                     "background-origin: content-box;" +
+                                     "background-clip: content-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addBackground()">
+        <div id="main" />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/background/background-repeat-space-content.html b/LayoutTests/css3/background/background-repeat-space-content.html
new file mode 100644 (file)
index 0000000..a67fc7b
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 800px;
+                height: 400px;
+                border: 50px solid transparent;
+                padding: 50px;
+                background-image: url("resources/circle.png");
+                background-size: 121px 93px;
+                background-repeat: space space;
+                background-origin: content-box;
+                background-clip: content-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/background/background-repeat-space-padding-expected.html b/LayoutTests/css3/background/background-repeat-space-padding-expected.html
new file mode 100644 (file)
index 0000000..7fd18c3
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 400px;
+                height: 300px;
+                border: 50px solid transparent;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 153, sizeY = 127, spaceX = 21, spaceY = 10, width = 700, height = 600;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addBackground() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("url(resources/circle.png)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("main");
+
+                div.style.cssText += "background-image: " + urls.join(", ") + ";" +
+                                     "background-size: " + size.join(", ")  + ";" +
+                                     "background-position: " + position.join(", ") + ";" +
+                                     "background-repeat: no-repeat;" +
+                                     "background-origin: padding-box;" +
+                                     "background-clip: padding-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addBackground()">
+        <div id="main" />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/background/background-repeat-space-padding.html b/LayoutTests/css3/background/background-repeat-space-padding.html
new file mode 100644 (file)
index 0000000..dafbfb7
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            div {
+                width: 400px;
+                height: 300px;
+                border: 50px solid transparent;
+                padding: 50px;
+                background-image: url("resources/circle.png");
+                background-size: 153px 127px;
+                background-repeat: space;
+                background-origin: padding-box;
+                background-clip: padding-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div />
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-border-expected.html b/LayoutTests/css3/masking/mask-repeat-space-border-expected.html
new file mode 100644 (file)
index 0000000..bf8dd48
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 700px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 500px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 151, sizeY = 128, spaceX = 32, spaceY = 58, width = 700, height = 500;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addMasks() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("linear-gradient(45deg, black, transparent 100%)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("front");
+
+                div.style.cssText += "-webkit-mask-image: " + urls.join(", ") + ";" +
+                                     "-webkit-mask-size: " + size.join(", ")  + ";" +
+                                     "-webkit-mask-position: " + position.join(", ") + ";" +
+                                     "-webkit-mask-repeat: no-repeat;" +
+                                     "-webkit-mask-origin: border-box;" +
+                                     "-webkit-mask-clip: border-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addMasks()">
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-border.html b/LayoutTests/css3/masking/mask-repeat-space-border.html
new file mode 100644 (file)
index 0000000..60caf52
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 700px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 500px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+                -webkit-mask-image: linear-gradient(45deg, black, transparent 100%);
+                -webkit-mask-size: 151px 128px;
+                -webkit-mask-repeat: space;
+                -webkit-mask-origin: border-box;
+                -webkit-mask-clip: border-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-content-expected.html b/LayoutTests/css3/masking/mask-repeat-space-content-expected.html
new file mode 100644 (file)
index 0000000..01c9266
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 500px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 300px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 121, sizeY = 93, spaceX = 58, spaceY = 11, width = 300, height = 300;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addMasks() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("url(resources/circle.svg)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("front");
+
+                div.style.cssText += "-webkit-mask-image: " + urls.join(", ") + ";" +
+                                     "-webkit-mask-size: " + size.join(", ")  + ";" +
+                                     "-webkit-mask-position: " + position.join(", ") + ";" +
+                                     "-webkit-mask-repeat: no-repeat;" +
+                                     "-webkit-mask-origin: content-box;" +
+                                     "-webkit-mask-clip: content-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addMasks()">
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-content.html b/LayoutTests/css3/masking/mask-repeat-space-content.html
new file mode 100644 (file)
index 0000000..486ea17
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 500px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 300px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+                -webkit-mask-image: url("resources/circle.svg");
+                -webkit-mask-size: 121px 93px;
+                -webkit-mask-repeat: space space;
+                -webkit-mask-origin: content-box;
+                -webkit-mask-clip: content-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-padding-expected.html b/LayoutTests/css3/masking/mask-repeat-space-padding-expected.html
new file mode 100644 (file)
index 0000000..4abd454
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 600px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 400px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+            }
+        </style>
+        <script>
+            var sizeX = 153, sizeY = 127, spaceX = 21, spaceY = 10, width = 700, height = 600;
+
+            var urls = Array(), size = Array(), position = Array();
+
+            function addMasks() {
+                for (var x = 0; x < width; x += sizeX + spaceX) {
+                    for (var y = 0; y < height; y += sizeY + spaceY) {
+                        urls.push("url(resources/circle.png)");
+                        size.push(sizeX + "px " + sizeY + "px");
+                        position.push(x + "px " + y + "px");
+                    }
+                }
+
+                div = document.getElementById("front");
+
+                div.style.cssText += "-webkit-mask-image: " + urls.join(", ") + ";" +
+                                     "-webkit-mask-size: " + size.join(", ")  + ";" +
+                                     "-webkit-mask-position: " + position.join(", ") + ";" +
+                                     "-webkit-mask-repeat: no-repeat;" +
+                                     "-webkit-mask-origin: padding-box;" +
+                                     "-webkit-mask-clip: padding-box;";
+           }
+       </script>
+    </head>
+
+    <body onload="addMasks()">
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/mask-repeat-space-padding.html b/LayoutTests/css3/masking/mask-repeat-space-padding.html
new file mode 100644 (file)
index 0000000..6f73919
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <style>
+            #back {
+                width: 600px;
+                height: 500px;
+                background-color: green;
+            }
+            #front {
+                width: 400px;
+                height: 300px;
+                background-color: red;
+                border: 50px solid blue;
+                padding: 50px;
+                -webkit-mask-image: url("resources/circle.png");
+                -webkit-mask-size: 153px 127px;
+                -webkit-mask-repeat: space;
+                -webkit-mask-origin: padding-box;
+                -webkit-mask-clip: padding-box;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div id="back">
+            <div id="front" />
+        </div>
+    </body>
+</html>
+
diff --git a/LayoutTests/css3/masking/resources/circle.svg b/LayoutTests/css3/masking/resources/circle.svg
new file mode 100644 (file)
index 0000000..2e5974f
--- /dev/null
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="360" height="288">
+    <circle cx="180" cy="144" r="80" />
+</svg>
+
index 36d395630b3d5adb2d027291eb14f7ad3ed793ee..1ab10a971ee1661c4ae0d8d2b3fe73507af0ebe1 100644 (file)
@@ -1,3 +1,46 @@
+2013-08-30  Andrei Parvu  <parvu@adobe.com>
+
+        [CSS Masking] -webkit-mask-repeat: space does not work
+        Added the space option to background-repeat and -webkit-mask-repeat.
+        With the property value 'space', the background or mask image gets repeated as often as it fits within the background positioning
+        area. The repeated images are spaced equally to fill the unused area.
+        https://bugs.webkit.org/show_bug.cgi?id=119324
+
+        Reviewed by Dirk Schulze.
+
+        Tests: css3/background/background-repeat-space-border.html
+               css3/background/background-repeat-space-content.html
+               css3/background/background-repeat-space-padding.html
+               css3/masking/mask-repeat-space-border.html
+               css3/masking/mask-repeat-space-content.html
+               css3/masking/mask-repeat-space-padding.html
+
+        * platform/graphics/GeneratorGeneratedImage.cpp:
+        (WebCore::GeneratorGeneratedImage::drawPattern): Passed the space values to the image buffer.
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::drawTiled): Added the space values when computing the location of the tile.
+        * platform/graphics/Image.h: Added the space property.
+        (WebCore::Image::spaceSize):
+        (WebCore::Image::setSpaceSize):
+        * platform/graphics/ImageBuffer.h: Added the space property.
+        (WebCore::ImageBuffer::spaceSize):
+        (WebCore::ImageBuffer::setSpaceSize):
+        * platform/graphics/cg/ImageBufferCG.cpp: Passed the space values when copying an image.
+        (WebCore::ImageBuffer::copyImage):
+        * platform/graphics/cg/ImageCG.cpp: Added the space values when creating a platform pattern.
+        (WebCore::Image::drawPattern):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended): Computed the space values on x and y axis.
+        (WebCore::getSpace):
+        (WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): Pass the space values to the Image class.
+        * rendering/RenderBoxModelObject.h: Added the space property.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize):
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize):
+        * svg/graphics/SVGImage.cpp: Passed the space property to the created image.
+        (WebCore::SVGImage::drawPatternForContainer):
+        * svg/graphics/SVGImageForContainer.cpp: Passed the space property to the image property.
+        (WebCore::SVGImageForContainer::drawPattern):
+
 2013-08-30  Antti Koivisto  <antti@apple.com>
 
         Remove AttachContext
index a7fc565cf0903dc8c56f12f44e5160e2f6aba813..84100a166977b3affde074cf6842fb9ea8fdc69a 100644 (file)
@@ -74,6 +74,7 @@ void GeneratorGeneratedImage::drawPattern(GraphicsContext* destContext, const Fl
         m_cachedAdjustedSize = adjustedSize;
     }
 
+    m_cachedImageBuffer->setSpaceSize(spaceSize());
     // Tile the image buffer into the context.
     m_cachedImageBuffer->drawPattern(destContext, adjustedSrcRect, adjustedPatternCTM, phase, styleColorSpace, compositeOp, destRect);
 }
index 2be0eba3ade77efdaddcb40e0950f3d26c948b6c..8b6efc365759f8d8d0576233f568e5c8d3308b91 100644 (file)
@@ -114,8 +114,9 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
                     scaledTileSize.height() / intrinsicTileSize.height());
 
     FloatRect oneTileRect;
-    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
-    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
+    FloatSize actualTileSize(scaledTileSize.width() + spaceSize().width(), scaledTileSize.height() + spaceSize().height());
+    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
+    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
     oneTileRect.setSize(scaledTileSize);
     
     // Check and see if a single draw of the image can cover the entire area we are supposed to tile.    
@@ -130,9 +131,9 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
     }
 
     AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height());
-    FloatRect tileRect(FloatPoint(), intrinsicTileSize);    
+    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
     drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect, blendMode);
-    
+
     startAnimation();
 }
 
index e706b5c999c7a5746b928f4c75e8511171209adf..768d0e40f55fe65fd3481d3df11b581b1b78cf63 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "Color.h"
 #include "ColorSpace.h"
+#include "FloatSize.h"
 #include "GraphicsTypes.h"
 #include "ImageOrientation.h"
 #include "IntRect.h"
@@ -187,6 +188,11 @@ public:
     virtual bool notSolidColor() { return true; }
 #endif
 
+    FloatSize spaceSize() const { return m_space; }
+    void setSpaceSize(const FloatSize& space)
+    {
+        m_space = space;
+    }
 protected:
     Image(ImageObserver* = 0);
 
@@ -209,6 +215,7 @@ protected:
 private:
     RefPtr<SharedBuffer> m_encodedImageData;
     ImageObserver* m_imageObserver;
+    FloatSize m_space;
 };
 
 }
index dc8c6437ad833210ad11d5a259e404eafcda08af..9f5719226490222ac4664ec89cadb5aaeb9b9ec9 100644 (file)
@@ -128,6 +128,12 @@ namespace WebCore {
         // with textures that are RGB or RGBA format, and UNSIGNED_BYTE type.
         bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool);
 
+        FloatSize spaceSize() const { return m_space; }
+        void setSpaceSize(const FloatSize& space)
+        {
+            m_space = space;
+        }
+
     private:
 #if USE(CG)
         PassNativeImagePtr copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
@@ -152,6 +158,7 @@ namespace WebCore {
         IntSize m_logicalSize;
         float m_resolutionScale;
         OwnPtr<GraphicsContext> m_context;
+        FloatSize m_space;
 
         // This constructor will place its success into the given out-variable
         // so that create() knows when it should return failure.
index 49d9eb42a15a5195d154ab33589809dd90b3431f..4e3acdf1977e060c3b8ad4e238b32b3925f676ab 100644 (file)
@@ -237,7 +237,10 @@ PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh
     if (!image)
         return 0;
 
-    return BitmapImage::create(image.get());
+    RefPtr<BitmapImage> bitmapImage = BitmapImage::create(image.get());
+    bitmapImage->setSpaceSize(spaceSize());
+
+    return bitmapImage.release();
 }
 
 BackingStoreCopy ImageBuffer::fastCopyImageMode()
index a535737786d8e5bd02059a0d8cbc377fad9d429d..69ba2d62be25384a833a9a9f25201faa5052a307 100644 (file)
@@ -73,6 +73,16 @@ static void drawPatternCallback(void* info, CGContextRef context)
     CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))), image);
 }
 
+static void patternReleaseOnMainThreadCallback(void* info)
+{
+    CGImageRelease((CGImageRef)info);
+}
+
+static void patternReleaseCallback(void* info)
+{
+    callOnMainThread(patternReleaseOnMainThreadCallback, info);
+}
+
 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
     const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
 {
@@ -112,42 +122,43 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
 
     // Adjust the color space.
     subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace);
-    
+
     // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
     // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the
     // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
     // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors.  Snow Leopard is ok.
     float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
     float w = CGImageGetWidth(tileImage);
-    if (w == size().width() && h == size().height())
+    if (w == size().width() && h == size().height() && !spaceSize().width() && !spaceSize().height())
         CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get());
     else {
-
-    // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
-    static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
-    CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
-    matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
-    // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
-    matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
-    RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(subImage.get(), CGRectMake(0, 0, tileRect.width(), tileRect.height()),
-                                             matrix, tileRect.width(), tileRect.height(), 
-                                             kCGPatternTilingConstantSpacing, true, &patternCallbacks));
-    if (!pattern)
-        return;
-
-    RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0));
-    
-    CGFloat alpha = 1;
-    RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
-    CGContextSetFillColorSpace(context, patternSpace.get());
-
-    // FIXME: Really want a public API for this.  It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
-    wkSetBaseCTM(context, CGAffineTransformIdentity);
-    CGContextSetPatternPhase(context, CGSizeZero);
-
-    CGContextSetFillColorWithColor(context, color.get());
-    CGContextFillRect(context, CGContextGetClipBoundingBox(context));
-
+        // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
+        static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, patternReleaseCallback };
+        CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
+        matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
+        // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
+        matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
+        CGImageRef platformImage = CGImageRetain(subImage.get());
+        RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(platformImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()), matrix,
+            tileRect.width() + spaceSize().width() * (1 / narrowPrecisionToFloat(patternTransform.a())),
+            tileRect.height() + spaceSize().height() * (1 / narrowPrecisionToFloat(patternTransform.d())),
+            kCGPatternTilingConstantSpacing, true, &patternCallbacks));
+        
+        if (!pattern)
+            return;
+
+        RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0));
+
+        CGFloat alpha = 1;
+        RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
+        CGContextSetFillColorSpace(context, patternSpace.get());
+
+        // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
+        wkSetBaseCTM(context, CGAffineTransformIdentity);
+        CGContextSetPatternPhase(context, CGSizeZero);
+
+        CGContextSetFillColorWithColor(context, color.get());
+        CGContextFillRect(context, CGContextGetClipBoundingBox(context));
     }
 
     stateSaver.restore();
index 9b3b2cf850ac809d69ff9b49761719037e54d71f..c3400b1c0b2f2581834a449b0075dbee96ac7973 100644 (file)
@@ -994,6 +994,8 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
             RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
             RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geometry.tileSize());
             bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), bgLayer, geometry.tileSize());
+            if (image.get())
+                image->setSpaceSize(geometry.spaceSize());
             context->drawTiledImage(image.get(), style()->colorSpace(), geometry.destRect(), geometry.relativePhase(), geometry.tileSize(), 
                 compositeOp, useLowQualityScaling, bgLayer->blendMode());
         }
@@ -1225,6 +1227,17 @@ bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const
 #endif
 }
 
+static inline int getSpace(int areaSize, int tileSize)
+{
+    int numberOfTiles = areaSize / tileSize;
+    int space = 0;
+
+    if (numberOfTiles > 1)
+        space = roundedLayoutUnit((float)(areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1));
+
+    return space;
+}
+
 void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer* fillLayer, const LayoutRect& paintRect,
     BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const
 {
@@ -1314,6 +1327,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerMod
         fillTileSize.setWidth(positioningAreaSize.width() / nrTiles);
         geometry.setTileSize(fillTileSize);
         geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
+        geometry.setSpaceSize(FloatSize());
     }
 
     LayoutUnit computedYPosition = minimumValueForLength(fillLayer->yPosition(), availableHeight, &view(), true);
@@ -1326,20 +1340,37 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerMod
         fillTileSize.setHeight(positioningAreaSize.height() / nrTiles);
         geometry.setTileSize(fillTileSize);
         geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0);
+        geometry.setSpaceSize(FloatSize());
     }
 
-    if (backgroundRepeatX == RepeatFill)
+    if (backgroundRepeatX == RepeatFill) {
         geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
-    else if (backgroundRepeatX == NoRepeatFill) {
+        geometry.setSpaceSize(FloatSize(0, geometry.spaceSize().height()));
+    } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > 0) {
+        int space = getSpace(positioningAreaSize.width(), geometry.tileSize().width());
+        int actualWidth = geometry.tileSize().width() + space;
+
+        geometry.setSpaceSize(FloatSize(space, 0));
+        geometry.setPhaseX(actualWidth ? actualWidth - roundToInt(computedXPosition + left) % actualWidth : 0);
+    } else if (backgroundRepeatX == NoRepeatFill) {
         int xOffset = fillLayer->backgroundXOrigin() == RightEdge ? availableWidth - computedXPosition : computedXPosition;
         geometry.setNoRepeatX(left + xOffset);
+        geometry.setSpaceSize(FloatSize(0, geometry.spaceSize().height()));
     }
 
-    if (backgroundRepeatY == RepeatFill)
+    if (backgroundRepeatY == RepeatFill) {
         geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0);
-    else if (backgroundRepeatY == NoRepeatFill) {
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), 0));
+    } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > 0) {
+        int space = getSpace(positioningAreaSize.height(), geometry.tileSize().height());
+        int actualHeight = geometry.tileSize().height() + space;
+
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), space));
+        geometry.setPhaseY(actualHeight ? actualHeight - roundToInt(computedYPosition + top) % actualHeight : 0);
+    } else if (backgroundRepeatY == NoRepeatFill) {
         int yOffset = fillLayer->backgroundYOrigin() == BottomEdge ? availableHeight - computedYPosition : computedYPosition;
         geometry.setNoRepeatY(top + yOffset);
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), 0));
     }
 
     if (fixedAttachment)
index 9b8e05e1af3a54da5f5bc0049e399491f8159096..d00403b01678bb1ce3ea5299a00a10257b8ff6cf 100644 (file)
@@ -228,7 +228,12 @@ protected:
         {
             m_tileSize = tileSize;
         }
-        
+        FloatSize spaceSize() const { return m_space; }
+        void setSpaceSize(const FloatSize& space)
+        {
+            m_space = space;
+        }
+
         void setPhaseX(int x) { m_phase.setX(x); }
         void setPhaseY(int y) { m_phase.setY(y); }
         
@@ -247,6 +252,7 @@ protected:
         IntPoint m_destOrigin;
         IntPoint m_phase;
         IntSize m_tileSize;
+        FloatSize m_space;
         bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
     };
 
index 1cf6d076960d0a0703c69b3ab4354696dcc18e61..4944e5e3a390dd9e21db8ad713fb865ee5696834 100644 (file)
@@ -201,6 +201,7 @@ void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize
         return;
     drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal);
     RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled);
+    image->setSpaceSize(spaceSize());
 
     // Adjust the source rect and transform due to the image buffer's scaling.
     FloatRect scaledSrcRect = srcRect;
index e9e2728c79640ac1a6214b4150446c6af02302c8..ddf4c68ab1e9e2fd5dc40704cee91351a9e4578e 100644 (file)
@@ -45,6 +45,7 @@ void SVGImageForContainer::draw(GraphicsContext* context, const FloatRect& dstRe
 void SVGImageForContainer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
     const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator compositeOp, const FloatRect& dstRect, BlendMode)
 {
+    m_image->setSpaceSize(spaceSize());
     m_image->drawPatternForContainer(context, m_containerSize, m_zoom, srcRect, patternTransform, phase, colorSpace, compositeOp, dstRect);
 }