'round' not implemented in border-image
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Feb 2013 01:46:14 +0000 (01:46 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Feb 2013 01:46:14 +0000 (01:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=14185

Patch by Uday Kiran <udaykiran@motorola.com> on 2013-02-19
Reviewed by David Hyatt.

Source/WebCore:

Add rendering support for 'round' keyword of border-image-repeat CSS property
http://dev.w3.org/csswg/css3-background/#border-image-repeat
Rebased original patch by Benjamin Otte <otte@gnome.org> and made few fixes.

Test: fast/borders/border-image-02.html

* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::drawTiledImage):
* platform/graphics/GraphicsContext.h:
(GraphicsContext):
* platform/graphics/Image.cpp:
(WebCore::Image::drawTiled):
* platform/graphics/Image.h:
(Image):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintNinePieceImage): For 'round' keyword,
the image is tiled (repeated) to fill the area. If it does not fill the area
with a whole number of tiles, the image is rescaled so that it does.

LayoutTests:

Added test for 'round' keyword of border-image-repeat CSS property
http://dev.w3.org/csswg/css3-background/#border-image-repeat

* fast/borders/border-image-02.html: Added.
* platform/chromium-linux/fast/borders/border-image-02-expected.png: Added.
* platform/chromium/TestExpectations:
* platform/chromium/fast/borders/border-image-02-expected.txt: Added.
* platform/efl/TestExpectations:
* platform/gtk/fast/borders/border-image-02-expected.png: Added.
* platform/gtk/fast/borders/border-image-02-expected.txt: Added.
* platform/mac-wk2/TestExpectations:
* platform/mac/TestExpectations:
* platform/qt/TestExpectations:
* platform/win/TestExpectations:

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

18 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/borders/border-image-02.html [new file with mode: 0644]
LayoutTests/platform/chromium-linux/fast/borders/border-image-02-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium/TestExpectations
LayoutTests/platform/chromium/fast/borders/border-image-02-expected.txt [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/fast/borders/border-image-02-expected.png [new file with mode: 0644]
LayoutTests/platform/gtk/fast/borders/border-image-02-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/qt/TestExpectations
LayoutTests/platform/win/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsContext.cpp
Source/WebCore/platform/graphics/GraphicsContext.h
Source/WebCore/platform/graphics/Image.cpp
Source/WebCore/platform/graphics/Image.h
Source/WebCore/rendering/RenderBoxModelObject.cpp

index 6a8b3c6ef04d18a11dad30e5263344df0417ec67..c4e6dbc4f482db64624deac72cf6b97476539015 100644 (file)
@@ -1,3 +1,25 @@
+2013-02-19  Uday Kiran  <udaykiran@motorola.com>
+
+        'round' not implemented in border-image
+        https://bugs.webkit.org/show_bug.cgi?id=14185
+
+        Reviewed by David Hyatt.
+
+        Added test for 'round' keyword of border-image-repeat CSS property
+        http://dev.w3.org/csswg/css3-background/#border-image-repeat
+
+        * fast/borders/border-image-02.html: Added.
+        * platform/chromium-linux/fast/borders/border-image-02-expected.png: Added.
+        * platform/chromium/TestExpectations:
+        * platform/chromium/fast/borders/border-image-02-expected.txt: Added.
+        * platform/efl/TestExpectations:
+        * platform/gtk/fast/borders/border-image-02-expected.png: Added.
+        * platform/gtk/fast/borders/border-image-02-expected.txt: Added.
+        * platform/mac-wk2/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/qt/TestExpectations:
+        * platform/win/TestExpectations:
+
 2013-02-19  Julien Chaffraix  <jchaffraix@webkit.org>
 
         [CSS Grid Layout] Refactor the code in preparation of auto placement support
diff --git a/LayoutTests/fast/borders/border-image-02.html b/LayoutTests/fast/borders/border-image-02.html
new file mode 100644 (file)
index 0000000..f23bfbc
--- /dev/null
@@ -0,0 +1,71 @@
+<html>
+<head>
+    <style>
+        div {
+            border-width: 21px 30px 30px 21px;
+            width: 70px;
+            height: 55px;
+            margin: 10px;
+            display: inline-block;
+               }
+       
+               div.oo {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill round round;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill round round;
+               }
+       
+               div.or {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill round repeat;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill round repeat;
+               }
+       
+               div.os {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill round stretch;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill round stretch;
+               }
+       
+               div.ro {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill repeat round;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill repeat round;
+               }
+       
+               div.rr {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill repeat repeat;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill repeat repeat;
+               }
+       
+               div.rs {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill repeat stretch;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill repeat stretch;
+               }
+       
+               div.so {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill stretch round;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill stretch round;
+               }
+       
+               div.sr {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill stretch repeat;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill stretch repeat;
+               }
+       
+               div.ss {
+                   -webkit-border-image: url("resources/border-image.png") 21 30 30 21 fill stretch stretch;
+                   border-image: url("resources/border-image.png") 21 30 30 21 fill stretch stretch;
+               }
+    </style>
+</head>
+<body>
+    <div class="oo"></div>
+    <div class="ro"></div>
+    <div class="so"></div>
+    <br>
+    <div class="or"></div>
+    <div class="rr"></div>
+    <div class="sr"></div>
+    <br>
+    <div class="os"></div>
+    <div class="rs"></div>
+    <div class="ss"></div>
+</body>
+</html>
diff --git a/LayoutTests/platform/chromium-linux/fast/borders/border-image-02-expected.png b/LayoutTests/platform/chromium-linux/fast/borders/border-image-02-expected.png
new file mode 100644 (file)
index 0000000..4d65296
Binary files /dev/null and b/LayoutTests/platform/chromium-linux/fast/borders/border-image-02-expected.png differ
index 6efad50fc6c46649c57166c4cf45537a132225ef..edb1af11ddc238cfc54b2048fe78332016011853 100644 (file)
@@ -2018,6 +2018,9 @@ crbug.com/9798 [ Win Release ] http/tests/xmlhttprequest/small-chunks-response-t
 # so the test timeouts.
 crbug.com/11001 http/tests/history/back-to-post.php [ Timeout ]
 
+# Needs baseline after 14185
+webkit.org/b/14185 [ Android Win Mac ] fast/borders/border-image-02.html [ Missing ]
+
 # WebKit 45086:45111
 crbug.com/15270 fast/js/excessive-comma-usage.html [ Failure ]
 
@@ -2911,6 +2914,9 @@ webkit.org/b/74694 http/tests/cache/history-only-cached-subresource-loads-max-ag
 
 webkit.org/b/67915 [ Android ] fast/borders/borderRadiusDashed06.html [ ImageOnlyFailure ]
 
+# Needs rebaseline after bug 14185
+webkit.org/b/14185 fast/borders/border-image-rotate-transform.html [ ImageOnlyFailure ]
+
 webkit.org/b/95365 fast/loader/reload-zero-byte-plugin.html
 
 webkit.org/b/68196 [ Win Mac Android ] fast/clip/overflow-border-radius-composited.html [ ImageOnlyFailure ]
diff --git a/LayoutTests/platform/chromium/fast/borders/border-image-02-expected.txt b/LayoutTests/platform/chromium/fast/borders/border-image-02-expected.txt
new file mode 100644 (file)
index 0000000..20dde6e
--- /dev/null
@@ -0,0 +1,33 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (10,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,111) size 4x19
+        text run at (141,111) width 4: " "
+      RenderBlock {DIV} at (155,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,111) size 4x19
+        text run at (286,111) width 4: " "
+      RenderBlock {DIV} at (300,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (431,111) size 4x19
+        text run at (431,111) width 4: " "
+      RenderBR {BR} at (0,0) size 0x0
+      RenderBlock {DIV} at (10,141) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,242) size 4x19
+        text run at (141,242) width 4: " "
+      RenderBlock {DIV} at (155,141) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,242) size 4x19
+        text run at (286,242) width 4: " "
+      RenderBlock {DIV} at (300,141) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (431,242) size 4x19
+        text run at (431,242) width 4: " "
+      RenderBR {BR} at (0,0) size 0x0
+      RenderBlock {DIV} at (10,272) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,373) size 4x19
+        text run at (141,373) width 4: " "
+      RenderBlock {DIV} at (155,272) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,373) size 4x19
+        text run at (286,373) width 4: " "
+      RenderBlock {DIV} at (300,272) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (0,0) size 0x0
index 01d8141cc28cba9cb66b4db096bab4b61c8bce89..99fd55fb37987542de7c7df5bed63176c033ee5a 100644 (file)
@@ -676,6 +676,9 @@ webkit.org/b/100519 fast/images/paletted-png-with-color-profile.html [ Skip ]
 webkit.org/b/105542 fast/canvas/canvas-blend-image.html [ Skip ]
 webkit.org/b/105542 fast/canvas/canvas-blend-solid.html [ Skip ]
 
+# Needs baseline after 14185
+webkit.org/b/14185 fast/borders/border-image-02.html [ Missing ]
+
 #////////////////////////////////////////////////////////////////////////////////////////
 # CRASHES
 #////////////////////////////////////////////////////////////////////////////////////////
diff --git a/LayoutTests/platform/gtk/fast/borders/border-image-02-expected.png b/LayoutTests/platform/gtk/fast/borders/border-image-02-expected.png
new file mode 100644 (file)
index 0000000..ebf3710
Binary files /dev/null and b/LayoutTests/platform/gtk/fast/borders/border-image-02-expected.png differ
diff --git a/LayoutTests/platform/gtk/fast/borders/border-image-02-expected.txt b/LayoutTests/platform/gtk/fast/borders/border-image-02-expected.txt
new file mode 100644 (file)
index 0000000..8ced534
--- /dev/null
@@ -0,0 +1,33 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (10,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,111) size 4x19
+        text run at (141,111) width 4: " "
+      RenderBlock {DIV} at (155,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,111) size 4x19
+        text run at (286,111) width 4: " "
+      RenderBlock {DIV} at (300,10) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (431,111) size 4x19
+        text run at (431,111) width 4: " "
+      RenderBR {BR} at (0,0) size 0x0
+      RenderBlock {DIV} at (10,139) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,240) size 4x19
+        text run at (141,240) width 4: " "
+      RenderBlock {DIV} at (155,139) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,240) size 4x19
+        text run at (286,240) width 4: " "
+      RenderBlock {DIV} at (300,139) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (431,240) size 4x19
+        text run at (431,240) width 4: " "
+      RenderBR {BR} at (0,0) size 0x0
+      RenderBlock {DIV} at (10,268) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (141,369) size 4x19
+        text run at (141,369) width 4: " "
+      RenderBlock {DIV} at (155,268) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (286,369) size 4x19
+        text run at (286,369) width 4: " "
+      RenderBlock {DIV} at (300,268) size 121x106 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
+      RenderText {#text} at (0,0) size 0x0
index 2ebc013742b9178eb4b2f0cf1da1eb2ae05cd751..c9a33a3e2655e735f5fff71c63d7d7d7ae220767 100644 (file)
@@ -252,6 +252,9 @@ http/tests/security/local-user-CSS-from-remote.html
 # https://bugs.webkit.org/show_bug.cgi?id=58337
 fast/dom/StyleSheet/detached-stylesheet-without-wrapper.html
 
+# Needs baseline after bug 14185
+fast/borders/border-image-02.html
+
 # All spatial navigation tests fail on Mac WK2
 webkit.org/b/96438 fast/spatial-navigation
 
index 4b932c1958cf22dcfc686e17066be1ba20d50d43..e1bb109c933555e7b414ab9283b95b93478e80cf 100644 (file)
@@ -1111,6 +1111,9 @@ plugins/npruntime/invoke-failure.html
 # Very flaky, often failing on retry, too.
 svg/dom/SVGScriptElement/script-change-externalResourcesRequired-while-loading.svg
 
+# Needs baseline after 14185
+webkit.org/b/14185 fast/borders/border-image-02.html [ Missing ]
+
 # Unknown failures.
 http/tests/multipart/invalid-image-data-standalone.html
 webkit.org/b/76478 compositing/iframes/repaint-after-losing-scrollbars.html [ ImageOnlyFailure ]
index ac32d2b5c1ee93aa8288fad78060b24c2352ecde..f7609a0b13d3f0d4fe1b9e8a40aa36411b8065be 100644 (file)
@@ -1681,6 +1681,7 @@ fast/block/positioning/absolute-in-inline-ltr.html
 fast/block/positioning/absolute-in-inline-rtl-2.html
 fast/block/positioning/absolute-in-inline-rtl-3.html
 fast/block/positioning/absolute-in-inline-rtl.html
+fast/borders/border-image-02.html
 fast/borders/border-image-omit-right-slice.html
 fast/borders/borderRadiusAllStylesAllCorners.html
 fast/borders/borderRadiusDashed01.html
index 23d3282720463d1fe70b38c0b51de848c225586e..8315d7b3a2332162b068ace4996ed8dff4a78649 100644 (file)
@@ -2555,6 +2555,9 @@ proximity/window-property.html
 webkit.org/b/9221 fast/css/resize-corner-tracking.html [ Failure ]
 webkit.org/b/9221 fast/css/resize-corner-tracking-transformed-iframe.html [ Missing ]
 
+# Needs baseline after 14185
+webkit.org/b/14185 fast/borders/border-image-02.html [ Missing ]
+
 # Temporarily skip inspector tests which are now failing on the bots due to some configuration problem
 inspector
 http/tests/inspector
index b40f59be00208a194f7caedd4e95a24c51505109..558cfbb7096ebafe2a54df0be060d362e6906858 100644 (file)
@@ -1,3 +1,29 @@
+2013-02-19  Uday Kiran  <udaykiran@motorola.com>
+
+        'round' not implemented in border-image
+        https://bugs.webkit.org/show_bug.cgi?id=14185
+
+        Reviewed by David Hyatt.
+
+        Add rendering support for 'round' keyword of border-image-repeat CSS property
+        http://dev.w3.org/csswg/css3-background/#border-image-repeat
+        Rebased original patch by Benjamin Otte <otte@gnome.org> and made few fixes.
+
+        Test: fast/borders/border-image-02.html
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawTiledImage):
+        * platform/graphics/GraphicsContext.h:
+        (GraphicsContext):
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::drawTiled):
+        * platform/graphics/Image.h:
+        (Image):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintNinePieceImage): For 'round' keyword,
+        the image is tiled (repeated) to fill the area. If it does not fill the area
+        with a whole number of tiles, the image is rescaled so that it does.
+
 2013-02-19  Conrad Shultz  <conrad_shultz@apple.com>
 
         Allow UI clients to handle vertical wheel events.
index 5a13ff8d476f8202c6348cf55cf1482d7e1d8621..deaccccf36d5539c120a08d6de9f8f52691fa400 100644 (file)
@@ -514,24 +514,18 @@ void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, c
 }
 
 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect,
-    const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale)
+    const FloatPoint& patternPhase, const AffineTransform& patternTransform, CompositeOperator op, bool useLowQualityScale)
 {
     if (paintingDisabled() || !image)
         return;
 
-    if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
-        // Just do a scale.
-        drawImage(image, styleColorSpace, dest, srcRect, op);
-        return;
-    }
-
     if (useLowQualityScale) {
         InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
         setImageInterpolationQuality(InterpolationLow);
-        image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
+        image->drawTiled(this, dest, srcRect, patternPhase, patternTransform, styleColorSpace, op);
         setImageInterpolationQuality(previousInterpolationQuality);
     } else
-        image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
+        image->drawTiled(this, dest, srcRect, patternPhase, patternTransform, styleColorSpace, op);
 }
 
 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op, BlendMode blendMode)
index 5bc8881b41789531f635d382e6d03eb674f176a8..8911beb00508e6d2122e8342dc6b0a44952a5de7 100644 (file)
@@ -327,9 +327,7 @@ namespace WebCore {
         
         void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false, BlendMode = BlendModeNormal);
-        void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect,
-                            const FloatSize& tileScaleFactor, Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
-                            CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, const FloatPoint& patternPhase, const AffineTransform& patternTransform, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
 
         void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal);
         void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal, bool useLowQualityScale = false);
index 2d269e69e94e7f689c3b4e9a2c9d1036b775cc6f..720216f886ccb040612b6e4dedc8c1ff529db1c9 100644 (file)
@@ -143,33 +143,13 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
 
 // FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
 void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
-    const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator op)
+    const FloatPoint& patternPhase, const AffineTransform &patternTransform, ColorSpace styleColorSpace, CompositeOperator op)
 {    
     if (mayFillWithSolidColor()) {
         fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, op);
         return;
     }
     
-    // FIXME: We do not support 'round' or 'space' yet. For now just map them to 'repeat'.
-    if (hRule == RoundTile || hRule == SpaceTile)
-        hRule = RepeatTile;
-    if (vRule == RoundTile || vRule == SpaceTile)
-        vRule = RepeatTile;
-
-    AffineTransform patternTransform = AffineTransform().scaleNonUniform(tileScaleFactor.width(), tileScaleFactor.height());
-
-    // We want to construct the phase such that the pattern is centered (when stretch is not
-    // set for a particular rule).
-    float hPhase = tileScaleFactor.width() * srcRect.x();
-    float vPhase = tileScaleFactor.height() * srcRect.y();
-    float scaledTileWidth = tileScaleFactor.width() * srcRect.width();
-    float scaledTileHeight = tileScaleFactor.height() * srcRect.height();
-    if (hRule == Image::RepeatTile)
-        hPhase -= (dstRect.width() - scaledTileWidth) / 2;
-    if (vRule == Image::RepeatTile)
-        vPhase -= (dstRect.height() - scaledTileHeight) / 2; 
-    FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
-    
     drawPattern(ctxt, srcRect, patternTransform, patternPhase, styleColorSpace, op, dstRect);
 
     startAnimation();
index 637643d39cfb7139be1a5e932806ac539b19e64d..b3de2a6d4753ae39d5804c0df9a4598fde7a08b6 100644 (file)
@@ -201,7 +201,7 @@ protected:
     virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator, BlendMode, RespectImageOrientationEnum);
     void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, ColorSpace styleColorSpace,
         CompositeOperator , BlendMode);
-    void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator);
+    void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, const FloatPoint& patternPhase, const AffineTransform& patternTransform, ColorSpace styleColorSpace, CompositeOperator);
 
     // Supporting tiled drawing
     virtual bool mayFillWithSolidColor() { return false; }
index 30c76238b5c6afb487a6eba0d2eaad2e557fb81d..a8fba0047ac5fe6a77efaea03d1dc1735d9ee61d 100644 (file)
@@ -1267,142 +1267,180 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
     int imageHeight = imageSize.height();
     RenderView* renderView = view();
 
+    enum { TopTile, CenterTile, BottomTile, LeftTile = TopTile, RightTile = BottomTile };
+    int sliceX[3];
+    int sliceY[3];
+
     float imageScaleFactor = styleImage->imageScaleFactor();
-    int topSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight, renderView)) * imageScaleFactor;
-    int rightSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth, renderView)) * imageScaleFactor;
-    int bottomSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight, renderView)) * imageScaleFactor;
-    int leftSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth, renderView)) * imageScaleFactor;
+    sliceY[TopTile] = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight, renderView)) * imageScaleFactor;
+    sliceX[RightTile] = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth, renderView)) * imageScaleFactor;
+    sliceY[BottomTile] = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight, renderView)) * imageScaleFactor;
+    sliceX[LeftTile] = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth, renderView)) * imageScaleFactor;
+    sliceY[CenterTile] = max(0, imageHeight - sliceY[TopTile] - sliceY[BottomTile]);
+    sliceX[CenterTile] = max(0, imageWidth - sliceX[LeftTile] - sliceX[RightTile]);
 
     ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
     ENinePieceImageRule vRule = ninePieceImage.verticalRule();
 
-    int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height(), renderView);
-    int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width(), renderView);
-    int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height(), renderView);
-    int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width(), renderView);
+    int widthY[3];
+    int widthX[3];
+    widthY[TopTile] = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), sliceY[TopTile], borderImageRect.height(), renderView);
+    widthX[RightTile] = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), sliceX[RightTile], borderImageRect.width(), renderView);
+    widthY[BottomTile] = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), sliceY[BottomTile], borderImageRect.height(), renderView);
+    widthX[LeftTile] = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), sliceX[LeftTile], borderImageRect.width(), renderView);
     
     // Reduce the widths if they're too large.
     // The spec says: Given Lwidth as the width of the border image area, Lheight as its height, and Wside as the border image width
     // offset for the side, let f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all W are reduced by
     // multiplying them by f.
-    int borderSideWidth = max(1, leftWidth + rightWidth);
-    int borderSideHeight = max(1, topWidth + bottomWidth);
+    int borderSideWidth = max(1, widthX[LeftTile] + widthX[RightTile]);
+    int borderSideHeight = max(1, widthY[TopTile] + widthY[BottomTile]);
     float borderSideScaleFactor = min((float)borderImageRect.width() / borderSideWidth, (float)borderImageRect.height() / borderSideHeight);
     if (borderSideScaleFactor < 1) {
-        topWidth *= borderSideScaleFactor;
-        rightWidth *= borderSideScaleFactor;
-        bottomWidth *= borderSideScaleFactor;
-        leftWidth *= borderSideScaleFactor;
+        widthY[TopTile] *= borderSideScaleFactor;
+        widthX[RightTile] *= borderSideScaleFactor;
+        widthY[BottomTile] *= borderSideScaleFactor;
+        widthX[LeftTile] *= borderSideScaleFactor;
+    }
+
+    widthY[CenterTile] = max(0, borderImageRect.height() - widthY[TopTile] - widthY[BottomTile]);
+    widthX[CenterTile] = max(0, borderImageRect.width() - widthX[LeftTile] - widthX[RightTile]);
+
+    // 1. Scale to 'border-image-width'.
+    // - The two images for the top and bottom edges are made as tall as the top and bottom border image area parts,
+    //   respectively, and their width is scaled proportionally.
+    // - The images for the left and right edge are made as wide as the left and right border image area parts,
+    //   respectively, and their height is scaled proportionally.
+    // - The corner images are scaled to be as wide and as tall as the two border-image edges they are part of.
+
+    // We're implementing the standard using two variables for every row and column:
+    // "stretch" is the amount of scaling needed to make the source tile exactly fit the destination
+    // "scale" is the scaling applied to the middle row and column respecting border-image-repeat. Be careful,
+    // because scaleX is scaling in X direction, but applies to a column.
+    // Also, when a row or column doesn't need to be drawn, we're using 0.0 only, and not INF, as the spec does.
+    float stretchX[3];
+    float stretchY[3];
+    float scaleX[3];
+    float scaleY[3];
+    stretchX[LeftTile] = sliceX[LeftTile] ? static_cast<float>(widthX[LeftTile]) / sliceX[LeftTile] : 0.0;
+    stretchX[RightTile] = sliceX[RightTile] ? static_cast<float>(widthX[RightTile]) / sliceX[RightTile] : 0.0;
+    stretchX[CenterTile] = sliceX[CenterTile] ? static_cast<float>(widthX[CenterTile]) / sliceX[CenterTile] : 0.0;
+    stretchY[TopTile] = sliceY[TopTile] ? static_cast<float>(widthY[TopTile]) / sliceY[TopTile] : 0.0;
+    stretchY[BottomTile] = sliceY[BottomTile] ? static_cast<float>(widthY[BottomTile]) / sliceY[BottomTile] : 0.0;
+    stretchY[CenterTile] = sliceY[CenterTile] ? static_cast<float>(widthY[CenterTile]) / sliceY[CenterTile] : 0.0;
+
+    scaleX[TopTile] = stretchY[TopTile];
+    scaleX[BottomTile] = stretchY[BottomTile];
+    scaleY[LeftTile] = stretchX[LeftTile];
+    scaleY[RightTile] = stretchX[RightTile];
+
+    // The middle image's width is scaled by the same factor as the top image unless that factor is zero or infinity,
+    // in which case the scaling factor of the bottom is substituted, and failing that, the width is not scaled.
+    // The height of the middle image is scaled by the same factor as the left image unless that factor is zero or infinity,
+    // in which case the scaling factor of the right image is substituted, and failing that, the height is not scaled.
+    if (scaleX[TopTile])
+        scaleX[CenterTile] = scaleX[TopTile];
+    else if (scaleX[BottomTile])
+        scaleX[CenterTile] = scaleX[BottomTile];
+    else
+        scaleX[CenterTile] = 1.0f;
+    if (scaleY[LeftTile])
+        scaleY[CenterTile] = scaleY[LeftTile];
+    else if (scaleY[RightTile])
+        scaleY[CenterTile] = scaleY[RightTile];
+    else
+        scaleY[CenterTile] = 1.0f;
+
+    // Scale to 'border-image-repeat'.
+    switch (hRule) {
+    case StretchImageRule:
+        // If the first keyword is 'stretch', the top, middle and bottom images are further scaled to be as wide
+        // as the middle part of the border image area. The height is not changed any further.
+        scaleX[TopTile] = stretchX[CenterTile];
+        scaleX[CenterTile] = stretchX[CenterTile];
+        scaleX[BottomTile] = stretchX[CenterTile];
+        break;
+    case RoundImageRule:
+        // If the first keyword is 'round', the top, middle and bottom images are resized in width,
+        // so that exactly a whole number of them fit in the middle part of the border-image area,
+        // exactly as for 'round' in the 'background-repeat' property.
+        scaleX[TopTile] = stretchX[CenterTile] / max(1.0f, roundf(stretchX[CenterTile] / scaleX[TopTile]));
+        scaleX[CenterTile] = stretchX[CenterTile] / max(1.0f, roundf(stretchX[CenterTile] / scaleX[CenterTile]));
+        scaleX[BottomTile] = stretchX[CenterTile] / max(1.0f, roundf(stretchX[CenterTile] / scaleX[BottomTile]));
+        break;
+    case SpaceImageRule:
+        // FIXME: We do not support 'space' yet. For now map it to 'repeat'.
+    case RepeatImageRule:
+        // If the first keyword is 'repeat' or 'space', the top, middle, and bottom images are not changed any further.
+        break;
+    }
+    // The effects of 'stretch', 'round', 'repeat', and 'space' for the second keyword are analogous,
+    // acting on the height of the left, middle and right images.
+    switch (vRule) {
+    case StretchImageRule:
+        // If the first keyword is 'stretch', the top, middle and bottom images are further scaled to be as wide
+        // as the middle part of the border image area. The height is not changed any further.
+        scaleY[LeftTile] = stretchY[CenterTile];
+        scaleY[CenterTile] = stretchY[CenterTile];
+        scaleY[RightTile] = stretchY[CenterTile];
+        break;
+    case RoundImageRule:
+        // If the first keyword is 'round', the top, middle and bottom images are resized in width,
+        // so that exactly a whole number of them fit in the middle part of the border-image area,
+        // exactly as for 'round' in the 'background-repeat' property.
+        scaleY[LeftTile] = stretchY[CenterTile] / max(1.0f, roundf(stretchY[CenterTile] / scaleY[LeftTile]));
+        scaleY[CenterTile] = stretchY[CenterTile] / max(1.0f, roundf(stretchY[CenterTile] / scaleY[CenterTile]));
+        scaleY[RightTile] = stretchY[CenterTile] / max(1.0f, roundf(stretchY[CenterTile] / scaleY[RightTile]));
+        break;
+    case SpaceImageRule:
+        // FIXME: We do not support 'space' yet. For now map it to 'repeat'.
+    case RepeatImageRule:
+        // If the first keyword is 'repeat' or 'space', the top, middle, and bottom images are not changed any further.
+        break;
     }
-
-    bool drawLeft = leftSlice > 0 && leftWidth > 0;
-    bool drawTop = topSlice > 0 && topWidth > 0;
-    bool drawRight = rightSlice > 0 && rightWidth > 0;
-    bool drawBottom = bottomSlice > 0 && bottomWidth > 0;
-    bool drawMiddle = ninePieceImage.fill() && (imageWidth - leftSlice - rightSlice) > 0 && (borderImageRect.width() - leftWidth - rightWidth) > 0
-                      && (imageHeight - topSlice - bottomSlice) > 0 && (borderImageRect.height() - topWidth - bottomWidth) > 0;
 
     RefPtr<Image> image = styleImage->image(this, imageSize);
     ColorSpace colorSpace = style->colorSpace();
-    
-    float destinationWidth = borderImageRect.width() - leftWidth - rightWidth;
-    float destinationHeight = borderImageRect.height() - topWidth - bottomWidth;
-    
-    float sourceWidth = imageWidth - leftSlice - rightSlice;
-    float sourceHeight = imageHeight - topSlice - bottomSlice;
-    
-    float leftSideScale = drawLeft ? (float)leftWidth / leftSlice : 1;
-    float rightSideScale = drawRight ? (float)rightWidth / rightSlice : 1;
-    float topSideScale = drawTop ? (float)topWidth / topSlice : 1;
-    float bottomSideScale = drawBottom ? (float)bottomWidth / bottomSlice : 1;
-    
-    if (drawLeft) {
-        // Paint the top and bottom left corners.
-
-        // The top left corner rect is (tx, ty, leftWidth, topWidth)
-        // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
-        if (drawTop)
-            graphicsContext->drawImage(image.get(), colorSpace, IntRect(borderImageRect.location(), IntSize(leftWidth, topWidth)),
-                                       LayoutRect(0, 0, leftSlice, topSlice), op);
-
-        // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
-        // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
-        if (drawBottom)
-            graphicsContext->drawImage(image.get(), colorSpace, IntRect(borderImageRect.x(), borderImageRect.maxY() - bottomWidth, leftWidth, bottomWidth),
-                                       LayoutRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op);
-
-        // Paint the left edge.
-        // Have to scale and tile into the border rect.
-        if (sourceHeight > 0)
-            graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x(), borderImageRect.y() + topWidth, leftWidth,
-                                            destinationHeight),
-                                            IntRect(0, topSlice, leftSlice, sourceHeight),
-                                            FloatSize(leftSideScale, leftSideScale), Image::StretchTile, (Image::TileRule)vRule, op);
-    }
-
-    if (drawRight) {
-        // Paint the top and bottom right corners
-        // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
-        // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
-        if (drawTop)
-            graphicsContext->drawImage(image.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y(), rightWidth, topWidth),
-                                       LayoutRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op);
-
-        // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
-        // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice)
-        if (drawBottom)
-            graphicsContext->drawImage(image.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.maxY() - bottomWidth, rightWidth, bottomWidth),
-                                       LayoutRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op);
-
-        // Paint the right edge.
-        if (sourceHeight > 0)
-            graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y() + topWidth, rightWidth,
-                                            destinationHeight),
-                                            IntRect(imageWidth - rightSlice, topSlice, rightSlice, sourceHeight),
-                                            FloatSize(rightSideScale, rightSideScale),
-                                            Image::StretchTile, (Image::TileRule)vRule, op);
-    }
-
-    // Paint the top edge.
-    if (drawTop && sourceWidth > 0)
-        graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x() + leftWidth, borderImageRect.y(), destinationWidth, topWidth),
-                                        IntRect(leftSlice, 0, sourceWidth, topSlice),
-                                        FloatSize(topSideScale, topSideScale), (Image::TileRule)hRule, Image::StretchTile, op);
-
-    // Paint the bottom edge.
-    if (drawBottom && sourceWidth > 0)
-        graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x() + leftWidth, borderImageRect.maxY() - bottomWidth,
-                                        destinationWidth, bottomWidth),
-                                        IntRect(leftSlice, imageHeight - bottomSlice, sourceWidth, bottomSlice),
-                                        FloatSize(bottomSideScale, bottomSideScale),
-                                        (Image::TileRule)hRule, Image::StretchTile, op);
-
-    // Paint the middle.
-    if (drawMiddle) {
-        FloatSize middleScaleFactor(1, 1);
-        if (drawTop)
-            middleScaleFactor.setWidth(topSideScale);
-        else if (drawBottom)
-            middleScaleFactor.setWidth(bottomSideScale);
-        if (drawLeft)
-            middleScaleFactor.setHeight(leftSideScale);
-        else if (drawRight)
-            middleScaleFactor.setHeight(rightSideScale);
-            
-        // For "stretch" rules, just override the scale factor and replace. We only had to do this for the
-        // center tile, since sides don't even use the scale factor unless they have a rule other than "stretch".
-        // The middle however can have "stretch" specified in one axis but not the other, so we have to
-        // correct the scale here.
-        if (hRule == StretchImageRule)
-            middleScaleFactor.setWidth(destinationWidth / sourceWidth);
-            
-        if (vRule == StretchImageRule)
-            middleScaleFactor.setHeight(destinationHeight / sourceHeight);
-        
-        graphicsContext->drawTiledImage(image.get(), colorSpace,
-            IntRect(borderImageRect.x() + leftWidth, borderImageRect.y() + topWidth, destinationWidth, destinationHeight),
-            IntRect(leftSlice, topSlice, sourceWidth, sourceHeight),
-            middleScaleFactor, (Image::TileRule)hRule, (Image::TileRule)vRule, op);
+
+    // If the first keyword is 'repeat', the top, middle, and bottom images are centered horizontally in
+    // their respective areas. Otherwise the images are placed at the left edge of their respective parts
+    // of the border-image area.
+    // If the second keyword is 'repeat', the left, middle, and right images are centered vertically in their
+    // respective areas. Otherwise the images are placed at the top edge of their respective parts of the
+    // border-image area.
+    for (int j = 0; j < 3; j++) {
+        if (!stretchY[j])
+            continue;
+        for (int i = 0; i < 3; i++) {
+            if (!stretchX[i])
+                continue;
+            if (i == CenterTile && j == CenterTile && !ninePieceImage.fill())
+                continue;
+
+            // This somewhat weird size computation is necessary because left and right tile may overlap.
+            IntRect destRect(borderImageRect.x() + (i == LeftTile ? 0 : i == CenterTile ? widthX[LeftTile] : borderImageRect.width() - widthX[RightTile]),
+                borderImageRect.y() + (j == TopTile ? 0 : j == CenterTile ? widthY[TopTile] : borderImageRect.height() - widthY[BottomTile]), widthX[i], widthY[j]);
+
+            IntRect srcRect(i == LeftTile ? 0 : i == CenterTile ? sliceX[LeftTile] : imageWidth - sliceX[RightTile],
+                j == TopTile ? 0 : j == CenterTile ? sliceY[TopTile] : imageHeight - sliceY[BottomTile], sliceX[i], sliceY[j]);
+
+            if ((i == CenterTile && hRule != StretchImageRule) || (j == CenterTile && vRule != StretchImageRule)) {
+                // We want to construct the phase such that the pattern is centered (when stretch is not
+                // set for a particular rule).
+                AffineTransform transform;
+
+                transform.translate(destRect.x(), destRect.y());
+                if (i == CenterTile && hRule == RepeatImageRule)
+                    transform.translate((destRect.width() - scaleX[j] * sliceX[i]) / 2, 0);
+                if (j == CenterTile && vRule == RepeatImageRule)
+                    transform.translate(0, (destRect.height() - scaleY[i] * sliceY[j]) / 2);
+                transform.scaleNonUniform(i == CenterTile ? scaleX[j] : stretchX[i], j == CenterTile ? scaleY[i] : stretchY[j]);
+                transform.translate(-srcRect.x(), -srcRect.y());
+
+                graphicsContext->drawTiledImage(image.get(), colorSpace, destRect, srcRect, FloatPoint(), transform, op);
+            } else
+                graphicsContext->drawImage(image.get(), colorSpace, destRect, srcRect, op);
+        }
     }
 
     return true;