[CSS Blending]The background images set on the root element will blend on an initial...
authorrosca@adobe.com <rosca@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 7 Jul 2014 07:16:04 +0000 (07:16 +0000)
committerrosca@adobe.com <rosca@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 7 Jul 2014 07:16:04 +0000 (07:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134342

Reviewed by Dean Jackson.

Source/WebCore:
Tests: css3/blending/background-blend-mode-body-image.html
       css3/blending/background-blend-mode-body-transparent-color-and-image.html
       css3/blending/background-blend-mode-body-transparent-image.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::paintFillLayers):
If the background layers have blend modes, we paint the base background color first,
before starting a new transparency layer. After creating the transparency layer,
the base background will be skipped, and the background layers will blend on top of
a transparent backdrop.
(WebCore::RenderBox::paintFillLayer):
* rendering/RenderBox.h:
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintFillLayerExtended):
This method is able to paint only the base background color (BaseBackgroundColorOnly),
skipping the background-color and background-images. This option is available only
on bottom layer of the root renderer and only if the background color is not opaque,
otherwise the method will return early.
Another option is to paint the root background without using the base background color
(BaseBackgroundColorSkip).
* rendering/RenderBoxModelObject.h:
Adding the BaseBackgroundColorUsage enum.

LayoutTests:
* css3/blending/background-blend-mode-body-image-expected.html: Added.
* css3/blending/background-blend-mode-body-image.html: Added.
* css3/blending/background-blend-mode-body-transparent-color-and-image-expected.html: Added.
* css3/blending/background-blend-mode-body-transparent-color-and-image.html: Added.
* css3/blending/background-blend-mode-body-transparent-image-expected.html: Added.
* css3/blending/background-blend-mode-body-transparent-image.html: Added.

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/blending/background-blend-mode-body-image-expected.html [new file with mode: 0644]
LayoutTests/css3/blending/background-blend-mode-body-image.html [new file with mode: 0644]
LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image-expected.html [new file with mode: 0644]
LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image.html [new file with mode: 0644]
LayoutTests/css3/blending/background-blend-mode-body-transparent-image-expected.html [new file with mode: 0644]
LayoutTests/css3/blending/background-blend-mode-body-transparent-image.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderBoxModelObject.h

index 98fafb2..0b78442 100644 (file)
@@ -1,3 +1,17 @@
+2014-07-07  Ion Rosca  <rosca@adobe.com>
+
+        [CSS Blending]The background images set on the root element will blend on an initial white backdrop.
+        https://bugs.webkit.org/show_bug.cgi?id=134342
+
+        Reviewed by Dean Jackson.
+
+        * css3/blending/background-blend-mode-body-image-expected.html: Added.
+        * css3/blending/background-blend-mode-body-image.html: Added.
+        * css3/blending/background-blend-mode-body-transparent-color-and-image-expected.html: Added.
+        * css3/blending/background-blend-mode-body-transparent-color-and-image.html: Added.
+        * css3/blending/background-blend-mode-body-transparent-image-expected.html: Added.
+        * css3/blending/background-blend-mode-body-transparent-image.html: Added.
+
 2014-07-06  Yoav Weiss  <yoav@yoav.ws>
 
         Turn on img@sizes compile flag
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-image-expected.html b/LayoutTests/css3/blending/background-blend-mode-body-image-expected.html
new file mode 100644 (file)
index 0000000..bbbcb76
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<style>
+body { 
+       background-color: green;
+}
+</style>
+<p>This test will check that a background-image set on body does not blend with the browser's white     background color.<br/>
+The test passes if the page has a green background.</p>
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-image.html b/LayoutTests/css3/blending/background-blend-mode-body-image.html
new file mode 100644 (file)
index 0000000..431958c
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<style>
+body { 
+       background-image: linear-gradient(green, green);
+       background-blend-mode: screen;
+}
+</style>
+<p>This test will check that a background-image set on body does not blend with the browser's white     background color.<br/>
+The test passes if the page has a green background.</p>
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image-expected.html b/LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image-expected.html
new file mode 100644 (file)
index 0000000..022795e
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<style>
+body, html {
+  height: 100%;
+}
+body {
+       margin: 0px;
+}
+div { 
+       background-image: linear-gradient(green, green);
+       background-color: rgba(255, 0, 0, 0.2);
+       background-blend-mode: screen;
+       height: 100%;
+}
+p {
+       display: inline;
+}
+</style>
+<div>
+       <p>This test will check that a background-image set on body does not blend with the browser's white background color, it will only blend with the red transparent background-color.<br/>
+       The test passes if the page has a green background.</p>
+</div>
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image.html b/LayoutTests/css3/blending/background-blend-mode-body-transparent-color-and-image.html
new file mode 100644 (file)
index 0000000..5f27ff2
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<style>
+body { 
+       background-image: linear-gradient(green, green);
+       background-color: rgba(255, 0, 0, 0.2);
+       background-blend-mode: screen;
+       margin: 0px;
+}
+p {
+       display: inline;
+}
+</style>
+<p>This test will check that a background-image set on body does not blend with the browser's white background color, it will only blend with the red transparent background-color.<br/>
+The test passes if the page has a green background.</p>
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-transparent-image-expected.html b/LayoutTests/css3/blending/background-blend-mode-body-transparent-image-expected.html
new file mode 100644 (file)
index 0000000..4d27259
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<style>
+body { 
+       background-image: linear-gradient(transparent, transparent 10%, green 10%, green 90%, transparent 90%, transparent);
+}
+</style>
+<p>This test will check that a transparent background-image set on body does not blend with the browser's white background color.<br/>
+The test passes if the page has a green background with white horizontal lines.</p>
diff --git a/LayoutTests/css3/blending/background-blend-mode-body-transparent-image.html b/LayoutTests/css3/blending/background-blend-mode-body-transparent-image.html
new file mode 100644 (file)
index 0000000..63757e7
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<style>
+body { 
+       background-image: linear-gradient(transparent, transparent 10%, green 10%, green 90%, transparent 90%, transparent);
+       background-blend-mode: screen;
+}
+</style>
+<p>This test will check that a transparent background-image set on body does not blend with the browser's white background color.<br/>
+The test passes if the page has a green background with white horizontal lines.</p>
index 22c5242..6112af2 100644 (file)
@@ -1,3 +1,33 @@
+2014-07-07  Ion Rosca  <rosca@adobe.com>
+
+        [CSS Blending]The background images set on the root element will blend on an initial white backdrop.
+        https://bugs.webkit.org/show_bug.cgi?id=134342
+
+        Reviewed by Dean Jackson.
+
+        Tests: css3/blending/background-blend-mode-body-image.html
+               css3/blending/background-blend-mode-body-transparent-color-and-image.html
+               css3/blending/background-blend-mode-body-transparent-image.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintFillLayers):
+        If the background layers have blend modes, we paint the base background color first,
+        before starting a new transparency layer. After creating the transparency layer,
+        the base background will be skipped, and the background layers will blend on top of
+        a transparent backdrop.
+        (WebCore::RenderBox::paintFillLayer):
+        * rendering/RenderBox.h:
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        This method is able to paint only the base background color (BaseBackgroundColorOnly), 
+        skipping the background-color and background-images. This option is available only
+        on bottom layer of the root renderer and only if the background color is not opaque,
+        otherwise the method will return early.
+        Another option is to paint the root background without using the base background color
+        (BaseBackgroundColorSkip).
+        * rendering/RenderBoxModelObject.h:
+        Adding the BaseBackgroundColorUsage enum.
+
 2014-07-06  Yoav Weiss  <yoav@yoav.ws>
 
         Turn on img@sizes compile flag
index 121c719..d919b1a 100644 (file)
@@ -1565,21 +1565,27 @@ void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, cons
     GraphicsContext* context = paintInfo.context;
     if (!context)
         shouldDrawBackgroundInSeparateBuffer = false;
-    if (shouldDrawBackgroundInSeparateBuffer)
+
+    BaseBackgroundColorUsage baseBgColorUsage = BaseBackgroundColorUse;
+
+    if (shouldDrawBackgroundInSeparateBuffer) {
+        paintFillLayer(paintInfo, c, *layers.rbegin(), rect, bleedAvoidance, op, backgroundObject, BaseBackgroundColorOnly);
+        baseBgColorUsage = BaseBackgroundColorSkip;
         context->beginTransparencyLayer(1);
+    }
 
     Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
     for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
-        paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject);
+        paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject, baseBgColorUsage);
 
     if (shouldDrawBackgroundInSeparateBuffer)
         context->endTransparencyLayer();
 }
 
 void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
-    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject)
+    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
 {
-    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
+    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, baseBgColorUsage);
 }
 
 static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
index e33fb9d..9a1dedf 100644 (file)
@@ -633,7 +633,7 @@ protected:
 
     void paintBackground(const PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone);
     
-    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderElement* backgroundObject);
+    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderElement* backgroundObject, BaseBackgroundColorUsage = BaseBackgroundColorUse);
     void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone, CompositeOperator = CompositeSourceOver, RenderElement* backgroundObject = nullptr);
 
     void paintMaskImages(const PaintInfo&, const LayoutRect&);
index 0f28cc7..f859b4d 100644 (file)
@@ -618,7 +618,7 @@ void RenderBoxModelObject::paintMaskForTextFillBox(ImageBuffer* maskImage, const
 }
 
 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect,
-    BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject)
+    BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderElement* backgroundObject, BaseBackgroundColorUsage baseBgColorUsage)
 {
     GraphicsContext* context = paintInfo.context;
     if (context->paintingDisabled() || rect.isEmpty())
@@ -660,6 +660,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
         }
     }
 
+    bool baseBgColorOnly = (baseBgColorUsage == BaseBackgroundColorOnly);
+    if (baseBgColorOnly && (!isRoot || bgLayer->next() || (bgColor.isValid() && !bgColor.hasAlpha())))
+        return;
+
     bool colorVisible = bgColor.isValid() && bgColor.alpha();
     float deviceScaleFactor = document().deviceScaleFactor();
     FloatRect pixelSnappedRect = pixelSnappedForPainting(rect, deviceScaleFactor);
@@ -801,7 +805,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
             // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
             Color baseColor;
             bool shouldClearBackground = false;
-            if (isOpaqueRoot) {
+            if ((baseBgColorUsage != BaseBackgroundColorSkip) && isOpaqueRoot) {
                 baseColor = view().frameView().baseBackgroundColor();
                 if (!baseColor.alpha())
                     shouldClearBackground = true;
@@ -813,11 +817,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
 
             FloatRect backgroundRectForPainting = pixelSnappedForPainting(backgroundRect, deviceScaleFactor);
             if (baseColor.alpha()) {
-                if (bgColor.alpha())
+                if (!baseBgColorOnly && bgColor.alpha())
                     baseColor = baseColor.blend(bgColor);
 
                 context->fillRect(backgroundRectForPainting, baseColor, style().colorSpace(), CompositeCopy);
-            } else if (bgColor.alpha()) {
+            } else if (!baseBgColorOnly && bgColor.alpha()) {
                 CompositeOperator operation = shouldClearBackground ? CompositeCopy : context->compositeOperation();
                 context->fillRect(backgroundRectForPainting, bgColor, style().colorSpace(), operation);
             } else if (shouldClearBackground)
@@ -826,7 +830,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
     }
 
     // no progressive loading of the background image
-    if (shouldPaintBackgroundImage) {
+    if (!baseBgColorOnly && shouldPaintBackgroundImage) {
         BackgroundImageGeometry geometry;
         calculateBackgroundImageGeometry(paintInfo.paintContainer, bgLayer, scrolledPaintRect, geometry, backgroundObject);
         geometry.clip(LayoutRect(pixelSnappedRect));
index 096b8b9..ace8885 100644 (file)
@@ -41,6 +41,12 @@ enum BackgroundBleedAvoidance {
     BackgroundBleedBackgroundOverBorder
 };
 
+enum BaseBackgroundColorUsage {
+    BaseBackgroundColorUse,
+    BaseBackgroundColorOnly,
+    BaseBackgroundColorSkip
+};
+
 enum ContentChangeType {
     ImageChanged,
     MaskImageChanged,
@@ -170,7 +176,7 @@ public:
     void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle&, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
     bool paintNinePieceImage(GraphicsContext*, const LayoutRect&, const RenderStyle&, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
     void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle&, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
-    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderElement* backgroundObject = 0);
+    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderElement* backgroundObject = 0, BaseBackgroundColorUsage = BaseBackgroundColorUse);
 
     virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox* = 0) const;