2011-01-30 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2011 06:02:01 +0000 (06:02 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2011 06:02:01 +0000 (06:02 +0000)
        Reviewed by Sam Weinig.

        Enhance ShadowBlur to render inset box shadows
        https://bugs.webkit.org/show_bug.cgi?id=51567

        Use ShadowBlur for inset box-shadows with CG. It
        currently lacks a tiled version, but is still much
        faster than CG shadows.

        Test: fast/box-shadow/inset-box-shadow-radius.html

        * platform/graphics/ShadowBlur.cpp:
        * platform/graphics/ShadowBlur.h: New method for inset
        shadows.
        (WebCore::ShadowBlur::drawInsetShadow):

        * platform/graphics/GraphicsContext.cpp: #ifdef out
        fillRectWithRoundedHole() for CG.

        * platform/graphics/cg/GraphicsContextCG.cpp:
        (WebCore::GraphicsContext::fillRectWithRoundedHole): If there's
        a shadow with a radius > 0, use ShadowBlur.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/box-shadow/inset-box-shadow-radius.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/box-shadow/inset-expected.checksum
LayoutTests/platform/mac/fast/box-shadow/inset-expected.png
LayoutTests/platform/mac/fast/css/shadow-multiple-expected.checksum
LayoutTests/platform/mac/fast/css/shadow-multiple-expected.png
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsContext.cpp
Source/WebCore/platform/graphics/ShadowBlur.cpp
Source/WebCore/platform/graphics/ShadowBlur.h
Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

index 4d74701..5bcddb2 100644 (file)
@@ -1,3 +1,22 @@
+2011-01-30  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Enhance ShadowBlur to render inset box shadows
+        https://bugs.webkit.org/show_bug.cgi?id=51567
+        
+        New test for inset shadow radius, and pixel results updated on tests
+        whose results are affected by using ShadowBlur rather than CG.
+
+        * fast/box-shadow/inset-box-shadow-radius.html: Added.
+        * platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.checksum: Added.
+        * platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.png: Added.
+        * platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.txt: Added.
+        * platform/mac/fast/box-shadow/inset-expected.checksum:
+        * platform/mac/fast/box-shadow/inset-expected.png:
+        * platform/mac/fast/css/shadow-multiple-expected.checksum:
+        * platform/mac/fast/css/shadow-multiple-expected.png:
+
 2011-01-28  Kenneth Russell  <kbr@google.com>
 
         Reviewed by Chris Marrin.
diff --git a/LayoutTests/fast/box-shadow/inset-box-shadow-radius.html b/LayoutTests/fast/box-shadow/inset-box-shadow-radius.html
new file mode 100644 (file)
index 0000000..e626016
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .wrapper {
+      outline: 1px solid black;
+      width: 280px;
+      height: 280px;
+      -webkit-box-sizing: border-box;
+      margin: 4px;
+      display: inline-block;
+    }
+    
+    .box {
+      position: relative;
+      width: 280px;
+      height: 280px;
+      display: inline-block;
+    }
+        
+    .indicator {
+      position: absolute;
+      width: 280px;
+      height: 280px;
+      -webkit-box-sizing: border-box;
+      border: 0 solid rgba(0, 255, 0, 0.05);
+    }
+    
+  </style>
+</head>
+<body>
+  
+  <!-- The extent of the shadow should approximately match the pale green boxes. -->
+  <div class="wrapper">
+    <div class="indicator box" style="border-width: 10px"></div>
+    <div class="box" style="box-shadow: 0 0 10px black inset"></div>
+  </div>
+
+  <div class="wrapper">
+    <div class="indicator box" style="border-width: 20px"></div>
+    <div class="box" style="box-shadow: 0 0 20px black inset"></div>
+  </div>
+  <br>
+
+  <div class="wrapper">
+    <div class="indicator box" style="border-width: 50px"></div>
+    <div class="box" style="box-shadow: 0 0 50px black inset"></div>
+  </div>
+
+  <div class="wrapper">
+    <div class="indicator box" style="border-width: 90px"></div>
+    <div class="box" style="box-shadow: 0 0 90px black inset"></div>
+  </div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.checksum b/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.checksum
new file mode 100644 (file)
index 0000000..5dd208a
--- /dev/null
@@ -0,0 +1 @@
+f2f5929911d4db695f6e5cea09899adf
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.png b/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.png
new file mode 100644 (file)
index 0000000..94ad7c4
Binary files /dev/null and b/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.txt b/LayoutTests/platform/mac/fast/box-shadow/inset-box-shadow-radius-expected.txt
new file mode 100644 (file)
index 0000000..0947dfe
--- /dev/null
@@ -0,0 +1,37 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x592
+  RenderBlock {HTML} at (0,0) size 800x592
+    RenderBody {BODY} at (8,8) size 784x576
+      RenderBlock {DIV} at (4,4) size 280x280
+        RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (288,270) size 4x18
+        text run at (288,270) width 4: " "
+      RenderBlock {DIV} at (296,4) size 280x280
+        RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (580,270) size 4x18
+        text run at (580,270) width 4: " "
+      RenderBR {BR} at (0,0) size 0x0
+      RenderBlock {DIV} at (4,292) size 280x280
+        RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (288,558) size 4x18
+        text run at (288,558) width 4: " "
+      RenderBlock {DIV} at (296,292) size 280x280
+        RenderText {#text} at (0,0) size 0x0
+      RenderText {#text} at (0,0) size 0x0
+layer at (12,12) size 280x280
+  RenderBlock (positioned) {DIV} at (12,12) size 280x280 [border: (10px solid #00FF000C)]
+layer at (12,12) size 280x280
+  RenderBlock (relative positioned) {DIV} at (0,0) size 280x280
+layer at (304,12) size 280x280
+  RenderBlock (positioned) {DIV} at (304,12) size 280x280 [border: (20px solid #00FF000C)]
+layer at (304,12) size 280x280
+  RenderBlock (relative positioned) {DIV} at (0,0) size 280x280
+layer at (12,300) size 280x280
+  RenderBlock (positioned) {DIV} at (12,300) size 280x280 [border: (50px solid #00FF000C)]
+layer at (12,300) size 280x280
+  RenderBlock (relative positioned) {DIV} at (0,0) size 280x280
+layer at (304,300) size 280x280
+  RenderBlock (positioned) {DIV} at (304,300) size 280x280 [border: (90px solid #00FF000C)]
+layer at (304,300) size 280x280
+  RenderBlock (relative positioned) {DIV} at (0,0) size 280x280
index f919535..85fffb8 100644 (file)
@@ -1 +1 @@
-922ba5683c7767e6abd3737835212336
\ No newline at end of file
+2f04453f3108bc8a47b5e6906bb09997
\ No newline at end of file
index d095738..f9175c5 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 706fb92..88f49a3 100644 (file)
@@ -1 +1 @@
-ec621f0c3fad619a9ce512be72345138
\ No newline at end of file
+3915900ef91f193c987bdeb2a1e8e030
\ No newline at end of file
index a55fd62..4ce88a5 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/css/shadow-multiple-expected.png and b/LayoutTests/platform/mac/fast/css/shadow-multiple-expected.png differ
index 592bbc6..0bc9714 100644 (file)
@@ -1,3 +1,28 @@
+2011-01-30  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Enhance ShadowBlur to render inset box shadows
+        https://bugs.webkit.org/show_bug.cgi?id=51567
+        
+        Use ShadowBlur for inset box-shadows with CG. It 
+        currently lacks a tiled version, but is still much
+        faster than CG shadows.
+
+        Test: fast/box-shadow/inset-box-shadow-radius.html
+
+        * platform/graphics/ShadowBlur.cpp:
+        * platform/graphics/ShadowBlur.h: New method for inset
+        shadows.
+        (WebCore::ShadowBlur::drawInsetShadow): 
+
+        * platform/graphics/GraphicsContext.cpp: #ifdef out
+        fillRectWithRoundedHole() for CG.
+
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::fillRectWithRoundedHole): If there's
+        a shadow with a radius > 0, use ShadowBlur.
+
 2011-01-28  Kenneth Russell  <kbr@google.com>
 
         Reviewed by Chris Marrin.
index 20971e7..298a89d 100644 (file)
@@ -610,6 +610,7 @@ void GraphicsContext::fillRoundedRect(const RoundedIntRect& rect, const Color& c
     fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color, colorSpace);
 }
 
+#if !PLATFORM(CG)
 void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
 {
     if (paintingDisabled())
@@ -635,6 +636,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
     setFillRule(oldFillRule);
     setFillColor(oldFillColor, oldFillColorSpace);
 }
+#endif
 
 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation)
 {
index c6033d9..ac9e775 100644 (file)
@@ -407,6 +407,24 @@ void ShadowBlur::drawRectShadow(GraphicsContext* graphicsContext, const FloatRec
     drawRectShadowWithTiling(graphicsContext, shadowedRect, radii, 1, shadowTemplateSize);
 }
 
+void ShadowBlur::drawInsetShadow(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii)
+{
+    // FIXME: add a tiling code path here.
+    GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, rect);
+    if (!shadowContext)
+        return;
+
+    Path path;
+    path.addRect(rect);
+    path.addRoundedRect(holeRect, holeRadii.topLeft(), holeRadii.topRight(), holeRadii.bottomLeft(), holeRadii.bottomRight());
+
+    shadowContext->setFillRule(RULE_EVENODD);
+    shadowContext->setFillColor(Color(.0f, .0f, .0f, 1.f), ColorSpaceDeviceRGB);
+    shadowContext->fillPath(path);
+    
+    endShadowLayer(graphicsContext);
+}
+
 void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, float alpha)
 {
     GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, shadowedRect);
index a93eb4d..e96c992 100644 (file)
@@ -49,6 +49,7 @@ public:
     bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
 
     void drawRectShadow(GraphicsContext*, const FloatRect&, const RoundedIntRect::Radii&);
+    void drawInsetShadow(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii);
 
 private:
     GraphicsContext* beginShadowLayer(GraphicsContext*, const FloatRect& layerArea);
index cbf467d..b4acd0f 100644 (file)
@@ -745,6 +745,50 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
         setCGFillColor(context, oldFillColor, oldColorSpace);
 }
 
+void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
+{
+    if (paintingDisabled())
+        return;
+
+    CGContextRef context = platformContext();
+
+    Path path;
+    path.addRect(rect);
+
+    if (!roundedHoleRect.radii().isZero())
+        path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+    else
+        path.addRect(roundedHoleRect.rect());
+
+    WindRule oldFillRule = fillRule();
+    Color oldFillColor = fillColor();
+    ColorSpace oldFillColorSpace = fillColorSpace();
+    
+    setFillRule(RULE_EVENODD);
+    setFillColor(color, colorSpace);
+
+    // fillRectWithRoundedHole() assumes that the edges of rect are clipped out, so we only care about shadows cast around inside the hole.
+    bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms;
+    if (drawOwnShadow) {
+        float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+
+        // Turn off CG shadows.
+        CGContextSaveGState(context);
+        CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+        ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+        contextShadow.drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii());
+    }
+
+    fillPath(path);
+
+    if (drawOwnShadow)
+        CGContextRestoreGState(context);
+    
+    setFillRule(oldFillRule);
+    setFillColor(oldFillColor, oldFillColorSpace);
+}
+
 void GraphicsContext::clip(const FloatRect& rect)
 {
     if (paintingDisabled())