2011-04-19 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 05:13:32 +0000 (05:13 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 05:13:32 +0000 (05:13 +0000)
        Reviewed by Dan Bernstein.

        background color of elements with border-radius shows around outer edge of border at corners
        https://bugs.webkit.org/show_bug.cgi?id=21819

        When drawing a background followed by a border with the same rounded
        clip, some border color leaks out because of antialiasing.

        Fix this by using two different strategies depending on the colors.
        If the border is opaque on all sides, we can inset the background by
        a device pixel. If not, then we have to draw the unclipped background
        and border into a transparency layer, and then clip that.

        A futher possible solution is mentioned in a comment in
        determineBackgroundBleedAvoidance() but not yet implemented.

        Also don't try to paint shadows with zero offset, spread and blur.

        Test: fast/backgrounds/background-leakage.html,
              fast/backgrounds/background-leakage-transforms.html

        * rendering/RenderBoxModelObject.h:
        Add a BackgroundBleedAvoidance enum with a value for each
        strategy.
        * rendering/RenderBoxModelObject.cpp:
        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
        Pass BackgroundBleedAvoidance, bail early if the border rect is empty.
        If using the transparency layer solution, don't bother to clip
        to the rounded rect for the background. If the strategy is to
        shrink the background, do that.
        (WebCore::BorderEdge::BorderEdge):
        (WebCore::BorderEdge::obscuresBackgroundEdge):
        Helper method to determine if this border side will totally
        obscured by the border edge, allowing us to inset it.
        (WebCore::RenderBoxModelObject::paintOneBorderSide):
        Pass BackgroundBleedAvoidance through.
        (WebCore::RenderBoxModelObject::paintBorderSides):
        Ditto.
        (WebCore::RenderBoxModelObject::paintTranslucentBorderSides):
        Ditto.
        (WebCore::RenderBoxModelObject::paintBorder):
        Fill BorderEdges using getBorderEdgeInfo now.
        Don't clip to the rounded border if we are using the
        transparency layer solution.
        (WebCore::RenderBoxModelObject::drawBoxSideFromPath):
        Pass bleedAvoidance through, and use it for double borders.
        (WebCore::RenderBoxModelObject::getBorderEdgeInfo):
        Helper to fill in the BorderEdge array.
        (WebCore::RenderBoxModelObject::borderObscuresBackgroundEdge):
        Used to determine if we can use the background shrinkage solution.
        (WebCore::RenderBoxModelObject::paintBoxShadow):
        Don't paint shadows that should not be visible.

        * rendering/RenderBox.h:
        * rendering/RenderBox.cpp:
        (WebCore::RenderBox::paintRootBoxFillLayers):
        Pass BackgroundBleedNone for the root box.

        (WebCore::RenderBox::determineBackgroundBleedAvoidance):
        Determine which bleed strategy we can use.

        (WebCore::RenderBox::paintBoxDecorationsWithSize):
        Based on the bleedAvoidance, make a transparency layer
        which will be clipped to the rounded border outside edge,
        and pass bleedAvoidance to the background and border-painting
        methods.
        (WebCore::RenderBox::paintMaskImages):
        Use BackgroundBleedNone.
        (WebCore::RenderBox::paintFillLayers):
        (WebCore::RenderBox::paintFillLayer):
        Pass bleedAvoidance through.

        * rendering/InlineFlowBox.cpp:
        (WebCore::InlineFlowBox::paintFillLayer):
        (WebCore::InlineFlowBox::paintBoxDecorations):
        Pass BackgroundBleedNone. At some point we may want to do the right
        thing for split inlines.

        * rendering/RenderFieldset.cpp:
        (WebCore::RenderFieldset::paintBoxDecorations):
        * rendering/RenderTableCell.cpp:
        (WebCore::RenderTableCell::paintBackgroundsBehindCell):
        Pass BackgroundBleedNone.

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

91 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/backgrounds/background-leakage-transforms.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/backgrounds/background-leakage-expected.checksum
LayoutTests/platform/mac/fast/backgrounds/background-leakage-expected.png
LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/borders/border-radius-circle-expected.checksum
LayoutTests/platform/mac/fast/borders/border-radius-circle-expected.png
LayoutTests/platform/mac/fast/borders/border-radius-huge-assert-expected.checksum
LayoutTests/platform/mac/fast/borders/border-radius-huge-assert-expected.png
LayoutTests/platform/mac/fast/borders/border-radius-wide-border-01-expected.checksum
LayoutTests/platform/mac/fast/borders/border-radius-wide-border-01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusArcs01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusArcs01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDashed01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDashed01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDashed02-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDashed02-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDashed03-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDashed03-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDotted01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDotted01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDotted02-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDotted02-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDotted03-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDotted03-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDouble01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDouble01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDouble02-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDouble02-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusDouble03-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusDouble03-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusGroove01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusGroove01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusGroove02-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusGroove02-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusInset01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusInset01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusInvalidColor-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusInvalidColor-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusOutset01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusOutset01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusRidge01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusRidge01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusSolid01-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusSolid01-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusSolid02-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusSolid02-expected.png
LayoutTests/platform/mac/fast/borders/borderRadiusSolid03-expected.checksum
LayoutTests/platform/mac/fast/borders/borderRadiusSolid03-expected.png
LayoutTests/platform/mac/fast/box-shadow/inset-expected.checksum
LayoutTests/platform/mac/fast/box-shadow/inset-expected.png
LayoutTests/platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.checksum
LayoutTests/platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png
LayoutTests/platform/mac/fast/forms/basic-selects-expected.checksum
LayoutTests/platform/mac/fast/forms/basic-selects-expected.png
LayoutTests/platform/mac/fast/forms/menulist-clip-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-clip-expected.png
LayoutTests/platform/mac/fast/forms/menulist-narrow-width-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-narrow-width-expected.png
LayoutTests/platform/mac/fast/forms/menulist-option-wrap-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-option-wrap-expected.png
LayoutTests/platform/mac/fast/forms/menulist-restrict-line-height-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-restrict-line-height-expected.png
LayoutTests/platform/mac/fast/forms/menulist-separator-painting-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-separator-painting-expected.png
LayoutTests/platform/mac/fast/forms/menulist-style-color-expected.checksum
LayoutTests/platform/mac/fast/forms/menulist-style-color-expected.png
LayoutTests/platform/mac/fast/forms/select-baseline-expected.checksum
LayoutTests/platform/mac/fast/forms/select-baseline-expected.png
LayoutTests/platform/mac/fast/forms/select-empty-option-height-expected.checksum
LayoutTests/platform/mac/fast/forms/select-empty-option-height-expected.png
LayoutTests/platform/mac/fast/forms/select-style-expected.checksum
LayoutTests/platform/mac/fast/forms/select-style-expected.png
LayoutTests/platform/mac/fast/overflow/border-radius-clipping-expected.checksum
LayoutTests/platform/mac/fast/overflow/border-radius-clipping-expected.png
LayoutTests/platform/mac/fast/repaint/border-radius-repaint-expected.checksum
LayoutTests/platform/mac/fast/repaint/border-radius-repaint-expected.png
LayoutTests/platform/mac/fast/repaint/control-clip-expected.checksum
LayoutTests/platform/mac/fast/repaint/control-clip-expected.png
Source/WebCore/ChangeLog
Source/WebCore/rendering/InlineFlowBox.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderBoxModelObject.h
Source/WebCore/rendering/RenderFieldset.cpp
Source/WebCore/rendering/RenderTableCell.cpp

index 1a7b112..c17ea2a 100644 (file)
@@ -1,3 +1,93 @@
+2011-04-19  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dan Bernstein.
+
+        background color of elements with border-radius shows around outer edge of border at corners
+        https://bugs.webkit.org/show_bug.cgi?id=21819
+
+        * fast/backgrounds/background-leakage-transforms.html: Added.
+        * platform/mac/fast/backgrounds/background-leakage-expected.checksum:
+        * platform/mac/fast/backgrounds/background-leakage-expected.png:
+        * platform/mac/fast/backgrounds/background-leakage-transforms-expected.checksum: Added.
+        * platform/mac/fast/backgrounds/background-leakage-transforms-expected.png: Added.
+        * platform/mac/fast/backgrounds/background-leakage-transforms-expected.txt: Added.
+        * platform/mac/fast/borders/border-radius-circle-expected.checksum:
+        * platform/mac/fast/borders/border-radius-circle-expected.png:
+        * platform/mac/fast/borders/border-radius-huge-assert-expected.checksum:
+        * platform/mac/fast/borders/border-radius-huge-assert-expected.png:
+        * platform/mac/fast/borders/border-radius-wide-border-01-expected.checksum:
+        * platform/mac/fast/borders/border-radius-wide-border-01-expected.png:
+        * platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png:
+        * platform/mac/fast/borders/borderRadiusArcs01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusArcs01-expected.png:
+        * platform/mac/fast/borders/borderRadiusDashed01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDashed01-expected.png:
+        * platform/mac/fast/borders/borderRadiusDashed02-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDashed02-expected.png:
+        * platform/mac/fast/borders/borderRadiusDashed03-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDashed03-expected.png:
+        * platform/mac/fast/borders/borderRadiusDotted01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDotted01-expected.png:
+        * platform/mac/fast/borders/borderRadiusDotted02-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDotted02-expected.png:
+        * platform/mac/fast/borders/borderRadiusDotted03-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDotted03-expected.png:
+        * platform/mac/fast/borders/borderRadiusDouble01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDouble01-expected.png:
+        * platform/mac/fast/borders/borderRadiusDouble02-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDouble02-expected.png:
+        * platform/mac/fast/borders/borderRadiusDouble03-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusDouble03-expected.png:
+        * platform/mac/fast/borders/borderRadiusGroove01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusGroove01-expected.png:
+        * platform/mac/fast/borders/borderRadiusGroove02-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusGroove02-expected.png:
+        * platform/mac/fast/borders/borderRadiusInset01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusInset01-expected.png:
+        * platform/mac/fast/borders/borderRadiusInvalidColor-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusInvalidColor-expected.png:
+        * platform/mac/fast/borders/borderRadiusOutset01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusOutset01-expected.png:
+        * platform/mac/fast/borders/borderRadiusRidge01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusRidge01-expected.png:
+        * platform/mac/fast/borders/borderRadiusSolid01-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusSolid01-expected.png:
+        * platform/mac/fast/borders/borderRadiusSolid02-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusSolid02-expected.png:
+        * platform/mac/fast/borders/borderRadiusSolid03-expected.checksum:
+        * platform/mac/fast/borders/borderRadiusSolid03-expected.png:
+        * platform/mac/fast/box-shadow/inset-expected.checksum:
+        * platform/mac/fast/box-shadow/inset-expected.png:
+        * platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.checksum:
+        * platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png:
+        * platform/mac/fast/forms/basic-selects-expected.checksum:
+        * platform/mac/fast/forms/basic-selects-expected.png:
+        * platform/mac/fast/forms/menulist-clip-expected.checksum:
+        * platform/mac/fast/forms/menulist-clip-expected.png:
+        * platform/mac/fast/forms/menulist-narrow-width-expected.checksum:
+        * platform/mac/fast/forms/menulist-narrow-width-expected.png:
+        * platform/mac/fast/forms/menulist-option-wrap-expected.checksum:
+        * platform/mac/fast/forms/menulist-option-wrap-expected.png:
+        * platform/mac/fast/forms/menulist-restrict-line-height-expected.checksum:
+        * platform/mac/fast/forms/menulist-restrict-line-height-expected.png:
+        * platform/mac/fast/forms/menulist-separator-painting-expected.checksum:
+        * platform/mac/fast/forms/menulist-separator-painting-expected.png:
+        * platform/mac/fast/forms/menulist-style-color-expected.checksum:
+        * platform/mac/fast/forms/menulist-style-color-expected.png:
+        * platform/mac/fast/forms/select-baseline-expected.checksum:
+        * platform/mac/fast/forms/select-baseline-expected.png:
+        * platform/mac/fast/forms/select-empty-option-height-expected.checksum:
+        * platform/mac/fast/forms/select-empty-option-height-expected.png:
+        * platform/mac/fast/forms/select-style-expected.checksum:
+        * platform/mac/fast/forms/select-style-expected.png:
+        * platform/mac/fast/overflow/border-radius-clipping-expected.checksum:
+        * platform/mac/fast/overflow/border-radius-clipping-expected.png:
+        * platform/mac/fast/repaint/border-radius-repaint-expected.checksum:
+        * platform/mac/fast/repaint/border-radius-repaint-expected.png:
+        * platform/mac/fast/repaint/control-clip-expected.checksum:
+        * platform/mac/fast/repaint/control-clip-expected.png:
+
 2011-04-19  Dirk Pranke  <dpranke@chromium.org>
 
         Unreviewed, expectations change.
diff --git a/LayoutTests/fast/backgrounds/background-leakage-transforms.html b/LayoutTests/fast/backgrounds/background-leakage-transforms.html
new file mode 100644 (file)
index 0000000..d47f6c5
--- /dev/null
@@ -0,0 +1,74 @@
+<html>
+   <head>
+      <style type="text/css">
+        .grouping {
+          margin: 10px;
+          padding: 2px;
+          display: inline-block;
+        }
+
+        .box {
+          display: inline-block;
+          margin: 10px;
+          height: 100px;
+          width: 110px;
+          background-color: black;
+          border: 20px solid white;
+          border-radius: 50px;
+          -moz-box-sizing: border-box;
+          box-sizing: border-box;
+        }
+        
+        .translucent {
+          background-color: gray;
+        }
+        .translucent > .box {
+          background-color: white;
+          border-color: rgba(0, 0, 255, 0.5);
+        }
+        
+        .scaled {
+          -webkit-transform: scale(1, 0.33);
+          -webkit-transform-origin: top left;
+        }
+        
+        .vertical {
+          -webkit-writing-mode: vertical-lr;
+        }
+      </style>
+   </head>
+   <body>
+     <div>
+        <div class="grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+       <div class="translucent grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+     </div>
+
+     <div class="scaled">
+        <div class="grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+       <div class="translucent grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+     </div>
+
+     <div class="scaled vertical">
+        <div class="grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+       <div class="translucent grouping">
+         <div class="box"></div>
+         <div class="box" style="border-style: double; border-color: groove;"></div>
+       </div>
+     </div>
+   </body>
+</html>
\ No newline at end of file
index f8841c1..0ee799d 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/backgrounds/background-leakage-expected.png and b/LayoutTests/platform/mac/fast/backgrounds/background-leakage-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.checksum b/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.checksum
new file mode 100644 (file)
index 0000000..0f9f521
--- /dev/null
@@ -0,0 +1 @@
+11aef4167bdbde2a6f0513c22ace79f2
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.png b/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.png
new file mode 100644 (file)
index 0000000..3184b7c
Binary files /dev/null and b/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.txt b/LayoutTests/platform/mac/fast/backgrounds/background-leakage-transforms-expected.txt
new file mode 100644 (file)
index 0000000..c295990
--- /dev/null
@@ -0,0 +1,55 @@
+layer at (0,0) size 785x912
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x912
+  RenderBlock {HTML} at (0,0) size 785x912
+    RenderBody {BODY} at (8,8) size 769x896
+      RenderBlock {DIV} at (0,0) size 769x148
+        RenderBlock {DIV} at (10,10) size 268x128
+          RenderBlock {DIV} at (12,12) size 110x100 [bgcolor=#000000] [border: (20px solid #FFFFFF)]
+          RenderText {#text} at (132,108) size 4x18
+            text run at (132,108) width 4: " "
+          RenderBlock {DIV} at (146,12) size 110x100 [bgcolor=#000000] [border: (20px double #FFFFFF)]
+          RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (288,118) size 4x18
+          text run at (288,118) width 4: " "
+        RenderBlock {DIV} at (302,10) size 268x128 [bgcolor=#808080]
+          RenderBlock {DIV} at (12,12) size 110x100 [bgcolor=#FFFFFF] [border: (20px solid #0000FF7F)]
+          RenderText {#text} at (132,108) size 4x18
+            text run at (132,108) width 4: " "
+          RenderBlock {DIV} at (146,12) size 110x100 [bgcolor=#FFFFFF] [border: (20px double #0000FF7F)]
+          RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (8,156) size 769x148
+  RenderBlock {DIV} at (0,148) size 769x148
+    RenderBlock {DIV} at (10,10) size 268x128
+      RenderBlock {DIV} at (12,12) size 110x100 [bgcolor=#000000] [border: (20px solid #FFFFFF)]
+      RenderText {#text} at (132,108) size 4x18
+        text run at (132,108) width 4: " "
+      RenderBlock {DIV} at (146,12) size 110x100 [bgcolor=#000000] [border: (20px double #FFFFFF)]
+      RenderText {#text} at (0,0) size 0x0
+    RenderText {#text} at (288,118) size 4x18
+      text run at (288,118) width 4: " "
+    RenderBlock {DIV} at (302,10) size 268x128 [bgcolor=#808080]
+      RenderBlock {DIV} at (12,12) size 110x100 [bgcolor=#FFFFFF] [border: (20px solid #0000FF7F)]
+      RenderText {#text} at (132,108) size 4x18
+        text run at (132,108) width 4: " "
+      RenderBlock {DIV} at (146,12) size 110x100 [bgcolor=#FFFFFF] [border: (20px double #0000FF7F)]
+      RenderText {#text} at (0,0) size 0x0
+    RenderText {#text} at (0,0) size 0x0
+layer at (8,304) size 158x600
+  RenderBlock {DIV} at (0,296) size 158x600
+    RenderBlock {DIV} at (10,10) size 138x248
+      RenderBlock {DIV} at (16,12) size 110x100 [bgcolor=#000000] [border: (20px solid #FFFFFF)]
+      RenderText {#text} at (2,122) size 18x4
+        text run at (2,122) width 4: " "
+      RenderBlock {DIV} at (16,136) size 110x100 [bgcolor=#000000] [border: (20px double #FFFFFF)]
+      RenderText {#text} at (0,0) size 0x0
+    RenderText {#text} at (128,268) size 18x4
+      text run at (128,268) width 4: " "
+    RenderBlock {DIV} at (10,282) size 138x248 [bgcolor=#808080]
+      RenderBlock {DIV} at (16,12) size 110x100 [bgcolor=#FFFFFF] [border: (20px solid #0000FF7F)]
+      RenderText {#text} at (2,122) size 18x4
+        text run at (2,122) width 4: " "
+      RenderBlock {DIV} at (16,136) size 110x100 [bgcolor=#FFFFFF] [border: (20px double #0000FF7F)]
+      RenderText {#text} at (0,0) size 0x0
+    RenderText {#text} at (0,0) size 0x0
index c4da928..a4fd08c 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/border-radius-circle-expected.png and b/LayoutTests/platform/mac/fast/borders/border-radius-circle-expected.png differ
index 632170d..1a81fd5 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/border-radius-huge-assert-expected.png and b/LayoutTests/platform/mac/fast/borders/border-radius-huge-assert-expected.png differ
index 5112ca3..e174952 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/border-radius-wide-border-01-expected.png and b/LayoutTests/platform/mac/fast/borders/border-radius-wide-border-01-expected.png differ
index b282f9e..47efe84 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png differ
index cca5b8e..51018a0 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusArcs01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusArcs01-expected.png differ
index 857df05..12a8b1c 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDashed01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDashed01-expected.png differ
index 46cc6b2..a3f6e9b 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDashed02-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDashed02-expected.png differ
index b27ccda..5b56a75 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDashed03-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDashed03-expected.png differ
index 434153d..8073c2e 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDotted01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDotted01-expected.png differ
index cf16671..e9577c2 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDotted02-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDotted02-expected.png differ
index 750e62e..06bece0 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDotted03-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDotted03-expected.png differ
index a434721..1f5ddd6 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDouble01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDouble01-expected.png differ
index 9793b9b..2df0ced 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDouble02-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDouble02-expected.png differ
index b9a144b..01a6747 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusDouble03-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusDouble03-expected.png differ
index df2f8aa..296dfb5 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusGroove01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusGroove01-expected.png differ
index c32347f..87cd497 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusGroove02-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusGroove02-expected.png differ
index fc4fe7d..5d8b420 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusInset01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusInset01-expected.png differ
index 256e4e5..f049f06 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusInvalidColor-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusInvalidColor-expected.png differ
index 48e2c9c..6eb2315 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusOutset01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusOutset01-expected.png differ
index 9a7a8cd..eff2965 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusRidge01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusRidge01-expected.png differ
index 3ec1300..3d0505e 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusSolid01-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusSolid01-expected.png differ
index 91101e0..376c99a 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusSolid02-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusSolid02-expected.png differ
index 5295160..f713c46 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/borders/borderRadiusSolid03-expected.png and b/LayoutTests/platform/mac/fast/borders/borderRadiusSolid03-expected.png differ
index 1d5cb70..f4be044 100644 (file)
@@ -1 +1 @@
-148b87d8c1c983a51eb13ed14dfe3981
\ No newline at end of file
+3a81fa1a4637004d2c01d01f90e58ca9
\ No newline at end of file
index fcf9d84..60f9d9b 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png and b/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png differ
index a44d6ed..c51c3e6 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png and b/LayoutTests/platform/mac/fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png differ
index d793bf3..e59bc81 100644 (file)
@@ -1 +1 @@
-f6a4d0d8403f4b8c72b3f6eb6792601c
\ No newline at end of file
+523cafd614a95b7ae70c6e3a8d9cea30
\ No newline at end of file
index 27cd39e..b38490c 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/basic-selects-expected.png and b/LayoutTests/platform/mac/fast/forms/basic-selects-expected.png differ
index 10d30ef..36ee2fd 100644 (file)
@@ -1 +1 @@
-a66f62c487a504263dd23816d30c1b7c
\ No newline at end of file
+2360329aaf19a9ac47855f071e020089
\ No newline at end of file
index 702c996..1a076d9 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-clip-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-clip-expected.png differ
index c7d486b..b65bed1 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-narrow-width-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-narrow-width-expected.png differ
index c065d90..e927ce8 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-option-wrap-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-option-wrap-expected.png differ
index f49c61f..2987f37 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-restrict-line-height-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-restrict-line-height-expected.png differ
index 9f57734..efa54fa 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-separator-painting-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-separator-painting-expected.png differ
index 2e89925..1efc5d3 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/menulist-style-color-expected.png and b/LayoutTests/platform/mac/fast/forms/menulist-style-color-expected.png differ
index 9ff1e40..62f3178 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/select-baseline-expected.png and b/LayoutTests/platform/mac/fast/forms/select-baseline-expected.png differ
index 8b2da71..c082963 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/select-empty-option-height-expected.png and b/LayoutTests/platform/mac/fast/forms/select-empty-option-height-expected.png differ
index c7e6338..9f5153e 100644 (file)
@@ -1 +1 @@
-48a3cab308291de930dc282008ef62d0
\ No newline at end of file
+0765dfc84133011df8c57e1dd30b1156
\ No newline at end of file
index 74ed402..24199b6 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/forms/select-style-expected.png and b/LayoutTests/platform/mac/fast/forms/select-style-expected.png differ
index db9207f..b640013 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/overflow/border-radius-clipping-expected.png and b/LayoutTests/platform/mac/fast/overflow/border-radius-clipping-expected.png differ
index 18605a3..39594dc 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/repaint/border-radius-repaint-expected.png and b/LayoutTests/platform/mac/fast/repaint/border-radius-repaint-expected.png differ
index 8891cec..a751fd4 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/repaint/control-clip-expected.png and b/LayoutTests/platform/mac/fast/repaint/control-clip-expected.png differ
index cdf9319..64ce8ec 100644 (file)
@@ -1,3 +1,89 @@
+2011-04-19  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dan Bernstein.
+
+        background color of elements with border-radius shows around outer edge of border at corners
+        https://bugs.webkit.org/show_bug.cgi?id=21819
+        
+        When drawing a background followed by a border with the same rounded
+        clip, some border color leaks out because of antialiasing.
+        
+        Fix this by using two different strategies depending on the colors.
+        If the border is opaque on all sides, we can inset the background by
+        a device pixel. If not, then we have to draw the unclipped background
+        and border into a transparency layer, and then clip that.
+        
+        A futher possible solution is mentioned in a comment in
+        determineBackgroundBleedAvoidance() but not yet implemented.
+        
+        Also don't try to paint shadows with zero offset, spread and blur.
+
+        Test: fast/backgrounds/background-leakage.html,
+              fast/backgrounds/background-leakage-transforms.html
+
+        * rendering/RenderBoxModelObject.h:
+        Add a BackgroundBleedAvoidance enum with a value for each
+        strategy.
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        Pass BackgroundBleedAvoidance, bail early if the border rect is empty.
+        If using the transparency layer solution, don't bother to clip
+        to the rounded rect for the background. If the strategy is to
+        shrink the background, do that.
+        (WebCore::BorderEdge::BorderEdge):
+        (WebCore::BorderEdge::obscuresBackgroundEdge):
+        Helper method to determine if this border side will totally
+        obscured by the border edge, allowing us to inset it.
+        (WebCore::RenderBoxModelObject::paintOneBorderSide):
+        Pass BackgroundBleedAvoidance through.
+        (WebCore::RenderBoxModelObject::paintBorderSides):
+        Ditto.
+        (WebCore::RenderBoxModelObject::paintTranslucentBorderSides):
+        Ditto.
+        (WebCore::RenderBoxModelObject::paintBorder):
+        Fill BorderEdges using getBorderEdgeInfo now.
+        Don't clip to the rounded border if we are using the
+        transparency layer solution.
+        (WebCore::RenderBoxModelObject::drawBoxSideFromPath):
+        Pass bleedAvoidance through, and use it for double borders.
+        (WebCore::RenderBoxModelObject::getBorderEdgeInfo):
+        Helper to fill in the BorderEdge array.
+        (WebCore::RenderBoxModelObject::borderObscuresBackgroundEdge):
+        Used to determine if we can use the background shrinkage solution.
+        (WebCore::RenderBoxModelObject::paintBoxShadow):
+        Don't paint shadows that should not be visible.
+
+        * rendering/RenderBox.h:
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintRootBoxFillLayers):
+        Pass BackgroundBleedNone for the root box.
+        
+        (WebCore::RenderBox::determineBackgroundBleedAvoidance):
+        Determine which bleed strategy we can use.
+        
+        (WebCore::RenderBox::paintBoxDecorationsWithSize):
+        Based on the bleedAvoidance, make a transparency layer
+        which will be clipped to the rounded border outside edge,
+        and pass bleedAvoidance to the background and border-painting
+        methods.        
+        (WebCore::RenderBox::paintMaskImages):
+        Use BackgroundBleedNone.
+        (WebCore::RenderBox::paintFillLayers):
+        (WebCore::RenderBox::paintFillLayer):
+        Pass bleedAvoidance through.
+
+        * rendering/InlineFlowBox.cpp:
+        (WebCore::InlineFlowBox::paintFillLayer):
+        (WebCore::InlineFlowBox::paintBoxDecorations):
+        Pass BackgroundBleedNone. At some point we may want to do the right
+        thing for split inlines.
+
+        * rendering/RenderFieldset.cpp:
+        (WebCore::RenderFieldset::paintBoxDecorations):
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::paintBackgroundsBehindCell):
+        Pass BackgroundBleedNone.
+
 2011-04-19  Yuta Kitamura  <yutak@chromium.org>
 
         Reviewed by Alexey Proskuryakov.
index 045edff..0900ce4 100644 (file)
@@ -1029,7 +1029,7 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
     StyleImage* img = fillLayer->image();
     bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());
     if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
-        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, this, w, h, op);
+        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, BackgroundBleedNone, this, w, h, op);
     else {
         // We have a fill image that spans multiple lines.
         // We need to adjust tx and ty by the width of all previous lines.
@@ -1058,7 +1058,7 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
         int stripHeight = isHorizontal() ? height() : totalLogicalWidth;
         paintInfo.context->save();
         paintInfo.context->clip(IntRect(tx, ty, width(), height()));
-        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, stripX, stripY, stripWidth, stripHeight, this, w, h, op);
+        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, stripX, stripY, stripWidth, stripHeight, BackgroundBleedNone, this, w, h, op);
         paintInfo.context->restore();
     }
 }
@@ -1127,7 +1127,7 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
             // The simple case is where we either have no border image or we are the only box for this object.  In those
             // cases only a single call to draw is required.
             if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
-                boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), includeLogicalLeftEdge(), includeLogicalRightEdge());
+                boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
             else {
                 // We have a border image that spans multiple lines.
                 // We need to adjust tx and ty by the width of all previous lines.
index 69f0691..23eec60 100644 (file)
@@ -803,7 +803,7 @@ void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
 
     // The background of the box generated by the root element covers the entire canvas, so just use
     // the RenderView's docTop/Left/Width/Height accessors.
-    paintFillLayers(paintInfo, bgColor, bgLayer, view()->docLeft(), view()->docTop(), view()->docWidth(), view()->docHeight(), CompositeSourceOver, bodyObject);
+    paintFillLayers(paintInfo, bgColor, bgLayer, view()->docLeft(), view()->docTop(), view()->docWidth(), view()->docHeight(), BackgroundBleedNone, CompositeSourceOver, bodyObject);
 }
 
 void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
@@ -813,6 +813,29 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
     return paintBoxDecorationsWithSize(paintInfo, tx, ty, width(), height());
 }
 
+BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context) const
+{
+    if (context->paintingDisabled())
+        return BackgroundBleedNone;
+
+    const RenderStyle* style = this->style();
+
+    if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius())
+        return BackgroundBleedNone;
+
+    AffineTransform ctm = context->getCTM();
+    FloatSize contextScaling(ctm.xScale(), ctm.yScale());
+    if (borderObscuresBackgroundEdge(contextScaling))
+        return BackgroundBleedShrinkBackground;
+    
+    // FIXME: there is one more strategy possible, for opaque backgrounds and
+    // translucent borders. In that case we could avoid using a transparency layer,
+    // and paint the border first, and then paint the background clipped to the
+    // inside of the border.
+
+    return BackgroundBleedUseTransparencyLayer;
+}
+
 void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty, int width, int height)
 {
     // border-fit can adjust where we paint our border and background.  If set, we snugly fit our line box descendants.  (The iChat
@@ -823,6 +846,17 @@ void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty
     // custom shadows of their own.
     paintBoxShadow(paintInfo.context, tx, ty, width, height, style(), Normal);
 
+    BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
+    if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+        // To avoid the background color bleeding out behind the border, we'll render background and border
+        // into a transparency layer, and then clip that in one go (which requires setting up the clip before
+        // beginning the layer).
+        RoundedIntRect border = style()->getRoundedBorderFor(IntRect(tx, ty, width, height));
+        paintInfo.context->save();
+        paintInfo.context->addRoundedRectClip(border);
+        paintInfo.context->beginTransparencyLayer(1);
+    }
+    
     // If we have a native theme appearance, paint that before painting our background.
     // The theme will tell us whether or not we should also paint the CSS background.
     bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, IntRect(tx, ty, width, height));
@@ -832,7 +866,7 @@ void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty
         else if (!isBody() || document()->documentElement()->renderer()->hasBackground()) {
             // The <body> only paints its background if the root element has defined a background
             // independent of the body.
-            paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, width, height);
+            paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, width, height, bleedAvoidance);
         }
         if (style()->hasAppearance())
             theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, width, height));
@@ -841,7 +875,12 @@ void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty
 
     // The theme will tell us whether or not we should also paint the CSS border.
     if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, IntRect(tx, ty, width, height)))) && style()->hasBorder())
-        paintBorder(paintInfo.context, tx, ty, width, height, style());
+        paintBorder(paintInfo.context, tx, ty, width, height, style(), bleedAvoidance);
+
+    if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+        paintInfo.context->endTransparencyLayer();
+        paintInfo.context->restore();
+    }
 }
 
 void RenderBox::paintMask(PaintInfo& paintInfo, int tx, int ty)
@@ -917,7 +956,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int
     }
 
     if (allMaskImagesLoaded) {
-        paintFillLayers(paintInfo, Color(), style()->maskLayers(), tx, ty, w, h, compositeOp);
+        paintFillLayers(paintInfo, Color(), style()->maskLayers(), tx, ty, w, h, BackgroundBleedNone, compositeOp);
         paintNinePieceImage(paintInfo.context, tx, ty, w, h, style(), style()->maskBoxImage(), compositeOp);
     }
     
@@ -944,18 +983,20 @@ IntRect RenderBox::maskClipRect()
     return result;
 }
 
-void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op, RenderObject* backgroundObject)
+void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height,
+    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
 {
     if (!fillLayer)
         return;
 
-    paintFillLayers(paintInfo, c, fillLayer->next(), tx, ty, width, height, op, backgroundObject);
-    paintFillLayer(paintInfo, c, fillLayer, tx, ty, width, height, op, backgroundObject);
+    paintFillLayers(paintInfo, c, fillLayer->next(), tx, ty, width, height, bleedAvoidance, op, backgroundObject);
+    paintFillLayer(paintInfo, c, fillLayer, tx, ty, width, height, bleedAvoidance, op, backgroundObject);
 }
 
-void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op, RenderObject* backgroundObject)
+void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height,
+    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
 {
-    paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, 0, 0, op, backgroundObject);
+    paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, bleedAvoidance, 0, 0, 0, op, backgroundObject);
 }
 
 #if USE(ACCELERATED_COMPOSITING)
index 6b6b437..258f213 100644 (file)
@@ -405,8 +405,8 @@ protected:
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
     virtual void updateBoxModelInfoFromStyle();
 
-    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator op, RenderObject* backgroundObject);
-    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, BackgroundBleedAvoidance, CompositeOperator, RenderObject* backgroundObject);
+    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, BackgroundBleedAvoidance = BackgroundBleedNone, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
 
     void paintBoxDecorationsWithSize(PaintInfo&, int tx, int ty, int width, int height);
     void paintMaskImages(const PaintInfo&, int tx, int ty, int width, int height);
@@ -452,6 +452,8 @@ private:
     // These include tables, positioned objects, floats and flexible boxes.
     virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
 
+    BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
+
 private:
     // The width/height of the contents + borders + padding.  The x/y location is relative to our container (which is not always our parent).
     IntRect m_frameRect;
index 52196e3..560753c 100644 (file)
@@ -572,12 +572,16 @@ RoundedIntRect RenderBoxModelObject::getBackgroundRoundedRect(const IntRect& bor
 }
 
 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, int tx, int ty, int w, int h,
-    InlineFlowBox* box, int inlineBoxWidth, int inlineBoxHeight, CompositeOperator op, RenderObject* backgroundObject)
+    BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, int inlineBoxWidth, int inlineBoxHeight, CompositeOperator op, RenderObject* backgroundObject)
 {
     GraphicsContext* context = paintInfo.context;
     if (context->paintingDisabled())
         return;
 
+    IntRect borderRect(tx, ty, w, h);
+    if (borderRect.isEmpty())
+        return;
+
     bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true;
     bool includeRightEdge = box ? box->includeLogicalRightEdge() : true;
 
@@ -612,12 +616,16 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
         if (!colorVisible)
             return;
 
-        IntRect borderRect(tx, ty, w, h);
-        if (borderRect.isEmpty())
-            return;
-
-        if (hasRoundedBorder) {
-            RoundedIntRect border = getBackgroundRoundedRect(borderRect, box, inlineBoxWidth, inlineBoxHeight, includeLeftEdge, includeRightEdge);
+        if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
+            IntRect roundedBorder = borderRect;
+            if (bleedAvoidance == BackgroundBleedShrinkBackground) {
+                // We need to shrink the border by one device pixel on each side.
+                AffineTransform ctm = context->getCTM();
+                FloatSize contextScale(ctm.xScale(), ctm.yScale());
+                roundedBorder.inflateX(-ceilf(1.0f / contextScale.width()));
+                roundedBorder.inflateY(-ceilf(1.0f / contextScale.height()));
+            }
+            RoundedIntRect border = getBackgroundRoundedRect(roundedBorder, box, inlineBoxWidth, inlineBoxHeight, includeLeftEdge, includeRightEdge);
             context->fillRoundedRect(border, bgColor, style()->colorSpace());
         } else
             context->fillRect(borderRect, bgColor, style()->colorSpace());
@@ -626,14 +634,8 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
     }
 
     bool clippedToBorderRadius = false;
-    if (hasRoundedBorder) {
-        IntRect borderRect(tx, ty, w, h);
-
-        if (borderRect.isEmpty())
-            return;
-
+    if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
         context->save();
-
         RoundedIntRect border = getBackgroundRoundedRect(borderRect, box, inlineBoxWidth, inlineBoxHeight, includeLeftEdge, includeRightEdge);
         context->addRoundedRectClip(border);
         clippedToBorderRadius = true;
@@ -1034,33 +1036,9 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
     return true;
 }
 
-#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
-static bool borderWillArcInnerEdge(const IntSize& firstRadius, const IntSize& secondRadius)
-{
-    return !firstRadius.isZero() || !secondRadius.isZero();
-}
-
-enum BorderEdgeFlag {
-    TopBorderEdge = 1 << BSTop,
-    RightBorderEdge = 1 << BSRight,
-    BottomBorderEdge = 1 << BSBottom,
-    LeftBorderEdge = 1 << BSLeft,
-    AllBorderEdges = TopBorderEdge | BottomBorderEdge | LeftBorderEdge | RightBorderEdge
-};
-
-static inline BorderEdgeFlag edgeFlagForSide(BoxSide side)
-{
-    return static_cast<BorderEdgeFlag>(1 << side);
-}
-
-static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side)
-{
-    return flags & edgeFlagForSide(side);
-}
-
 class BorderEdge {
 public:
-    BorderEdge(int edgeWidth, const Color& edgeColor, EBorderStyle edgeStyle, bool edgeIsTransparent, bool edgeIsPresent)
+    BorderEdge(int edgeWidth, const Color& edgeColor, EBorderStyle edgeStyle, bool edgeIsTransparent, bool edgeIsPresent = true)
         : width(edgeWidth)
         , color(edgeColor)
         , style(edgeStyle)
@@ -1071,9 +1049,30 @@ public:
             style = SOLID;
     }
     
+    BorderEdge()
+        : width(0)
+        , style(BHIDDEN)
+        , isTransparent(false)
+        , isPresent(false)
+    {
+    }
+    
     bool hasVisibleColorAndStyle() const { return style > BHIDDEN && !isTransparent; }
     bool shouldRender() const { return isPresent && hasVisibleColorAndStyle(); }
     bool presentButInvisible() const { return usedWidth() && !hasVisibleColorAndStyle(); }
+    bool obscuresBackgroundEdge(float scale) const
+    {
+        if (!isPresent || isTransparent || width < (2 * scale) || color.hasAlpha() || style == BHIDDEN)
+            return false;
+
+        if (style == DOTTED || style == DASHED)
+            return false;
+
+        if (style == DOUBLE)
+            return width >= 5 * scale; // The outer band needs to be >= 2px wide at unit scale.
+
+        return true;
+    }
 
     int usedWidth() const { return isPresent ? width : 0; }
     
@@ -1098,6 +1097,30 @@ public:
     bool isPresent;
 };
 
+#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
+static bool borderWillArcInnerEdge(const IntSize& firstRadius, const IntSize& secondRadius)
+{
+    return !firstRadius.isZero() || !secondRadius.isZero();
+}
+
+enum BorderEdgeFlag {
+    TopBorderEdge = 1 << BSTop,
+    RightBorderEdge = 1 << BSRight,
+    BottomBorderEdge = 1 << BSBottom,
+    LeftBorderEdge = 1 << BSLeft,
+    AllBorderEdges = TopBorderEdge | BottomBorderEdge | LeftBorderEdge | RightBorderEdge
+};
+
+static inline BorderEdgeFlag edgeFlagForSide(BoxSide side)
+{
+    return static_cast<BorderEdgeFlag>(1 << side);
+}
+
+static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side)
+{
+    return flags & edgeFlagForSide(side);
+}
+
 inline bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge)
 {
     return firstEdge.color == secondEdge.color;
@@ -1207,7 +1230,7 @@ static bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEd
 
 void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
     const IntRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path, 
-    bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+    BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
 {
     const BorderEdge& edgeToRender = edges[side];
     const BorderEdge& adjacentEdge1 = edges[adjacentSide1];
@@ -1225,7 +1248,8 @@ void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext,
         graphicsContext->save();
         clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, adjacentSide1StylesMatch, adjacentSide2StylesMatch);
         float thickness = max(max(edgeToRender.width, adjacentEdge1.width), adjacentEdge2.width);
-        drawBoxSideFromPath(graphicsContext, outerBorder.rect(), *path, edges, edgeToRender.width, thickness, side, style, colorToPaint, edgeToRender.style, includeLogicalLeftEdge, includeLogicalRightEdge);
+        drawBoxSideFromPath(graphicsContext, outerBorder.rect(), *path, edges, edgeToRender.width, thickness, side, style,
+            colorToPaint, edgeToRender.style, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
         graphicsContext->restore();
     } else {
         bool didClip = false;
@@ -1248,7 +1272,8 @@ void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext,
 }
 
 void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
-                                            const BorderEdge edges[], BorderEdgeFlags edgeSet, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+                                            const BorderEdge edges[], BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance,
+                                            bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
 {
     bool renderRadii = outerBorder.isRounded();
 
@@ -1261,7 +1286,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
         sideRect.setHeight(edges[BSTop].width);
 
         bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight()));
-        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
     }
 
     if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) {
@@ -1269,7 +1294,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
         sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width);
 
         bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight()));
-        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
     }
 
     if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) {
@@ -1277,7 +1302,7 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
         sideRect.setWidth(edges[BSLeft].width);
 
         bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft()));
-        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
     }
 
     if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) {
@@ -1285,12 +1310,12 @@ void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, co
         sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width);
 
         bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight()));
-        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
     }
 }
 
 void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
-                                                       const BorderEdge edges[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
+                                                       const BorderEdge edges[], BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
 {
     BorderEdgeFlags edgesToDraw = AllBorderEdges;
     while (edgesToDraw) {
@@ -1320,7 +1345,7 @@ void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphics
             commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue());
         }
 
-        paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, commonColorEdgeSet, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
+        paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, commonColorEdgeSet, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
             
         if (useTransparencyLayer)
             graphicsContext->endTransparencyLayer();
@@ -1330,42 +1355,17 @@ void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphics
 }
 
 void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
-                                       const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+                                       const RenderStyle* style, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
 {
+    // border-image is not affected by border-radius.
     if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
         return;
 
     if (graphicsContext->paintingDisabled())
         return;
 
-    bool horizontal = style->isHorizontalWritingMode();
-
-    BorderEdge edges[4] = {
-        // BSTop
-        BorderEdge(style->borderTopWidth(),
-                    style->visitedDependentColor(CSSPropertyBorderTopColor),
-                    style->borderTopStyle(),
-                    style->borderTopIsTransparent(),
-                    horizontal || includeLogicalLeftEdge),
-        // BSRight
-        BorderEdge(style->borderRightWidth(),
-                    style->visitedDependentColor(CSSPropertyBorderRightColor),
-                    style->borderRightStyle(),
-                    style->borderRightIsTransparent(),
-                    !horizontal || includeLogicalRightEdge),
-        // BSBottom
-        BorderEdge(style->borderBottomWidth(),
-                    style->visitedDependentColor(CSSPropertyBorderBottomColor),
-                    style->borderBottomStyle(),
-                    style->borderBottomIsTransparent(),
-                    horizontal || includeLogicalRightEdge),
-        // BSLeft
-        BorderEdge(style->borderLeftWidth(),
-                    style->visitedDependentColor(CSSPropertyBorderLeftColor),
-                    style->borderLeftStyle(),
-                    style->borderLeftIsTransparent(),
-                    !horizontal || includeLogicalLeftEdge)
-    };
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges, includeLogicalLeftEdge, includeLogicalRightEdge);
 
     IntRect borderRect(tx, ty, w, h);
     RoundedIntRect outerBorder = style->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
@@ -1409,8 +1409,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
         if (outerBorder.isRounded() || haveAlphaColor) {
             Path path;
             
-            // FIXME: Path should take a RoundedIntRect directly.
-            if (outerBorder.isRounded())
+            if (outerBorder.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
                 path.addRoundedRect(outerBorder);
             else
                 path.addRect(outerBorder.rect());
@@ -1424,7 +1423,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
             graphicsContext->setFillColor(edges[firstVisibleEdge].color, style->colorSpace());
             graphicsContext->fillPath(path);
         } else
-            paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+            paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
     
         return;
     }
@@ -1432,14 +1431,15 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
     if (outerBorder.isRounded()) {
         // Clip to the inner and outer radii rects.
         graphicsContext->save();
-        graphicsContext->addRoundedRectClip(outerBorder);
+        if (bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+            graphicsContext->addRoundedRectClip(outerBorder);
         graphicsContext->clipOutRoundedRect(innerBorder);
     }
 
     if (haveAlphaColor)
-        paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+        paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
     else
-        paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+        paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
 
     if (outerBorder.isRounded()) 
         graphicsContext->restore();
@@ -1447,7 +1447,7 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
 
 void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const IntRect& borderRect, const Path& borderPath, const BorderEdge edges[],
                                     float thickness, float drawThickness, BoxSide side, const RenderStyle* style, 
-                                    Color color, EBorderStyle borderStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+                                    Color color, EBorderStyle borderStyle, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
 {
     if (thickness <= 0)
         return;
@@ -1526,18 +1526,26 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext,
             includeLogicalLeftEdge, includeLogicalRightEdge);
         
         graphicsContext->addRoundedRectClip(innerClip);
-        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, includeLogicalLeftEdge, includeLogicalRightEdge);
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
         graphicsContext->restore();
 
         // Draw outer border line
         graphicsContext->save();
-        
-        RoundedIntRect outerClip = style->getRoundedInnerBorderFor(borderRect,
+
+        IntRect outerRect = borderRect;
+        if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+            outerRect.inflate(1);
+            ++outerBorderTopWidth;
+            ++outerBorderBottomWidth;
+            ++outerBorderLeftWidth;
+            ++outerBorderRightWidth;
+        }
+            
+        RoundedIntRect outerClip = style->getRoundedInnerBorderFor(outerRect,
             outerBorderTopWidth, outerBorderBottomWidth, outerBorderLeftWidth, outerBorderRightWidth,
             includeLogicalLeftEdge, includeLogicalRightEdge);
-        
         graphicsContext->clipOutRoundedRect(outerClip);
-        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, includeLogicalLeftEdge, includeLogicalRightEdge);
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
         graphicsContext->restore();
         return;
     }
@@ -1555,7 +1563,7 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext,
         }
         
         // Paint full border
-        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s1, includeLogicalLeftEdge, includeLogicalRightEdge);
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s1, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
 
         // Paint inner only
         graphicsContext->save();
@@ -1570,7 +1578,7 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext,
             includeLogicalLeftEdge, includeLogicalRightEdge);
 
         graphicsContext->addRoundedRectClip(clipRect);
-        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s2, includeLogicalLeftEdge, includeLogicalRightEdge);
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s2, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
         graphicsContext->restore();
         return;
     }
@@ -1592,7 +1600,7 @@ void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext,
 }
 #else
 void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
-                                       const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+                                       const RenderStyle* style, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
 {
     // FIXME: This old version of paintBorder should be removed when all ports implement 
     // GraphicsContext::clipConvexPolygon()!! This should happen soon.
@@ -2046,6 +2054,52 @@ void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContex
     graphicsContext->clipConvexPolygon(4, secondQuad, !secondEdgeMatches);
 }
 
+void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    const RenderStyle* style = this->style();
+    bool horizontal = style->isHorizontalWritingMode();
+
+    edges[BSTop] = BorderEdge(style->borderTopWidth(),
+        style->visitedDependentColor(CSSPropertyBorderTopColor),
+        style->borderTopStyle(),
+        style->borderTopIsTransparent(),
+        horizontal || includeLogicalLeftEdge);
+
+    edges[BSRight] = BorderEdge(style->borderRightWidth(),
+        style->visitedDependentColor(CSSPropertyBorderRightColor),
+        style->borderRightStyle(),
+        style->borderRightIsTransparent(),
+        !horizontal || includeLogicalRightEdge);
+
+    edges[BSBottom] = BorderEdge(style->borderBottomWidth(),
+        style->visitedDependentColor(CSSPropertyBorderBottomColor),
+        style->borderBottomStyle(),
+        style->borderBottomIsTransparent(),
+        horizontal || includeLogicalRightEdge);
+
+    edges[BSLeft] = BorderEdge(style->borderLeftWidth(),
+        style->visitedDependentColor(CSSPropertyBorderLeftColor),
+        style->borderLeftStyle(),
+        style->borderLeftIsTransparent(),
+        !horizontal || includeLogicalLeftEdge);
+}
+
+bool RenderBoxModelObject::borderObscuresBackgroundEdge(const FloatSize& contextScale) const
+{
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges);
+
+    for (int i = BSTop; i <= BSLeft; ++i) {
+        const BorderEdge& currEdge = edges[i];
+        // FIXME: for vertical text
+        float axisScale = (i == BSTop || i == BSBottom) ? contextScale.height() : contextScale.width();
+        if (!currEdge.obscuresBackgroundEdge(axisScale))
+            return false;
+    }
+
+    return true;
+}
+
 static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset)
 {
     IntRect bounds(holeRect);
@@ -2082,6 +2136,10 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int
         IntSize shadowOffset(shadow->x(), shadow->y());
         int shadowBlur = shadow->blur();
         int shadowSpread = shadow->spread();
+        
+        if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
+            continue;
+        
         const Color& shadowColor = shadow->color();
 
         if (shadow->style() == Normal) {
index d2f5972..87311b3 100644 (file)
@@ -34,6 +34,12 @@ enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes };
 enum LineDirectionMode { HorizontalLine, VerticalLine };
 typedef unsigned BorderEdgeFlags;
 
+enum BackgroundBleedAvoidance {
+    BackgroundBleedNone,
+    BackgroundBleedShrinkBackground,
+    BackgroundBleedUseTransparencyLayer
+};
+
 // This class is the base for all objects that adhere to the CSS box model as described
 // at http://www.w3.org/TR/CSS21/box.html
 
@@ -112,10 +118,10 @@ public:
 
     virtual void childBecameNonInline(RenderObject* /*child*/) { }
 
-    void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
+    void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
     bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
     void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
-    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, int inlineBoxWidth = 0, int inlineBoxHeight = 0, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, BackgroundBleedAvoidance, InlineFlowBox* = 0, int inlineBoxWidth = 0, int inlineBoxHeight = 0, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
     
     // Overridden by subclasses to determine line height and baseline position.
     virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
@@ -129,12 +135,14 @@ public:
     virtual void setSelectionState(SelectionState s);
 protected:
     void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
+    void getBorderEdgeInfo(class BorderEdge[], bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+    bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
 
     bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const IntSize&);
 
     RenderBoxModelObject* continuation() const;
     void setContinuation(RenderBoxModelObject*);
-    
+
 private:
     virtual bool isBoxModelObject() const { return true; }
 
@@ -147,14 +155,15 @@ private:
                                BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
     void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
                                 const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[],
-                                const Path*, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
+                                const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
     void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
-                          const class BorderEdge[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
+                          const class BorderEdge[], BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
     void paintBorderSides(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
-                          const class BorderEdge[], BorderEdgeFlags, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
+                          const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
+                          bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
     void drawBoxSideFromPath(GraphicsContext*, const IntRect&, const Path&, const class BorderEdge[],
                             float thickness, float drawThickness, BoxSide, const RenderStyle*, 
-                            Color, EBorderStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
+                            Color, EBorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
 
     friend class RenderView;
 
index 8c65314..e13da3f 100644 (file)
@@ -177,7 +177,7 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
         graphicsContext->clipOut(IntRect(clipLeft, ty + legend->y(), clipWidth, legend->height()));
     }
 
-    paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);
+    paintBorder(paintInfo.context, tx, ty, w, h, style());
 
     graphicsContext->restore();
 }
index ef597c1..f8a3899 100644 (file)
@@ -994,7 +994,7 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i
             paintInfo.context->save();
             paintInfo.context->clip(clipRect);
         }
-        paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h, CompositeSourceOver, backgroundObject);
+        paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h, BackgroundBleedNone, CompositeSourceOver, backgroundObject);
         if (shouldClip)
             paintInfo.context->restore();
     }