2010-09-24 Martin Robinson <mrobinson@igalia.com>
authormrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Oct 2010 19:18:10 +0000 (19:18 +0000)
committermrobinson@webkit.org <mrobinson@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Oct 2010 19:18:10 +0000 (19:18 +0000)
        Reviewed by Dirk Schulze.

        [Cairo] Activate ContextShadow in all places where shadows are drawn
        https://bugs.webkit.org/show_bug.cgi?id=46475

        Rebaselined tests. All these changes seem reasonable. In some cases, the
        new results are much better / closer matches to Chromium.

        * platform/gtk/fast/box-shadow/basic-shadows-expected.checksum:
        * platform/gtk/fast/box-shadow/basic-shadows-expected.png:
        * platform/gtk/fast/box-shadow/inset-expected.checksum:
        * platform/gtk/fast/box-shadow/inset-expected.png:
        * platform/gtk/fast/css/shadow-multiple-expected.checksum:
        * platform/gtk/fast/css/shadow-multiple-expected.png:
        * platform/gtk/fast/text/shadow-no-blur-expected.checksum:
        * platform/gtk/fast/text/shadow-no-blur-expected.png:
        * platform/gtk/fast/text/shadow-translucent-fill-expected.checksum:
        * platform/gtk/fast/text/shadow-translucent-fill-expected.png:
        * platform/gtk/fast/text/stroking-decorations-expected.checksum:
        * platform/gtk/fast/text/stroking-decorations-expected.png:
        * platform/gtk/fast/text/stroking-expected.checksum:
        * platform/gtk/fast/text/stroking-expected.png:
        * platform/gtk/fast/transforms/shadows-expected.checksum:
        * platform/gtk/fast/transforms/shadows-expected.png:
        * platform/gtk/svg/css/arrow-with-shadow-expected.checksum:
        * platform/gtk/svg/css/arrow-with-shadow-expected.png:
        * platform/gtk/svg/css/composite-shadow-text-expected.checksum:
        * platform/gtk/svg/css/composite-shadow-text-expected.png:
        * platform/gtk/svg/css/group-with-shadow-expected.checksum:
        * platform/gtk/svg/css/group-with-shadow-expected.png:
        * platform/gtk/svg/css/path-with-shadow-expected.checksum:
        * platform/gtk/svg/css/path-with-shadow-expected.png:
        * platform/gtk/svg/css/shadow-with-large-radius-expected.checksum:
        * platform/gtk/svg/css/shadow-with-large-radius-expected.png:
        * platform/gtk/svg/css/shadow-with-negative-offset-expected.checksum:
        * platform/gtk/svg/css/shadow-with-negative-offset-expected.png:
2010-10-06  Martin Robinson  <mrobinson@igalia.com>

        Reviewed by Dirk Schulze.

        [Cairo] Activate ContextShadow in all places where shadows are drawn
        https://bugs.webkit.org/show_bug.cgi?id=46475

        Turn on ContextShadow for the Cairo port and remove all old shadow code.
        Shadow tiling optimizations will be added in a followup patch to ContextShadowCairo.

        * platform/graphics/GraphicsContext.h: Add a ContextShadow forward declaration for Cairo.
        * platform/graphics/cairo/FontCairo.cpp: Switch to using ContextShadow.
        (WebCore::prepareContextForGlyphDrawing): Added this helper which sets up the translation
        on the specified cairo_t to prepare for drawing glyphs.
        (WebCore::drawGlyphsToContext): Added this helper which draws the glyphs to a cairo_t,
        while properly handling glyphs with synthetic bold.
        (WebCore::Font::drawGlyphs): Removed old shadow code and replaced it with ContextShadow usage.
        * platform/graphics/cairo/GraphicsContextCairo.cpp:
        (WebCore::drawPathShadow): Modified this to use ContextShadow and to take an enum
        argument specifying whether to fill or stroke the solid figure for the shadow.
        (WebCore::fillCurrentCairoPath): Updated drawPathShadow call.
        (WebCore::strokeCurrentCairoPath): Ditto.
        (WebCore::GraphicsContext::savePlatformState): Save the ContextShadow.
        (WebCore::GraphicsContext::restorePlatformState): Restore the ContextShadow.
        (WebCore::GraphicsContext::drawPath): Updated drawPathShadow call.
        (WebCore::GraphicsContext::fillRect): Uses ContextShadow now.
        (WebCore::GraphicsContext::setPlatformShadow): Uses ContextShadow now.
        (WebCore::GraphicsContext::contextShadow): Added.
        (WebCore::GraphicsContext::clearPlatformShadow): Clears the ContextShadow member.
        (WebCore::GraphicsContext::fillRoundedRect): Updated drawPathShadow call.
        * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h:
        (WebCore::GraphicsContextPlatformPrivate::hasShadow): Added.
        * platform/graphics/cairo/ImageCairo.cpp:
        (WebCore::BitmapImage::draw): Updated to use ContextShadow.

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

63 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/gtk/fast/box-shadow/basic-shadows-expected.checksum
LayoutTests/platform/gtk/fast/box-shadow/basic-shadows-expected.png
LayoutTests/platform/gtk/fast/box-shadow/border-radius-big-expected.checksum
LayoutTests/platform/gtk/fast/box-shadow/border-radius-big-expected.png
LayoutTests/platform/gtk/fast/box-shadow/inset-expected.checksum
LayoutTests/platform/gtk/fast/box-shadow/inset-expected.png
LayoutTests/platform/gtk/fast/box-shadow/spread-expected.checksum
LayoutTests/platform/gtk/fast/box-shadow/spread-expected.png
LayoutTests/platform/gtk/fast/box-shadow/transform-fringing-expected.checksum
LayoutTests/platform/gtk/fast/box-shadow/transform-fringing-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-1-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-1-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-2-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-2-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-3-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-3-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-4-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-4-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-5-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-5-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-6-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-6-expected.png
LayoutTests/platform/gtk/fast/canvas/shadow-offset-7-expected.checksum
LayoutTests/platform/gtk/fast/canvas/shadow-offset-7-expected.png
LayoutTests/platform/gtk/fast/css/shadow-multiple-expected.checksum
LayoutTests/platform/gtk/fast/css/shadow-multiple-expected.png
LayoutTests/platform/gtk/fast/forms/box-shadow-override-expected.checksum
LayoutTests/platform/gtk/fast/forms/box-shadow-override-expected.png
LayoutTests/platform/gtk/fast/text/shadow-translucent-fill-expected.checksum
LayoutTests/platform/gtk/fast/text/shadow-translucent-fill-expected.png
LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.checksum
LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.png
LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.txt
LayoutTests/platform/gtk/fast/text/stroking-expected.checksum
LayoutTests/platform/gtk/fast/text/stroking-expected.png
LayoutTests/platform/gtk/fast/transforms/shadows-expected.checksum
LayoutTests/platform/gtk/fast/transforms/shadows-expected.png
LayoutTests/platform/gtk/svg/css/arrow-with-shadow-expected.checksum
LayoutTests/platform/gtk/svg/css/arrow-with-shadow-expected.png
LayoutTests/platform/gtk/svg/css/composite-shadow-example-expected.checksum
LayoutTests/platform/gtk/svg/css/composite-shadow-example-expected.png
LayoutTests/platform/gtk/svg/css/composite-shadow-text-expected.checksum
LayoutTests/platform/gtk/svg/css/composite-shadow-text-expected.png
LayoutTests/platform/gtk/svg/css/group-with-shadow-expected.checksum
LayoutTests/platform/gtk/svg/css/group-with-shadow-expected.png
LayoutTests/platform/gtk/svg/css/mask-with-shadow-expected.checksum
LayoutTests/platform/gtk/svg/css/mask-with-shadow-expected.png
LayoutTests/platform/gtk/svg/css/path-with-shadow-expected.checksum
LayoutTests/platform/gtk/svg/css/path-with-shadow-expected.png
LayoutTests/platform/gtk/svg/css/shadow-with-large-radius-expected.checksum
LayoutTests/platform/gtk/svg/css/shadow-with-large-radius-expected.png
LayoutTests/platform/gtk/svg/css/shadow-with-negative-offset-expected.checksum
LayoutTests/platform/gtk/svg/css/shadow-with-negative-offset-expected.png
LayoutTests/platform/gtk/svg/css/stars-with-shadow-expected.checksum
LayoutTests/platform/gtk/svg/css/stars-with-shadow-expected.png
WebCore/ChangeLog
WebCore/platform/graphics/ContextShadow.h
WebCore/platform/graphics/GraphicsContext.h
WebCore/platform/graphics/cairo/FontCairo.cpp
WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
WebCore/platform/graphics/cairo/ImageCairo.cpp

index 57d57e0..e6860fb 100644 (file)
@@ -1,3 +1,42 @@
+2010-09-24  Martin Robinson  <mrobinson@igalia.com>
+
+        Reviewed by Dirk Schulze.
+
+        [Cairo] Activate ContextShadow in all places where shadows are drawn
+        https://bugs.webkit.org/show_bug.cgi?id=46475
+
+        Rebaselined tests. All these changes seem reasonable. In some cases, the
+        new results are much better / closer matches to Chromium.
+
+        * platform/gtk/fast/box-shadow/basic-shadows-expected.checksum:
+        * platform/gtk/fast/box-shadow/basic-shadows-expected.png:
+        * platform/gtk/fast/box-shadow/inset-expected.checksum:
+        * platform/gtk/fast/box-shadow/inset-expected.png:
+        * platform/gtk/fast/css/shadow-multiple-expected.checksum:
+        * platform/gtk/fast/css/shadow-multiple-expected.png:
+        * platform/gtk/fast/text/shadow-no-blur-expected.checksum:
+        * platform/gtk/fast/text/shadow-no-blur-expected.png:
+        * platform/gtk/fast/text/shadow-translucent-fill-expected.checksum:
+        * platform/gtk/fast/text/shadow-translucent-fill-expected.png:
+        * platform/gtk/fast/text/stroking-decorations-expected.checksum:
+        * platform/gtk/fast/text/stroking-decorations-expected.png:
+        * platform/gtk/fast/text/stroking-expected.checksum:
+        * platform/gtk/fast/text/stroking-expected.png:
+        * platform/gtk/fast/transforms/shadows-expected.checksum:
+        * platform/gtk/fast/transforms/shadows-expected.png:
+        * platform/gtk/svg/css/arrow-with-shadow-expected.checksum:
+        * platform/gtk/svg/css/arrow-with-shadow-expected.png:
+        * platform/gtk/svg/css/composite-shadow-text-expected.checksum:
+        * platform/gtk/svg/css/composite-shadow-text-expected.png:
+        * platform/gtk/svg/css/group-with-shadow-expected.checksum:
+        * platform/gtk/svg/css/group-with-shadow-expected.png:
+        * platform/gtk/svg/css/path-with-shadow-expected.checksum:
+        * platform/gtk/svg/css/path-with-shadow-expected.png:
+        * platform/gtk/svg/css/shadow-with-large-radius-expected.checksum:
+        * platform/gtk/svg/css/shadow-with-large-radius-expected.png:
+        * platform/gtk/svg/css/shadow-with-negative-offset-expected.checksum:
+        * platform/gtk/svg/css/shadow-with-negative-offset-expected.png:
+
 2010-10-13  Nate Chapin  <japhet@chromium.org>
 
         Unreviewed, Chromium test fix.
index bf4ed66..276b2fe 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/box-shadow/basic-shadows-expected.png and b/LayoutTests/platform/gtk/fast/box-shadow/basic-shadows-expected.png differ
index 98f36c0..2685b12 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/box-shadow/border-radius-big-expected.png and b/LayoutTests/platform/gtk/fast/box-shadow/border-radius-big-expected.png differ
index ac3d7c5..1673726 100644 (file)
@@ -1 +1 @@
-6d342f464b9c3b1b359652690668b018
\ No newline at end of file
+031c0afbbbf2d3d170b1d5ec47340360
\ No newline at end of file
index 12e6d09..5525c8e 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/box-shadow/inset-expected.png and b/LayoutTests/platform/gtk/fast/box-shadow/inset-expected.png differ
index 31cdc78..40e938b 100644 (file)
@@ -1 +1 @@
-725db46a3dfc6bd70efff487e32b54c9
\ No newline at end of file
+47ae516cd0eb09ddb903c4faee42bc6d
\ No newline at end of file
index 060a920..08ad742 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/box-shadow/spread-expected.png and b/LayoutTests/platform/gtk/fast/box-shadow/spread-expected.png differ
index b50bfeb..83c4032 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/box-shadow/transform-fringing-expected.png and b/LayoutTests/platform/gtk/fast/box-shadow/transform-fringing-expected.png differ
index 9f5db3e..414a478 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-1-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-1-expected.png differ
index aae89d3..d69dcd3 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-2-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-2-expected.png differ
index 9f5db3e..414a478 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-3-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-3-expected.png differ
index f3cb63d..5cc8c55 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-4-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-4-expected.png differ
index f3cb63d..5cc8c55 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-5-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-5-expected.png differ
index 49c5e44..e2a2311 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-6-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-6-expected.png differ
index f8cd6e7..d516ceb 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/canvas/shadow-offset-7-expected.png and b/LayoutTests/platform/gtk/fast/canvas/shadow-offset-7-expected.png differ
index d259d07..dcd2f3d 100644 (file)
@@ -1 +1 @@
-701fabbd3a807c01bb522ec6f2d85122
\ No newline at end of file
+c5e2b47412e5f8bd9d491052823d7ffa
\ No newline at end of file
index 7a0a628..9fccb28 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/css/shadow-multiple-expected.png and b/LayoutTests/platform/gtk/fast/css/shadow-multiple-expected.png differ
index de32e48..25c4ee0 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/forms/box-shadow-override-expected.png and b/LayoutTests/platform/gtk/fast/forms/box-shadow-override-expected.png differ
index 46f2d66..97cc2f0 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/text/shadow-translucent-fill-expected.png and b/LayoutTests/platform/gtk/fast/text/shadow-translucent-fill-expected.png differ
index 6eaf508..f7f33ea 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.png and b/LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.png differ
index 36ff13b..c79cca4 100644 (file)
@@ -3,15 +3,15 @@ layer at (0,0) size 800x600
 layer at (0,0) size 800x600
   RenderBlock {HTML} at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
-      RenderBlock {DIV} at (0,0) size 784x156 [textFillColor=#800080] [textStrokeWidth=2.00]
-        RenderText {#text} at (0,0) size 759x156
-          text run at (0,0) width 690: "Purple\x{300} fill, black stroke,"
-          text run at (0,78) width 759: "complex text, black underline"
-      RenderBlock {DIV} at (0,156) size 784x156 [textStrokeColor=#FFA500] [textStrokeWidth=1.33]
-        RenderText {#text} at (0,0) size 636x156
-          text run at (0,0) width 636: "Orange stroke, black fill,"
-          text run at (0,78) width 414: "orange overline."
-      RenderBlock {DIV} at (0,312) size 784x156 [textFillColor=#0000FF] [textStrokeWidth=1.33]
-        RenderText {#text} at (0,0) size 596x156
-          text run at (0,0) width 596: "No stroke, blue fill, red"
-          text run at (0,78) width 594: "shadow, blue underline"
+      RenderBlock {DIV} at (0,0) size 784x148 [textFillColor=#800080] [textStrokeWidth=2.00]
+        RenderText {#text} at (0,1) size 755x146
+          text run at (0,1) width 616: "Purple\x{300} fill, black stroke,"
+          text run at (0,75) width 755: "complex text, black underline"
+      RenderBlock {DIV} at (0,148) size 784x148 [textStrokeColor=#FFA500] [textStrokeWidth=1.33]
+        RenderText {#text} at (0,1) size 633x146
+          text run at (0,1) width 633: "Orange stroke, black fill,"
+          text run at (0,75) width 412: "orange overline."
+      RenderBlock {DIV} at (0,296) size 784x148 [textFillColor=#0000FF] [textStrokeWidth=1.33]
+        RenderText {#text} at (0,1) size 593x146
+          text run at (0,1) width 593: "No stroke, blue fill, red"
+          text run at (0,75) width 592: "shadow, blue underline"
index 70f66ad..425a7d0 100644 (file)
@@ -1 +1 @@
-9bda69d71f92b48dcbeadbc97d4aa314
\ No newline at end of file
+1dbe4580c4247c66169215a291f01784
\ No newline at end of file
index 17fed76..54db7e9 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/text/stroking-expected.png and b/LayoutTests/platform/gtk/fast/text/stroking-expected.png differ
index 98d2974..6677973 100644 (file)
@@ -1 +1 @@
-53b5647f358b53516a2971cef984ef43
\ No newline at end of file
+643ebb3d9f814c590c1360ee8780a711
\ No newline at end of file
index fd0efa2..a0791bc 100644 (file)
Binary files a/LayoutTests/platform/gtk/fast/transforms/shadows-expected.png and b/LayoutTests/platform/gtk/fast/transforms/shadows-expected.png differ
index 231713f..dae89e4 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/arrow-with-shadow-expected.png and b/LayoutTests/platform/gtk/svg/css/arrow-with-shadow-expected.png differ
index 047fb29..da6fceb 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/composite-shadow-example-expected.png and b/LayoutTests/platform/gtk/svg/css/composite-shadow-example-expected.png differ
index d3512c1..be15098 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/composite-shadow-text-expected.png and b/LayoutTests/platform/gtk/svg/css/composite-shadow-text-expected.png differ
index 2fc11e0..262467f 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/group-with-shadow-expected.png and b/LayoutTests/platform/gtk/svg/css/group-with-shadow-expected.png differ
index 209c85a..698e251 100644 (file)
@@ -1 +1 @@
-95a13b575496a68e7be1e244fc085917
\ No newline at end of file
+fccfdd6c1ec02071e92cf8d3e4e055a4
\ No newline at end of file
index aa99f16..91f619b 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/mask-with-shadow-expected.png and b/LayoutTests/platform/gtk/svg/css/mask-with-shadow-expected.png differ
index 0250727..05039e3 100644 (file)
@@ -1 +1 @@
-5d5b77a6e165e0386e1ed99ca462e546
\ No newline at end of file
+32a221a08c690feca7b5f130b0f2b878
\ No newline at end of file
index 978165e..fda258c 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/path-with-shadow-expected.png and b/LayoutTests/platform/gtk/svg/css/path-with-shadow-expected.png differ
index 13cb0d9..5457ca9 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/shadow-with-large-radius-expected.png and b/LayoutTests/platform/gtk/svg/css/shadow-with-large-radius-expected.png differ
index 328e2d7..e1bdaa7 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/shadow-with-negative-offset-expected.png and b/LayoutTests/platform/gtk/svg/css/shadow-with-negative-offset-expected.png differ
index 43e58d0..328adf8 100644 (file)
Binary files a/LayoutTests/platform/gtk/svg/css/stars-with-shadow-expected.png and b/LayoutTests/platform/gtk/svg/css/stars-with-shadow-expected.png differ
index 0882724..1a1e6e5 100644 (file)
@@ -1,3 +1,38 @@
+2010-10-06  Martin Robinson  <mrobinson@igalia.com>
+
+        Reviewed by Dirk Schulze.
+
+        [Cairo] Activate ContextShadow in all places where shadows are drawn
+        https://bugs.webkit.org/show_bug.cgi?id=46475
+
+        Turn on ContextShadow for the Cairo port and remove all old shadow code.
+        Shadow tiling optimizations will be added in a followup patch to ContextShadowCairo.
+
+        * platform/graphics/GraphicsContext.h: Add a ContextShadow forward declaration for Cairo.
+        * platform/graphics/cairo/FontCairo.cpp: Switch to using ContextShadow.
+        (WebCore::prepareContextForGlyphDrawing): Added this helper which sets up the translation
+        on the specified cairo_t to prepare for drawing glyphs.
+        (WebCore::drawGlyphsToContext): Added this helper which draws the glyphs to a cairo_t,
+        while properly handling glyphs with synthetic bold.
+        (WebCore::Font::drawGlyphs): Removed old shadow code and replaced it with ContextShadow usage.
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::drawPathShadow): Modified this to use ContextShadow and to take an enum
+        argument specifying whether to fill or stroke the solid figure for the shadow.
+        (WebCore::fillCurrentCairoPath): Updated drawPathShadow call.
+        (WebCore::strokeCurrentCairoPath): Ditto.
+        (WebCore::GraphicsContext::savePlatformState): Save the ContextShadow.
+        (WebCore::GraphicsContext::restorePlatformState): Restore the ContextShadow.
+        (WebCore::GraphicsContext::drawPath): Updated drawPathShadow call.
+        (WebCore::GraphicsContext::fillRect): Uses ContextShadow now.
+        (WebCore::GraphicsContext::setPlatformShadow): Uses ContextShadow now.
+        (WebCore::GraphicsContext::contextShadow): Added.
+        (WebCore::GraphicsContext::clearPlatformShadow): Clears the ContextShadow member.
+        (WebCore::GraphicsContext::fillRoundedRect): Updated drawPathShadow call.
+        * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h:
+        (WebCore::GraphicsContextPlatformPrivate::hasShadow): Added.
+        * platform/graphics/cairo/ImageCairo.cpp:
+        (WebCore::BitmapImage::draw): Updated to use ContextShadow.
+
 2010-10-13  John Knottenbelt  <jknotten@chromium.org>
 
         Reviewed by Steve Block.
index a396cbe..0160f8a 100644 (file)
@@ -100,7 +100,7 @@ public:
     void endShadowLayer(PlatformContext);
     static void purgeScratchBuffer();
 #if PLATFORM(CAIRO)
-    void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius);
+    void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
 #endif
 
 #if PLATFORM(QT)
index 4d55e3d..2465a7c 100644 (file)
@@ -41,6 +41,9 @@
 typedef struct CGContext PlatformGraphicsContext;
 #elif PLATFORM(CAIRO)
 #include "PlatformRefPtrCairo.h"
+namespace WebCore {
+class ContextShadow;
+}
 typedef struct _cairo PlatformGraphicsContext;
 #elif PLATFORM(OPENVG)
 namespace WebCore {
@@ -298,11 +301,6 @@ namespace WebCore {
         void setAlpha(float);
 #if PLATFORM(CAIRO)
         float getAlpha();
-        void applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, FloatRect& shadowRect, float radius);
-        PlatformRefPtr<cairo_surface_t> createShadowMask(PassOwnPtr<ImageBuffer>, FloatRect&, float radius);
-
-        static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur);
-        void drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace);
 #endif
 
         void setCompositeOperation(CompositeOperator);
@@ -403,6 +401,9 @@ namespace WebCore {
         void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask);
         QPen pen();
         static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
+#endif
+
+#if PLATFORM(QT) || PLATFORM(CAIRO)
         ContextShadow* contextShadow();
 #endif
 
index cd5d362..3d55c70 100644 (file)
@@ -31,6 +31,8 @@
 #include "Font.h"
 
 #include "AffineTransform.h"
+#include "CairoUtilities.h"
+#include "ContextShadow.h"
 #include "GlyphBuffer.h"
 #include "Gradient.h"
 #include "GraphicsContext.h"
 #include "Pattern.h"
 #include "SimpleFontData.h"
 
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
 namespace WebCore {
 
-void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
-                      int from, int numGlyphs, const FloatPoint& point) const
+static void prepareContextForGlyphDrawing(cairo_t* context, const SimpleFontData* font, const FloatPoint& point)
 {
-    cairo_t* cr = context->platformContext();
-    cairo_save(cr);
+    static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
+    cairo_set_scaled_font(context, font->platformData().scaledFont());
+    if (font->platformData().syntheticOblique()) {
+        cairo_matrix_t mat = {1, 0, syntheticObliqueSkew, 1, point.x(), point.y()};
+        cairo_transform(context, &mat);
+    } else
+        cairo_translate(context, point.x(), point.y());
+}
 
-    cairo_set_scaled_font(cr, font->platformData().scaledFont());
+static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+{
+    cairo_show_glyphs(context, glyphs, numGlyphs);
+    if (font->syntheticBoldOffset()) {
+        // We could use cairo_save/cairo_restore here, but two translations are likely faster.
+        cairo_translate(context, font->syntheticBoldOffset(), 0);
+        cairo_show_glyphs(context, glyphs, numGlyphs);
+        cairo_translate(context, -font->syntheticBoldOffset(), 0);
+    }
+}
+
+static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
+{
+    ContextShadow* shadow = graphicsContext->contextShadow();
+    ASSERT(shadow);
+
+    if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow)
+        return;
+
+    if (shadow->m_type == ContextShadow::SolidShadow) {
+        // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
+        cairo_save(context);
+        cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
+        setSourceRGBAFromColor(context, shadow->m_color);
+        prepareContextForGlyphDrawing(context, font, point);
+        cairo_show_glyphs(context, glyphs, numGlyphs);
+        cairo_restore(context);
+        return;
+    }
+
+    cairo_text_extents_t extents;
+    cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
+    FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height);
+    cairo_t* shadowContext = shadow->beginShadowLayer(context, fontExtentsRect);
+    if (shadowContext) {
+        prepareContextForGlyphDrawing(shadowContext, font, point);
+        drawGlyphsToContext(shadowContext, font, glyphs, numGlyphs);
+        shadow->endShadowLayer(context);
+    }
+}
 
+void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
+                      int from, int numGlyphs, const FloatPoint& point) const
+{
     GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
 
     float offset = 0.0f;
@@ -59,75 +106,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
         offset += glyphBuffer.advanceAt(from + i);
     }
 
-    Color fillColor = context->fillColor();
-
-    // Synthetic Oblique
-    if(font->platformData().syntheticOblique()) {
-        cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()};
-        cairo_transform(cr, &mat);
-    } else {
-        cairo_translate(cr, point.x(), point.y());
-    }
-
-    // Text shadow, inspired by FontMac
-    FloatSize shadowOffset;
-    float shadowBlur = 0;
-    Color shadowColor;
-    bool hasShadow = context->textDrawingMode() & cTextFill
-                     && context->getShadow(shadowOffset, shadowBlur, shadowColor);
-
-    // TODO: Blur support
-    if (hasShadow) {
-        // Disable graphics context shadows (not yet implemented) and paint them manually
-        context->clearShadow();
-        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
-        cairo_save(cr);
-
-        float red, green, blue, alpha;
-        shadowFillColor.getRGBA(red, green, blue, alpha);
-        cairo_set_source_rgba(cr, red, green, blue, alpha);
-
-#if ENABLE(FILTERS)
-        cairo_text_extents_t extents;
-        cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
-
-        FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
-        IntSize shadowBufferSize;
-        FloatRect shadowRect;
-        float radius = 0;
-        context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
-        // Draw shadow into a new ImageBuffer
-        OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
-        GraphicsContext* shadowContext = shadowBuffer->context();
-        cairo_t* shadowCr = shadowContext->platformContext();
-
-        cairo_translate(shadowCr, radius, extents.height + radius);
-
-        cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
-        cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
-        if (font->syntheticBoldOffset()) {
-            cairo_save(shadowCr);
-            cairo_translate(shadowCr, font->syntheticBoldOffset(), 0);
-            cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
-            cairo_restore(shadowCr);
-        }
-        cairo_translate(cr, 0.0, -extents.height);
-        context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#else
-        cairo_translate(cr, shadowOffset.width(), shadowOffset.height());
-        cairo_show_glyphs(cr, glyphs, numGlyphs);
-        if (font->syntheticBoldOffset()) {
-            cairo_save(cr);
-            cairo_translate(cr, font->syntheticBoldOffset(), 0);
-            cairo_show_glyphs(cr, glyphs, numGlyphs);
-            cairo_restore(cr);
-        }
-#endif
-
-        cairo_restore(cr);
-    }
+    cairo_t* cr = context->platformContext();
+    drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs);
 
+    cairo_save(cr);
+    prepareContextForGlyphDrawing(cr, font, point);
     if (context->textDrawingMode() & cTextFill) {
         if (context->fillGradient()) {
             cairo_set_source(cr, context->fillGradient()->platformGradient());
@@ -148,16 +131,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
             cairo_pattern_destroy(pattern);
         } else {
             float red, green, blue, alpha;
-            fillColor.getRGBA(red, green, blue, alpha);
+            context->fillColor().getRGBA(red, green, blue, alpha);
             cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
         }
-        cairo_show_glyphs(cr, glyphs, numGlyphs);
-        if (font->syntheticBoldOffset()) {
-            cairo_save(cr);
-            cairo_translate(cr, font->syntheticBoldOffset(), 0);
-            cairo_show_glyphs(cr, glyphs, numGlyphs);
-            cairo_restore(cr);
-        }
+        drawGlyphsToContext(cr, font, glyphs, numGlyphs);
     }
 
     // Prevent running into a long computation within cairo. If the stroke width is
@@ -183,20 +160,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
             }
             cairo_pattern_destroy(pattern);
         } else {
-            Color strokeColor = context->strokeColor();
             float red, green, blue, alpha;
-            strokeColor.getRGBA(red, green, blue, alpha);
+            context->strokeColor().getRGBA(red, green, blue, alpha);
             cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
-        } 
+        }
         cairo_glyph_path(cr, glyphs, numGlyphs);
         cairo_set_line_width(cr, context->strokeThickness());
         cairo_stroke(cr);
     }
 
-    // Re-enable the platform shadow we disabled earlier
-    if (hasShadow)
-        context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace);
-
     cairo_restore(cr);
 }
 
index a4b644c..0847da1 100644 (file)
 #include "AffineTransform.h"
 #include "CairoPath.h"
 #include "CairoUtilities.h"
-#include "FEGaussianBlur.h"
+#include "ContextShadow.h"
 #include "FloatRect.h"
 #include "Font.h"
+#include "GraphicsContextPlatformPrivateCairo.h"
+#include "GraphicsContextPrivate.h"
 #include "OwnPtrCairo.h"
-#include "ImageBuffer.h"
-#include "ImageBufferFilter.h"
 #include "IntRect.h"
 #include "NotImplemented.h"
 #include "Path.h"
 #include "Pattern.h"
 #include "PlatformRefPtrCairo.h"
 #include "SimpleFontData.h"
-#include "SourceGraphic.h"
-
 #include <cairo.h>
 #include <math.h>
 #include <stdio.h>
@@ -61,8 +59,6 @@
 #elif PLATFORM(WIN)
 #include <cairo-win32.h>
 #endif
-#include "GraphicsContextPlatformPrivateCairo.h"
-#include "GraphicsContextPrivate.h"
 
 using namespace std;
 
@@ -140,83 +136,59 @@ static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const
     cairo_close_path(context);
 }
 
-void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur)
-{
-#if ENABLE(FILTERS)
-    // limit radius to 128
-    radius = min(128.f, max(shadowBlur, 0.f));
-
-    shadowBufferSize = IntSize(sourceRect.width() + radius * 2, sourceRect.height() + radius * 2);
-
-    // determine dimensions of shadow rect
-    shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
-    shadowRect.move(shadowOffset.width() - radius, shadowOffset.height() - radius);
-#endif
-}
+enum PathDrawingStyle { 
+    Fill = 1,
+    Stroke = 2,
+    FillAndStroke = Fill + Stroke
+};
 
-static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow)
+static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* contextPrivate, PathDrawingStyle drawingStyle)
 {
-#if ENABLE(FILTERS)
-    FloatSize shadowOffset;
-    float shadowBlur;
-    Color shadowColor;
-    if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
+    ContextShadow* shadow = context->contextShadow();
+    ASSERT(shadow);
+    if (shadow->m_type == ContextShadow::NoShadow)
         return;
-    
-    // Calculate filter values to create appropriate shadow.
-    cairo_t* cr = context->platformContext();
-    double x0, x1, y0, y1;
-    if (strokeShadow)
-        cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
-    else
-        cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
-    FloatRect rect(x0, y0, x1 - x0, y1 - y0);
-
-    IntSize shadowBufferSize;
-    FloatRect shadowRect;
-    float radius = 0;
-    GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
-    cairo_clip_extents(cr, &x0, &y0, &x1, &y1);
-    FloatRect clipRect(x0, y0, x1 - x0, y1 - y0);
-
-    FloatPoint rectLocation = shadowRect.location();
-
-    // Reduce the shadow rect using the clip area.
-    if (!clipRect.contains(shadowRect)) {
-        shadowRect.intersect(clipRect);
-        if (shadowRect.isEmpty())
-            return;
-        shadowRect.inflate(radius);
-        shadowBufferSize = IntSize(shadowRect.width(), shadowRect.height());
-    }
 
-    shadowOffset = rectLocation - shadowRect.location();
+    // Calculate the extents of the rendered solid paths.
+    cairo_t* cairoContext = context->platformContext();
+    cairo_path_t* path = cairo_copy_path(cairoContext);
+
+    FloatRect solidFigureExtents;
+    double x0 = 0;
+    double x1 = 0;
+    double y0 = 0;
+    double y1 = 0;
+    if (drawingStyle & Stroke) {
+        cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1);
+        solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0);
+    }
+    if (drawingStyle & Fill) {
+        cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1);
+        FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0);
+        solidFigureExtents.unite(fillExtents);
+    }
 
-    // Create suitably-sized ImageBuffer to hold the shadow.
-    OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+    cairo_t* shadowContext = shadow->beginShadowLayer(cairoContext, solidFigureExtents);
+    if (!shadowContext)
+        return;
 
-    // Draw shadow into a new ImageBuffer.
-    cairo_t* shadowContext = shadowBuffer->context()->platformContext();
-    copyContextProperties(cr, shadowContext);
-    cairo_translate(shadowContext, -rect.x() + radius + shadowOffset.width(), -rect.y() + radius + shadowOffset.height());
-    cairo_new_path(shadowContext);
-    OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
-    cairo_append_path(shadowContext, path.get());
+    // It's important to copy the context properties to the new shadow
+    // context to preserve things such as the fill rule and stroke width.
+    copyContextProperties(cairoContext, shadowContext);
+    cairo_append_path(shadowContext, path);
 
-    if (fillShadow)
-        setPlatformFill(context, shadowContext, gcp);
-    if (strokeShadow)
-        setPlatformStroke(context, shadowContext, gcp);
+    if (drawingStyle & Fill)
+        setPlatformFill(context, shadowContext, contextPrivate);
+    if (drawingStyle & Stroke)
+        setPlatformStroke(context, shadowContext, contextPrivate);
 
-    context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#endif
+    shadow->endShadowLayer(cairoContext);
 }
 
 static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
 {
     cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
-    drawPathShadow(context, gcp, true, false);
+    drawPathShadow(context, gcp, Fill);
 
     setPlatformFill(context, cairoContext, gcp);
     cairo_new_path(cairoContext);
@@ -224,7 +196,7 @@ static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivat
 
 static void strokeCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
 {
-    drawPathShadow(context, gcp, false, true);
+    drawPathShadow(context, gcp, Stroke);
     setPlatformStroke(context, cairoContext, gcp);
     cairo_new_path(cairoContext);
 }
@@ -261,12 +233,20 @@ void GraphicsContext::savePlatformState()
 {
     cairo_save(m_data->cr);
     m_data->save();
+    m_data->shadowStack.append(m_data->shadow);
 }
 
 void GraphicsContext::restorePlatformState()
 {
     cairo_restore(m_data->cr);
     m_data->restore();
+
+    if (m_data->shadowStack.isEmpty())
+        m_data->shadow = ContextShadow();
+    else {
+        m_data->shadow = m_data->shadowStack.last();
+        m_data->shadowStack.removeLast();
+    }
 }
 
 // Draws a filled rectangle with a stroked border.
@@ -582,7 +562,7 @@ void GraphicsContext::drawPath()
     setPathOnCairoContext(cr, m_data->m_pendingPath.context());
 
     cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
-    drawPathShadow(this, m_common, true, true);
+    drawPathShadow(this, m_common, FillAndStroke);
 
     setPlatformFill(this, cr, m_common);
     setPlatformStroke(this, cr, m_common);
@@ -601,35 +581,14 @@ void GraphicsContext::fillRect(const FloatRect& rect)
     cairo_restore(cr);
 }
 
-static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
-{
-#if ENABLE(FILTERS)
-    FloatSize shadowOffset;
-    float shadowBlur;
-    Color shadowColor;
-    if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
-        return;
-
-    IntSize shadowBufferSize;
-    FloatRect shadowRect;
-    float radius = 0;
-    GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
-
-    // Draw shadow into a new ImageBuffer
-    OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
-    GraphicsContext* shadowContext = shadowBuffer->context();
-    shadowContext->fillRect(FloatRect(FloatPoint(radius, radius), rect.size()), rectColor, DeviceColorSpace);
-
-    context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
-#endif
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
 {
     if (paintingDisabled())
         return;
 
-    drawBorderlessRectShadow(this, rect, color);
+    if (m_data->hasShadow())
+        m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
+
     if (color.alpha())
         fillRectSourceOver(m_data->cr, rect, color);
 }
@@ -899,61 +858,26 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
     cairo_set_fill_rule(cr, savedFillRule);
 }
 
-void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace)
+void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
 {
-    // Cairo doesn't support shadows natively, they are drawn manually in the draw*
-    // functions
-
+    // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
     if (m_common->state.shadowsIgnoreTransforms) {
         // Meaning that this graphics context is associated with a CanvasRenderingContext
         // We flip the height since CG and HTML5 Canvas have opposite Y axis
         m_common->state.shadowOffset = FloatSize(size.width(), -size.height());
-    }
+        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
+    } else
+        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
 }
 
-void GraphicsContext::applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, FloatRect& shadowRect, float radius)
+ContextShadow* GraphicsContext::contextShadow()
 {
-#if ENABLE(FILTERS)
-    setColor(m_data->cr, shadowColor);
-    PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(buffer, shadowRect, radius));
-    cairo_mask_surface(m_data->cr, shadowMask.get(), shadowRect.x(), shadowRect.y());
-#endif
+    return &m_data->shadow;
 }
 
-PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<ImageBuffer> buffer, FloatRect& shadowRect, float radius)
-{
-#if ENABLE(FILTERS)
-    if (!radius)
-        return buffer->m_data.m_surface;
-
-    FloatPoint blurRadius = FloatPoint(radius, radius);
-    float stdDeviation = FEGaussianBlur::calculateStdDeviation(radius);
-    if (!stdDeviation)
-        return buffer->m_data.m_surface;
-
-    // create filter
-    IntRect filterRegion = IntRect(IntPoint(), roundedIntSize(shadowRect.size()));
-    RefPtr<Filter> filter = ImageBufferFilter::create(filterRegion);
-    filter->setSourceImage(buffer);
-    RefPtr<FilterEffect> source = SourceGraphic::create();
-    source->setIsAlphaImage(true);
-    RefPtr<FilterEffect> blur = FEGaussianBlur::create(stdDeviation, stdDeviation);
-    blur->setMaxEffectRect(filterRegion);
-    FilterEffectVector& inputEffects = blur->inputEffects();
-    inputEffects.append(source.get());
-    blur->apply(filter.get());
-
-    // Calculate shadow region for context
-    shadowRect.move(blur->absolutePaintRect().location().x(), blur->absolutePaintRect().location().y());
-    shadowRect.setSize(blur->absolutePaintRect().size());
-    return blur->resultImage()->m_data.m_surface;
-#endif
-}
-
-
 void GraphicsContext::clearPlatformShadow()
 {
-    notImplemented();
+    m_data->shadow.clear();
 }
 
 void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -1186,208 +1110,20 @@ static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile)
     return phase;
 }
 
-/*
-  This function uses tiling to improve the performance of the shadow
-  drawing of rounded rectangles. The code basically does the following
-  steps:
-
-     1. Calculate the minimum rectangle size required to create the
-     tiles
-
-     2. If that size is smaller than the real rectangle render the new
-     small rectangle and its shadow in a new surface, in other case
-     render the shadow of the real rectangle in the destination
-     surface.
-
-     3. Calculate the sizes and positions of the tiles and their
-     destinations and use drawPattern to render the final shadow. The
-     code divides the rendering in 8 tiles:
-
-        1 | 2 | 3
-       -----------
-        4 |   | 5
-       -----------
-        6 | 7 | 8
-
-     The corners are directly copied from the small rectangle to the
-     real one and the side tiles are 1 pixel width, we use them as
-
-     tiles to cover the destination side. The corner tiles are bigger
-     than just the side of the rounded corner, we need to increase it
-     because the modifications caused by the corner over the blur
-     effect. We fill the central part with solid color to complete the
-     shadow.
- */
-void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace)
-{
-#if ENABLE(FILTERS)
-    FloatSize shadowSize;
-    float shadowBlur;
-    Color shadowColor;
-    if (!getShadow(shadowSize, shadowBlur, shadowColor))
-        return;
-
-    // Calculate filter values to create appropriate shadow.
-    cairo_t* cr = m_data->cr;
-
-    IntSize shadowBufferSize;
-    FloatRect shadowRect;
-    float blurRadius = 0;
-    GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, blurRadius, rect, shadowSize, shadowBlur);
-
-    // Size of the tiling side.
-    int sideTileWidth = 1;
-    float radiusTwice = blurRadius * 2;
-
-    // Find the extra space needed from the curve of the corners.
-    int extraWidthFromCornerRadii = radiusTwice + max(topLeftRadius.width(), bottomLeftRadius.width()) +
-                                    radiusTwice + max(topRightRadius.width(), bottomRightRadius.width());
-    int extraHeightFromCornerRadii = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) +
-                                     radiusTwice + max(bottomLeftRadius.height(), bottomRightRadius.height());
-
-    // The length of a side of the buffer is the enough space for four blur radii,
-    // the radii of the corners, and then 1 pixel to draw the side tiles.
-    IntSize smallBufferSize = IntSize(sideTileWidth + extraWidthFromCornerRadii,
-                                      sideTileWidth + extraHeightFromCornerRadii);
-
-    if ((smallBufferSize.width() > shadowBufferSize.width()) || (smallBufferSize.height() > shadowBufferSize.height()) || (blurRadius <= 0)) {
-        // Create suitably-sized ImageBuffer to hold the shadow.
-        OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
-        if (!shadowBuffer)
-            return;
-
-        // Draw shadow into a new ImageBuffer.
-        cairo_t* shadowContext = shadowBuffer->context()->platformContext();
-        copyContextProperties(cr, shadowContext);
-        cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius);
-        cairo_new_path(shadowContext);
-        OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
-        cairo_append_path(shadowContext, path.get());
-
-        setPlatformFill(this, shadowContext, m_common);
-
-        applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, blurRadius);
-
-        return;
-    }
-
-    OwnPtr<ImageBuffer> smallBuffer = ImageBuffer::create(smallBufferSize);
-    if (!smallBuffer)
-        return;
-
-    FloatRect smallRect = FloatRect(blurRadius, blurRadius, smallBufferSize.width() - radiusTwice, smallBufferSize.height() - radiusTwice);
-
-    // Draw shadow into a new ImageBuffer.
-    cairo_t* smallBufferContext = smallBuffer->context()->platformContext();
-    copyContextProperties(cr, smallBufferContext);
-
-    Path path;
-    path.addRoundedRect(smallRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
-    appendWebCorePathToCairoContext(smallBuffer->context()->platformContext(), path);
-    setPlatformFill(this, smallBufferContext, m_common);
-
-    OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(smallBufferSize);
-    if (!shadowBuffer)
-        return;
-
-    smallRect.setSize(smallBufferSize);
-
-    PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(smallBuffer.release(), smallRect, blurRadius));
-
-    cairo_t* shadowContext = shadowBuffer->context()->platformContext();
-    setColor(shadowContext, shadowColor);
-    cairo_mask_surface(shadowContext, shadowMask.get(), 0, 0);
-
-    // Fill the internal part of the shadow.
-    shadowRect.inflate(-radiusTwice);
-    if (!shadowRect.isEmpty()) {
-        cairo_save(cr);
-        path.clear();
-        path.addRoundedRect(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
-        appendWebCorePathToCairoContext(cr, path);
-        setColor(cr, shadowColor);
-        cairo_fill(cr);
-        cairo_restore(cr);
-    }
-    shadowRect.inflate(radiusTwice);
-
-    // Draw top side.
-    FloatRect tileRect = FloatRect(radiusTwice + topLeftRadius.width(), 0, sideTileWidth, radiusTwice);
-    FloatRect destRect = tileRect;
-    destRect.move(shadowRect.x(), shadowRect.y());
-    destRect.setWidth(shadowRect.width() - topLeftRadius.width() - topRightRadius.width() - blurRadius * 4);
-    FloatPoint phase = getPhase(destRect, tileRect);
-    AffineTransform patternTransform;
-    patternTransform.makeIdentity();
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the bottom side.
-    tileRect = FloatRect(radiusTwice + bottomLeftRadius.width(), smallBufferSize.height() - radiusTwice, sideTileWidth, radiusTwice);
-    destRect = tileRect;
-    destRect.move(shadowRect.x(), shadowRect.y() + radiusTwice + rect.height() - smallBufferSize.height());
-    destRect.setWidth(shadowRect.width() - bottomLeftRadius.width() - bottomRightRadius.width() - blurRadius * 4);
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the right side.
-    tileRect = FloatRect(smallBufferSize.width() - radiusTwice, radiusTwice + topRightRadius.height(), radiusTwice, sideTileWidth);
-    destRect = tileRect;
-    destRect.move(shadowRect.x() + radiusTwice + rect.width() - smallBufferSize.width(), shadowRect.y());
-    destRect.setHeight(shadowRect.height() - topRightRadius.height() - bottomRightRadius.height() - blurRadius * 4);
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the left side.
-    tileRect = FloatRect(0, radiusTwice + topLeftRadius.height(), radiusTwice, sideTileWidth);
-    destRect = tileRect;
-    destRect.move(shadowRect.x(), shadowRect.y());
-    destRect.setHeight(shadowRect.height() - topLeftRadius.height() - bottomLeftRadius.height() - blurRadius * 4);
-    phase = FloatPoint(destRect.x() - tileRect.x(), destRect.y() - tileRect.y());
-    shadowBuffer->drawPattern(this, tileRect, patternTransform,
-                              phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the top left corner.
-    tileRect = FloatRect(0, 0, radiusTwice + topLeftRadius.width(), radiusTwice + topLeftRadius.height());
-    destRect = tileRect;
-    destRect.move(shadowRect.x(), shadowRect.y());
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the top right corner.
-    tileRect = FloatRect(smallBufferSize.width() - radiusTwice - topRightRadius.width(), 0, radiusTwice + topRightRadius.width(), radiusTwice + topRightRadius.height());
-    destRect = tileRect;
-    destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y());
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the bottom right corner.
-    tileRect = FloatRect(smallBufferSize.width() - radiusTwice - bottomRightRadius.width(), smallBufferSize.height() - radiusTwice - bottomRightRadius.height(), radiusTwice + bottomRightRadius.width(), radiusTwice + bottomRightRadius.height());
-    destRect = tileRect;
-    destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-
-    // Draw the bottom left corner.
-    tileRect = FloatRect(0, smallBufferSize.height() - radiusTwice - bottomLeftRadius.height(), radiusTwice + bottomLeftRadius.width(), radiusTwice + bottomLeftRadius.height());
-    destRect = tileRect;
-    destRect.move(shadowRect.x(), shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
-    phase = getPhase(destRect, tileRect);
-    shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
-#endif
-}
-
 void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
 {
     if (paintingDisabled())
         return;
 
+    if (m_data->hasShadow())
+        m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
+
     cairo_t* cr = m_data->cr;
     cairo_save(cr);
     Path path;
     path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
     appendWebCorePathToCairoContext(cr, path);
     setColor(cr, color);
-    drawPathShadow(this, m_common, true, false);
     cairo_fill(cr);
     cairo_restore(cr);
 }
index 81987ef..22a0722 100644 (file)
@@ -98,6 +98,10 @@ public:
     Vector<float> layers;
     CairoPath m_pendingPath;
 
+    ContextShadow shadow;
+    Vector<ContextShadow> shadowStack;
+    bool hasShadow() const { return shadow.m_type != ContextShadow::NoShadow; }
+
 #if PLATFORM(GTK)
     GdkEventExpose* expose;
 #elif PLATFORM(WIN)
index 995f77b..8f7a194 100644 (file)
@@ -33,6 +33,7 @@
 #include "AffineTransform.h"
 #include "CairoUtilities.h"
 #include "Color.h"
+#include "ContextShadow.h"
 #include "FloatRect.h"
 #include "PlatformRefPtrCairo.h"
 #include "GraphicsContext.h"
@@ -134,29 +135,18 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
     cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
     cairo_pattern_set_matrix(pattern, &matrix);
 
-    // Draw the shadow
-#if ENABLE(FILTERS)
-    FloatSize shadowOffset;
-    float shadowBlur;
-    Color shadowColor;
-    if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) {
-        IntSize shadowBufferSize;
-        FloatRect shadowRect;
-        float radius = 0;
-        context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur);
-        shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() *  context->getAlpha()) / 255.f);
-
-        //draw shadow into a new ImageBuffer
-        OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
-        cairo_t* shadowContext = shadowBuffer->context()->platformContext();
-        cairo_set_source(shadowContext, pattern);
-        cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
-        cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
-        cairo_fill(shadowContext);
-
-        context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
+    ContextShadow* shadow = context->contextShadow();
+    ASSERT(shadow);
+    if (shadow->m_type != ContextShadow::NoShadow) {
+        cairo_t* shadowContext = shadow->beginShadowLayer(cr, dstRect);
+        if (shadowContext) {
+            cairo_translate(shadowContext, dstRect.x(), dstRect.y());
+            cairo_set_source(shadowContext, pattern);
+            cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
+            cairo_fill(shadowContext);
+            shadow->endShadowLayer(cr);
+        }
     }
-#endif
 
     // Draw the image.
     cairo_translate(cr, dstRect.x(), dstRect.y());