Changeset 69681 in webkit


Ignore:
Timestamp:
Oct 13, 2010 12:18:10 PM (13 years ago)
Author:
Martin Robinson
Message:

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-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.
Location:
trunk
Files:
63 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r69679 r69681  
     12010-09-24  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Reviewed by Dirk Schulze.
     4
     5        [Cairo] Activate ContextShadow in all places where shadows are drawn
     6        https://bugs.webkit.org/show_bug.cgi?id=46475
     7
     8        Rebaselined tests. All these changes seem reasonable. In some cases, the
     9        new results are much better / closer matches to Chromium.
     10
     11        * platform/gtk/fast/box-shadow/basic-shadows-expected.checksum:
     12        * platform/gtk/fast/box-shadow/basic-shadows-expected.png:
     13        * platform/gtk/fast/box-shadow/inset-expected.checksum:
     14        * platform/gtk/fast/box-shadow/inset-expected.png:
     15        * platform/gtk/fast/css/shadow-multiple-expected.checksum:
     16        * platform/gtk/fast/css/shadow-multiple-expected.png:
     17        * platform/gtk/fast/text/shadow-no-blur-expected.checksum:
     18        * platform/gtk/fast/text/shadow-no-blur-expected.png:
     19        * platform/gtk/fast/text/shadow-translucent-fill-expected.checksum:
     20        * platform/gtk/fast/text/shadow-translucent-fill-expected.png:
     21        * platform/gtk/fast/text/stroking-decorations-expected.checksum:
     22        * platform/gtk/fast/text/stroking-decorations-expected.png:
     23        * platform/gtk/fast/text/stroking-expected.checksum:
     24        * platform/gtk/fast/text/stroking-expected.png:
     25        * platform/gtk/fast/transforms/shadows-expected.checksum:
     26        * platform/gtk/fast/transforms/shadows-expected.png:
     27        * platform/gtk/svg/css/arrow-with-shadow-expected.checksum:
     28        * platform/gtk/svg/css/arrow-with-shadow-expected.png:
     29        * platform/gtk/svg/css/composite-shadow-text-expected.checksum:
     30        * platform/gtk/svg/css/composite-shadow-text-expected.png:
     31        * platform/gtk/svg/css/group-with-shadow-expected.checksum:
     32        * platform/gtk/svg/css/group-with-shadow-expected.png:
     33        * platform/gtk/svg/css/path-with-shadow-expected.checksum:
     34        * platform/gtk/svg/css/path-with-shadow-expected.png:
     35        * platform/gtk/svg/css/shadow-with-large-radius-expected.checksum:
     36        * platform/gtk/svg/css/shadow-with-large-radius-expected.png:
     37        * platform/gtk/svg/css/shadow-with-negative-offset-expected.checksum:
     38        * platform/gtk/svg/css/shadow-with-negative-offset-expected.png:
     39
    1402010-10-13  Nate Chapin  <japhet@chromium.org>
    241
  • trunk/LayoutTests/platform/gtk/fast/box-shadow/basic-shadows-expected.checksum

    r66607 r69681  
    1 6daac1f7e6af1534a5d83a808573a5c6
     1f3de98a36ced3833112c6a4015124c40
  • trunk/LayoutTests/platform/gtk/fast/box-shadow/border-radius-big-expected.checksum

    r66393 r69681  
    1 f0c925808e96b7a3c3fb3dd6af9f0bef
     10f81b48394aca674d7d6fda921894590
  • trunk/LayoutTests/platform/gtk/fast/box-shadow/inset-expected.checksum

    r66393 r69681  
    1 6d342f464b9c3b1b359652690668b018
     1031c0afbbbf2d3d170b1d5ec47340360
  • trunk/LayoutTests/platform/gtk/fast/box-shadow/spread-expected.checksum

    r66393 r69681  
    1 725db46a3dfc6bd70efff487e32b54c9
     147ae516cd0eb09ddb903c4faee42bc6d
  • trunk/LayoutTests/platform/gtk/fast/box-shadow/transform-fringing-expected.checksum

    r66393 r69681  
    1 66269bba477ba14b5f904c3edcd7a596
     106d7219b65698e41236bf902fc140a4e
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-1-expected.checksum

    r66393 r69681  
    1 b24d55d0a3671f2e40ff90f9515b8f00
     10c1b31a0c94ec92859e1de91bf1c1c56
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-2-expected.checksum

    r66393 r69681  
    1 701883d2e2f95b9d50212bdc39fb59d8
     1c56a7a9113871adb1a75a08af85ab186
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-3-expected.checksum

    r66393 r69681  
    1 b24d55d0a3671f2e40ff90f9515b8f00
     10c1b31a0c94ec92859e1de91bf1c1c56
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-4-expected.checksum

    r66393 r69681  
    1 63cb5d33757a90a841d654189f713879
     110a69afccdf47959f6aee5a2c4e1ef66
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-5-expected.checksum

    r66393 r69681  
    1 63cb5d33757a90a841d654189f713879
     110a69afccdf47959f6aee5a2c4e1ef66
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-6-expected.checksum

    r66393 r69681  
    1 db6adefba05e354dd1d2e812f8c84714
     1b50f28ba9f5040841ee6ce23e85ee986
  • trunk/LayoutTests/platform/gtk/fast/canvas/shadow-offset-7-expected.checksum

    r66393 r69681  
    1 7251d5e6065a233d322bf895b73cde6d
     1f349f090b70db32dee81d2e646d3a807
  • trunk/LayoutTests/platform/gtk/fast/css/shadow-multiple-expected.checksum

    r69558 r69681  
    1 701fabbd3a807c01bb522ec6f2d85122
     1c5e2b47412e5f8bd9d491052823d7ffa
  • trunk/LayoutTests/platform/gtk/fast/forms/box-shadow-override-expected.checksum

    r66393 r69681  
    1 0c3455ef1a424a2702d95d377ca19e1a
     199b1869ec4d61313015fd2f3b02f3fdf
  • trunk/LayoutTests/platform/gtk/fast/text/shadow-translucent-fill-expected.checksum

    r63212 r69681  
    1 ce7b93fc7b29c0f7f9a879369f39159a
     14844ccf7d596f6f8e3f7b47028101646
  • trunk/LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.checksum

    r63176 r69681  
    1 8fe4216cf5158e1a48ff9a096e73c49c
     1a8d29b21cf38133e73674466c89ae4d9
  • trunk/LayoutTests/platform/gtk/fast/text/stroking-decorations-expected.txt

    r63176 r69681  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x156 [textFillColor=#800080] [textStrokeWidth=2.00]
    7         RenderText {#text} at (0,0) size 759x156
    8           text run at (0,0) width 690: "Purple\x{300} fill, black stroke,"
    9           text run at (0,78) width 759: "complex text, black underline"
    10       RenderBlock {DIV} at (0,156) size 784x156 [textStrokeColor=#FFA500] [textStrokeWidth=1.33]
    11         RenderText {#text} at (0,0) size 636x156
    12           text run at (0,0) width 636: "Orange stroke, black fill,"
    13           text run at (0,78) width 414: "orange overline."
    14       RenderBlock {DIV} at (0,312) size 784x156 [textFillColor=#0000FF] [textStrokeWidth=1.33]
    15         RenderText {#text} at (0,0) size 596x156
    16           text run at (0,0) width 596: "No stroke, blue fill, red"
    17           text run at (0,78) width 594: "shadow, blue underline"
     6      RenderBlock {DIV} at (0,0) size 784x148 [textFillColor=#800080] [textStrokeWidth=2.00]
     7        RenderText {#text} at (0,1) size 755x146
     8          text run at (0,1) width 616: "Purple\x{300} fill, black stroke,"
     9          text run at (0,75) width 755: "complex text, black underline"
     10      RenderBlock {DIV} at (0,148) size 784x148 [textStrokeColor=#FFA500] [textStrokeWidth=1.33]
     11        RenderText {#text} at (0,1) size 633x146
     12          text run at (0,1) width 633: "Orange stroke, black fill,"
     13          text run at (0,75) width 412: "orange overline."
     14      RenderBlock {DIV} at (0,296) size 784x148 [textFillColor=#0000FF] [textStrokeWidth=1.33]
     15        RenderText {#text} at (0,1) size 593x146
     16          text run at (0,1) width 593: "No stroke, blue fill, red"
     17          text run at (0,75) width 592: "shadow, blue underline"
  • trunk/LayoutTests/platform/gtk/fast/text/stroking-expected.checksum

    r63176 r69681  
    1 9bda69d71f92b48dcbeadbc97d4aa314
     11dbe4580c4247c66169215a291f01784
  • trunk/LayoutTests/platform/gtk/fast/transforms/shadows-expected.checksum

    r66393 r69681  
    1 53b5647f358b53516a2971cef984ef43
     1643ebb3d9f814c590c1360ee8780a711
  • trunk/LayoutTests/platform/gtk/svg/css/arrow-with-shadow-expected.checksum

    r66393 r69681  
    1 60406d17eccb661d0abcd479d52d18ae
     17d901aa9e6137f3d4eb0ecffa0a0f6f1
  • trunk/LayoutTests/platform/gtk/svg/css/composite-shadow-example-expected.checksum

    r66400 r69681  
    1 eb02e2baeae31fc65b216461d6335e4e
     1ed68ae2b7a0581824bc52f03f4c24081
  • trunk/LayoutTests/platform/gtk/svg/css/composite-shadow-text-expected.checksum

    r66400 r69681  
    1 fa62fff1ff8a295928c6e40d613d036e
     1ed041c188a24404f25bd470e8b6897c7
  • trunk/LayoutTests/platform/gtk/svg/css/group-with-shadow-expected.checksum

    r66393 r69681  
    1 934838cc206f3bb144a04f0ec0c66fd6
     1b9583689ec16aa6f14a1b326dc4efb20
  • trunk/LayoutTests/platform/gtk/svg/css/mask-with-shadow-expected.checksum

    r66393 r69681  
    1 95a13b575496a68e7be1e244fc085917
     1fccfdd6c1ec02071e92cf8d3e4e055a4
  • trunk/LayoutTests/platform/gtk/svg/css/path-with-shadow-expected.checksum

    r66393 r69681  
    1 5d5b77a6e165e0386e1ed99ca462e546
     132a221a08c690feca7b5f130b0f2b878
  • trunk/LayoutTests/platform/gtk/svg/css/shadow-with-large-radius-expected.checksum

    r66400 r69681  
    1 986e969dd5390eec347bde78441e9610
     1323c4bac52ad86e6f6a1428e85acbf35
  • trunk/LayoutTests/platform/gtk/svg/css/shadow-with-negative-offset-expected.checksum

    r66400 r69681  
    1 3676ffa41f1289d75c2a94d625be27c4
     1a2bc3466efff610dd09fdc9969d0b756
  • trunk/LayoutTests/platform/gtk/svg/css/stars-with-shadow-expected.checksum

    r66607 r69681  
    1 cf31a5f1ae3ef8dd8bba3df35e5ebb9b
     188f3dc364c44bdaa92e09d883c6f7609
  • trunk/WebCore/ChangeLog

    r69673 r69681  
     12010-10-06  Martin Robinson  <mrobinson@igalia.com>
     2
     3        Reviewed by Dirk Schulze.
     4
     5        [Cairo] Activate ContextShadow in all places where shadows are drawn
     6        https://bugs.webkit.org/show_bug.cgi?id=46475
     7
     8        Turn on ContextShadow for the Cairo port and remove all old shadow code.
     9        Shadow tiling optimizations will be added in a followup patch to ContextShadowCairo.
     10
     11        * platform/graphics/GraphicsContext.h: Add a ContextShadow forward declaration for Cairo.
     12        * platform/graphics/cairo/FontCairo.cpp: Switch to using ContextShadow.
     13        (WebCore::prepareContextForGlyphDrawing): Added this helper which sets up the translation
     14        on the specified cairo_t to prepare for drawing glyphs.
     15        (WebCore::drawGlyphsToContext): Added this helper which draws the glyphs to a cairo_t,
     16        while properly handling glyphs with synthetic bold.
     17        (WebCore::Font::drawGlyphs): Removed old shadow code and replaced it with ContextShadow usage.
     18        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     19        (WebCore::drawPathShadow): Modified this to use ContextShadow and to take an enum
     20        argument specifying whether to fill or stroke the solid figure for the shadow.
     21        (WebCore::fillCurrentCairoPath): Updated drawPathShadow call.
     22        (WebCore::strokeCurrentCairoPath): Ditto.
     23        (WebCore::GraphicsContext::savePlatformState): Save the ContextShadow.
     24        (WebCore::GraphicsContext::restorePlatformState): Restore the ContextShadow.
     25        (WebCore::GraphicsContext::drawPath): Updated drawPathShadow call.
     26        (WebCore::GraphicsContext::fillRect): Uses ContextShadow now.
     27        (WebCore::GraphicsContext::setPlatformShadow): Uses ContextShadow now.
     28        (WebCore::GraphicsContext::contextShadow): Added.
     29        (WebCore::GraphicsContext::clearPlatformShadow): Clears the ContextShadow member.
     30        (WebCore::GraphicsContext::fillRoundedRect): Updated drawPathShadow call.
     31        * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h:
     32        (WebCore::GraphicsContextPlatformPrivate::hasShadow): Added.
     33        * platform/graphics/cairo/ImageCairo.cpp:
     34        (WebCore::BitmapImage::draw): Updated to use ContextShadow.
     35
    1362010-10-13  John Knottenbelt  <jknotten@chromium.org>
    237
  • trunk/WebCore/platform/graphics/ContextShadow.h

    r69223 r69681  
    101101    static void purgeScratchBuffer();
    102102#if PLATFORM(CAIRO)
    103     void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius);
     103    void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
    104104#endif
    105105
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r69187 r69681  
    4242#elif PLATFORM(CAIRO)
    4343#include "PlatformRefPtrCairo.h"
     44namespace WebCore {
     45class ContextShadow;
     46}
    4447typedef struct _cairo PlatformGraphicsContext;
    4548#elif PLATFORM(OPENVG)
     
    299302#if PLATFORM(CAIRO)
    300303        float getAlpha();
    301         void applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, FloatRect& shadowRect, float radius);
    302         PlatformRefPtr<cairo_surface_t> createShadowMask(PassOwnPtr<ImageBuffer>, FloatRect&, float radius);
    303 
    304         static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur);
    305         void drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace);
    306304#endif
    307305
     
    404402        QPen pen();
    405403        static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
     404#endif
     405
     406#if PLATFORM(QT) || PLATFORM(CAIRO)
    406407        ContextShadow* contextShadow();
    407408#endif
  • trunk/WebCore/platform/graphics/cairo/FontCairo.cpp

    r66607 r69681  
    3232
    3333#include "AffineTransform.h"
     34#include "CairoUtilities.h"
     35#include "ContextShadow.h"
    3436#include "GlyphBuffer.h"
    3537#include "Gradient.h"
     
    3941#include "SimpleFontData.h"
    4042
    41 #define SYNTHETIC_OBLIQUE_ANGLE 14
     43namespace WebCore {
    4244
    43 namespace WebCore {
     45static void prepareContextForGlyphDrawing(cairo_t* context, const SimpleFontData* font, const FloatPoint& point)
     46{
     47    static const float syntheticObliqueSkew = -tanf(14 * acosf(0) / 90);
     48    cairo_set_scaled_font(context, font->platformData().scaledFont());
     49    if (font->platformData().syntheticOblique()) {
     50        cairo_matrix_t mat = {1, 0, syntheticObliqueSkew, 1, point.x(), point.y()};
     51        cairo_transform(context, &mat);
     52    } else
     53        cairo_translate(context, point.x(), point.y());
     54}
     55
     56static void drawGlyphsToContext(cairo_t* context, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
     57{
     58    cairo_show_glyphs(context, glyphs, numGlyphs);
     59    if (font->syntheticBoldOffset()) {
     60        // We could use cairo_save/cairo_restore here, but two translations are likely faster.
     61        cairo_translate(context, font->syntheticBoldOffset(), 0);
     62        cairo_show_glyphs(context, glyphs, numGlyphs);
     63        cairo_translate(context, -font->syntheticBoldOffset(), 0);
     64    }
     65}
     66
     67static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
     68{
     69    ContextShadow* shadow = graphicsContext->contextShadow();
     70    ASSERT(shadow);
     71
     72    if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow)
     73        return;
     74
     75    if (shadow->m_type == ContextShadow::SolidShadow) {
     76        // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
     77        cairo_save(context);
     78        cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
     79        setSourceRGBAFromColor(context, shadow->m_color);
     80        prepareContextForGlyphDrawing(context, font, point);
     81        cairo_show_glyphs(context, glyphs, numGlyphs);
     82        cairo_restore(context);
     83        return;
     84    }
     85
     86    cairo_text_extents_t extents;
     87    cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
     88    FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height);
     89    cairo_t* shadowContext = shadow->beginShadowLayer(context, fontExtentsRect);
     90    if (shadowContext) {
     91        prepareContextForGlyphDrawing(shadowContext, font, point);
     92        drawGlyphsToContext(shadowContext, font, glyphs, numGlyphs);
     93        shadow->endShadowLayer(context);
     94    }
     95}
    4496
    4597void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
    4698                      int from, int numGlyphs, const FloatPoint& point) const
    4799{
    48     cairo_t* cr = context->platformContext();
    49     cairo_save(cr);
    50 
    51     cairo_set_scaled_font(cr, font->platformData().scaledFont());
    52 
    53100    GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
    54101
     
    60107    }
    61108
    62     Color fillColor = context->fillColor();
     109    cairo_t* cr = context->platformContext();
     110    drawGlyphsShadow(context, cr, point, font, glyphs, numGlyphs);
    63111
    64     // Synthetic Oblique
    65     if(font->platformData().syntheticOblique()) {
    66         cairo_matrix_t mat = {1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, point.x(), point.y()};
    67         cairo_transform(cr, &mat);
    68     } else {
    69         cairo_translate(cr, point.x(), point.y());
    70     }
    71 
    72     // Text shadow, inspired by FontMac
    73     FloatSize shadowOffset;
    74     float shadowBlur = 0;
    75     Color shadowColor;
    76     bool hasShadow = context->textDrawingMode() & cTextFill
    77                      && context->getShadow(shadowOffset, shadowBlur, shadowColor);
    78 
    79     // TODO: Blur support
    80     if (hasShadow) {
    81         // Disable graphics context shadows (not yet implemented) and paint them manually
    82         context->clearShadow();
    83         Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
    84         cairo_save(cr);
    85 
    86         float red, green, blue, alpha;
    87         shadowFillColor.getRGBA(red, green, blue, alpha);
    88         cairo_set_source_rgba(cr, red, green, blue, alpha);
    89 
    90 #if ENABLE(FILTERS)
    91         cairo_text_extents_t extents;
    92         cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
    93 
    94         FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
    95         IntSize shadowBufferSize;
    96         FloatRect shadowRect;
    97         float radius = 0;
    98         context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
    99 
    100         // Draw shadow into a new ImageBuffer
    101         OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
    102         GraphicsContext* shadowContext = shadowBuffer->context();
    103         cairo_t* shadowCr = shadowContext->platformContext();
    104 
    105         cairo_translate(shadowCr, radius, extents.height + radius);
    106 
    107         cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
    108         cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
    109         if (font->syntheticBoldOffset()) {
    110             cairo_save(shadowCr);
    111             cairo_translate(shadowCr, font->syntheticBoldOffset(), 0);
    112             cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
    113             cairo_restore(shadowCr);
    114         }
    115         cairo_translate(cr, 0.0, -extents.height);
    116         context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
    117 #else
    118         cairo_translate(cr, shadowOffset.width(), shadowOffset.height());
    119         cairo_show_glyphs(cr, glyphs, numGlyphs);
    120         if (font->syntheticBoldOffset()) {
    121             cairo_save(cr);
    122             cairo_translate(cr, font->syntheticBoldOffset(), 0);
    123             cairo_show_glyphs(cr, glyphs, numGlyphs);
    124             cairo_restore(cr);
    125         }
    126 #endif
    127 
    128         cairo_restore(cr);
    129     }
    130 
     112    cairo_save(cr);
     113    prepareContextForGlyphDrawing(cr, font, point);
    131114    if (context->textDrawingMode() & cTextFill) {
    132115        if (context->fillGradient()) {
     
    149132        } else {
    150133            float red, green, blue, alpha;
    151             fillColor.getRGBA(red, green, blue, alpha);
     134            context->fillColor().getRGBA(red, green, blue, alpha);
    152135            cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
    153136        }
    154         cairo_show_glyphs(cr, glyphs, numGlyphs);
    155         if (font->syntheticBoldOffset()) {
    156             cairo_save(cr);
    157             cairo_translate(cr, font->syntheticBoldOffset(), 0);
    158             cairo_show_glyphs(cr, glyphs, numGlyphs);
    159             cairo_restore(cr);
    160         }
     137        drawGlyphsToContext(cr, font, glyphs, numGlyphs);
    161138    }
    162139
     
    184161            cairo_pattern_destroy(pattern);
    185162        } else {
    186             Color strokeColor = context->strokeColor();
    187163            float red, green, blue, alpha;
    188             strokeColor.getRGBA(red, green, blue, alpha);
     164            context->strokeColor().getRGBA(red, green, blue, alpha);
    189165            cairo_set_source_rgba(cr, red, green, blue, alpha * context->getAlpha());
    190         } 
     166        }
    191167        cairo_glyph_path(cr, glyphs, numGlyphs);
    192168        cairo_set_line_width(cr, context->strokeThickness());
     
    194170    }
    195171
    196     // Re-enable the platform shadow we disabled earlier
    197     if (hasShadow)
    198         context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace);
    199 
    200172    cairo_restore(cr);
    201173}
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r69517 r69681  
    3737#include "CairoPath.h"
    3838#include "CairoUtilities.h"
    39 #include "FEGaussianBlur.h"
     39#include "ContextShadow.h"
    4040#include "FloatRect.h"
    4141#include "Font.h"
     42#include "GraphicsContextPlatformPrivateCairo.h"
     43#include "GraphicsContextPrivate.h"
    4244#include "OwnPtrCairo.h"
    43 #include "ImageBuffer.h"
    44 #include "ImageBufferFilter.h"
    4545#include "IntRect.h"
    4646#include "NotImplemented.h"
     
    4949#include "PlatformRefPtrCairo.h"
    5050#include "SimpleFontData.h"
    51 #include "SourceGraphic.h"
    52 
    5351#include <cairo.h>
    5452#include <math.h>
     
    6260#include <cairo-win32.h>
    6361#endif
    64 #include "GraphicsContextPlatformPrivateCairo.h"
    65 #include "GraphicsContextPrivate.h"
    6662
    6763using namespace std;
     
    141137}
    142138
    143 void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur)
    144 {
    145 #if ENABLE(FILTERS)
    146     // limit radius to 128
    147     radius = min(128.f, max(shadowBlur, 0.f));
    148 
    149     shadowBufferSize = IntSize(sourceRect.width() + radius * 2, sourceRect.height() + radius * 2);
    150 
    151     // determine dimensions of shadow rect
    152     shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
    153     shadowRect.move(shadowOffset.width() - radius, shadowOffset.height() - radius);
    154 #endif
    155 }
    156 
    157 static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow)
    158 {
    159 #if ENABLE(FILTERS)
    160     FloatSize shadowOffset;
    161     float shadowBlur;
    162     Color shadowColor;
    163     if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
    164         return;
    165    
    166     // Calculate filter values to create appropriate shadow.
    167     cairo_t* cr = context->platformContext();
    168     double x0, x1, y0, y1;
    169     if (strokeShadow)
    170         cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
    171     else
    172         cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
    173     FloatRect rect(x0, y0, x1 - x0, y1 - y0);
    174 
    175     IntSize shadowBufferSize;
    176     FloatRect shadowRect;
    177     float radius = 0;
    178     GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
    179 
    180     cairo_clip_extents(cr, &x0, &y0, &x1, &y1);
    181     FloatRect clipRect(x0, y0, x1 - x0, y1 - y0);
    182 
    183     FloatPoint rectLocation = shadowRect.location();
    184 
    185     // Reduce the shadow rect using the clip area.
    186     if (!clipRect.contains(shadowRect)) {
    187         shadowRect.intersect(clipRect);
    188         if (shadowRect.isEmpty())
    189             return;
    190         shadowRect.inflate(radius);
    191         shadowBufferSize = IntSize(shadowRect.width(), shadowRect.height());
    192     }
    193 
    194     shadowOffset = rectLocation - shadowRect.location();
    195 
    196     // Create suitably-sized ImageBuffer to hold the shadow.
    197     OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
    198 
    199     // Draw shadow into a new ImageBuffer.
    200     cairo_t* shadowContext = shadowBuffer->context()->platformContext();
    201     copyContextProperties(cr, shadowContext);
    202     cairo_translate(shadowContext, -rect.x() + radius + shadowOffset.width(), -rect.y() + radius + shadowOffset.height());
    203     cairo_new_path(shadowContext);
    204     OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
    205     cairo_append_path(shadowContext, path.get());
    206 
    207     if (fillShadow)
    208         setPlatformFill(context, shadowContext, gcp);
    209     if (strokeShadow)
    210         setPlatformStroke(context, shadowContext, gcp);
    211 
    212     context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
    213 #endif
     139enum PathDrawingStyle {
     140    Fill = 1,
     141    Stroke = 2,
     142    FillAndStroke = Fill + Stroke
     143};
     144
     145static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* contextPrivate, PathDrawingStyle drawingStyle)
     146{
     147    ContextShadow* shadow = context->contextShadow();
     148    ASSERT(shadow);
     149    if (shadow->m_type == ContextShadow::NoShadow)
     150        return;
     151
     152    // Calculate the extents of the rendered solid paths.
     153    cairo_t* cairoContext = context->platformContext();
     154    cairo_path_t* path = cairo_copy_path(cairoContext);
     155
     156    FloatRect solidFigureExtents;
     157    double x0 = 0;
     158    double x1 = 0;
     159    double y0 = 0;
     160    double y1 = 0;
     161    if (drawingStyle & Stroke) {
     162        cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1);
     163        solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0);
     164    }
     165    if (drawingStyle & Fill) {
     166        cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1);
     167        FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0);
     168        solidFigureExtents.unite(fillExtents);
     169    }
     170
     171    cairo_t* shadowContext = shadow->beginShadowLayer(cairoContext, solidFigureExtents);
     172    if (!shadowContext)
     173        return;
     174
     175    // It's important to copy the context properties to the new shadow
     176    // context to preserve things such as the fill rule and stroke width.
     177    copyContextProperties(cairoContext, shadowContext);
     178    cairo_append_path(shadowContext, path);
     179
     180    if (drawingStyle & Fill)
     181        setPlatformFill(context, shadowContext, contextPrivate);
     182    if (drawingStyle & Stroke)
     183        setPlatformStroke(context, shadowContext, contextPrivate);
     184
     185    shadow->endShadowLayer(cairoContext);
    214186}
    215187
     
    217189{
    218190    cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
    219     drawPathShadow(context, gcp, true, false);
     191    drawPathShadow(context, gcp, Fill);
    220192
    221193    setPlatformFill(context, cairoContext, gcp);
     
    225197static void strokeCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
    226198{
    227     drawPathShadow(context, gcp, false, true);
     199    drawPathShadow(context, gcp, Stroke);
    228200    setPlatformStroke(context, cairoContext, gcp);
    229201    cairo_new_path(cairoContext);
     
    262234    cairo_save(m_data->cr);
    263235    m_data->save();
     236    m_data->shadowStack.append(m_data->shadow);
    264237}
    265238
     
    268241    cairo_restore(m_data->cr);
    269242    m_data->restore();
     243
     244    if (m_data->shadowStack.isEmpty())
     245        m_data->shadow = ContextShadow();
     246    else {
     247        m_data->shadow = m_data->shadowStack.last();
     248        m_data->shadowStack.removeLast();
     249    }
    270250}
    271251
     
    583563
    584564    cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
    585     drawPathShadow(this, m_common, true, true);
     565    drawPathShadow(this, m_common, FillAndStroke);
    586566
    587567    setPlatformFill(this, cr, m_common);
     
    602582}
    603583
    604 static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
    605 {
    606 #if ENABLE(FILTERS)
    607     FloatSize shadowOffset;
    608     float shadowBlur;
    609     Color shadowColor;
    610     if (!context->getShadow(shadowOffset, shadowBlur, shadowColor))
    611         return;
    612 
    613     IntSize shadowBufferSize;
    614     FloatRect shadowRect;
    615     float radius = 0;
    616     GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur);
    617 
    618     // Draw shadow into a new ImageBuffer
    619     OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
    620     GraphicsContext* shadowContext = shadowBuffer->context();
    621     shadowContext->fillRect(FloatRect(FloatPoint(radius, radius), rect.size()), rectColor, DeviceColorSpace);
    622 
    623     context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
    624 #endif
    625 }
    626 
    627 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
    628 {
    629     if (paintingDisabled())
    630         return;
    631 
    632     drawBorderlessRectShadow(this, rect, color);
     584void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
     585{
     586    if (paintingDisabled())
     587        return;
     588
     589    if (m_data->hasShadow())
     590        m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
     591
    633592    if (color.alpha())
    634593        fillRectSourceOver(m_data->cr, rect, color);
     
    900859}
    901860
    902 void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace)
    903 {
    904     // Cairo doesn't support shadows natively, they are drawn manually in the draw*
    905     // functions
    906 
     861void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
     862{
     863    // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
    907864    if (m_common->state.shadowsIgnoreTransforms) {
    908865        // Meaning that this graphics context is associated with a CanvasRenderingContext
    909866        // We flip the height since CG and HTML5 Canvas have opposite Y axis
    910867        m_common->state.shadowOffset = FloatSize(size.width(), -size.height());
    911     }
    912 }
    913 
    914 void GraphicsContext::applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, FloatRect& shadowRect, float radius)
    915 {
    916 #if ENABLE(FILTERS)
    917     setColor(m_data->cr, shadowColor);
    918     PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(buffer, shadowRect, radius));
    919     cairo_mask_surface(m_data->cr, shadowMask.get(), shadowRect.x(), shadowRect.y());
    920 #endif
    921 }
    922 
    923 PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<ImageBuffer> buffer, FloatRect& shadowRect, float radius)
    924 {
    925 #if ENABLE(FILTERS)
    926     if (!radius)
    927         return buffer->m_data.m_surface;
    928 
    929     FloatPoint blurRadius = FloatPoint(radius, radius);
    930     float stdDeviation = FEGaussianBlur::calculateStdDeviation(radius);
    931     if (!stdDeviation)
    932         return buffer->m_data.m_surface;
    933 
    934     // create filter
    935     IntRect filterRegion = IntRect(IntPoint(), roundedIntSize(shadowRect.size()));
    936     RefPtr<Filter> filter = ImageBufferFilter::create(filterRegion);
    937     filter->setSourceImage(buffer);
    938     RefPtr<FilterEffect> source = SourceGraphic::create();
    939     source->setIsAlphaImage(true);
    940     RefPtr<FilterEffect> blur = FEGaussianBlur::create(stdDeviation, stdDeviation);
    941     blur->setMaxEffectRect(filterRegion);
    942     FilterEffectVector& inputEffects = blur->inputEffects();
    943     inputEffects.append(source.get());
    944     blur->apply(filter.get());
    945 
    946     // Calculate shadow region for context
    947     shadowRect.move(blur->absolutePaintRect().location().x(), blur->absolutePaintRect().location().y());
    948     shadowRect.setSize(blur->absolutePaintRect().size());
    949     return blur->resultImage()->m_data.m_surface;
    950 #endif
    951 }
    952 
     868        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
     869    } else
     870        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
     871}
     872
     873ContextShadow* GraphicsContext::contextShadow()
     874{
     875    return &m_data->shadow;
     876}
    953877
    954878void GraphicsContext::clearPlatformShadow()
    955879{
    956     notImplemented();
     880    m_data->shadow.clear();
    957881}
    958882
     
    11871111}
    11881112
    1189 /*
    1190   This function uses tiling to improve the performance of the shadow
    1191   drawing of rounded rectangles. The code basically does the following
    1192   steps:
    1193 
    1194      1. Calculate the minimum rectangle size required to create the
    1195      tiles
    1196 
    1197      2. If that size is smaller than the real rectangle render the new
    1198      small rectangle and its shadow in a new surface, in other case
    1199      render the shadow of the real rectangle in the destination
    1200      surface.
    1201 
    1202      3. Calculate the sizes and positions of the tiles and their
    1203      destinations and use drawPattern to render the final shadow. The
    1204      code divides the rendering in 8 tiles:
    1205 
    1206         1 | 2 | 3
    1207        -----------
    1208         4 |   | 5
    1209        -----------
    1210         6 | 7 | 8
    1211 
    1212      The corners are directly copied from the small rectangle to the
    1213      real one and the side tiles are 1 pixel width, we use them as
    1214 
    1215      tiles to cover the destination side. The corner tiles are bigger
    1216      than just the side of the rounded corner, we need to increase it
    1217      because the modifications caused by the corner over the blur
    1218      effect. We fill the central part with solid color to complete the
    1219      shadow.
    1220  */
    1221 void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace)
    1222 {
    1223 #if ENABLE(FILTERS)
    1224     FloatSize shadowSize;
    1225     float shadowBlur;
    1226     Color shadowColor;
    1227     if (!getShadow(shadowSize, shadowBlur, shadowColor))
    1228         return;
    1229 
    1230     // Calculate filter values to create appropriate shadow.
    1231     cairo_t* cr = m_data->cr;
    1232 
    1233     IntSize shadowBufferSize;
    1234     FloatRect shadowRect;
    1235     float blurRadius = 0;
    1236     GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, blurRadius, rect, shadowSize, shadowBlur);
    1237 
    1238     // Size of the tiling side.
    1239     int sideTileWidth = 1;
    1240     float radiusTwice = blurRadius * 2;
    1241 
    1242     // Find the extra space needed from the curve of the corners.
    1243     int extraWidthFromCornerRadii = radiusTwice + max(topLeftRadius.width(), bottomLeftRadius.width()) +
    1244                                     radiusTwice + max(topRightRadius.width(), bottomRightRadius.width());
    1245     int extraHeightFromCornerRadii = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) +
    1246                                      radiusTwice + max(bottomLeftRadius.height(), bottomRightRadius.height());
    1247 
    1248     // The length of a side of the buffer is the enough space for four blur radii,
    1249     // the radii of the corners, and then 1 pixel to draw the side tiles.
    1250     IntSize smallBufferSize = IntSize(sideTileWidth + extraWidthFromCornerRadii,
    1251                                       sideTileWidth + extraHeightFromCornerRadii);
    1252 
    1253     if ((smallBufferSize.width() > shadowBufferSize.width()) || (smallBufferSize.height() > shadowBufferSize.height()) || (blurRadius <= 0)) {
    1254         // Create suitably-sized ImageBuffer to hold the shadow.
    1255         OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
    1256         if (!shadowBuffer)
    1257             return;
    1258 
    1259         // Draw shadow into a new ImageBuffer.
    1260         cairo_t* shadowContext = shadowBuffer->context()->platformContext();
    1261         copyContextProperties(cr, shadowContext);
    1262         cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius);
    1263         cairo_new_path(shadowContext);
    1264         OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
    1265         cairo_append_path(shadowContext, path.get());
    1266 
    1267         setPlatformFill(this, shadowContext, m_common);
    1268 
    1269         applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, blurRadius);
    1270 
    1271         return;
    1272     }
    1273 
    1274     OwnPtr<ImageBuffer> smallBuffer = ImageBuffer::create(smallBufferSize);
    1275     if (!smallBuffer)
    1276         return;
    1277 
    1278     FloatRect smallRect = FloatRect(blurRadius, blurRadius, smallBufferSize.width() - radiusTwice, smallBufferSize.height() - radiusTwice);
    1279 
    1280     // Draw shadow into a new ImageBuffer.
    1281     cairo_t* smallBufferContext = smallBuffer->context()->platformContext();
    1282     copyContextProperties(cr, smallBufferContext);
    1283 
    1284     Path path;
    1285     path.addRoundedRect(smallRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    1286     appendWebCorePathToCairoContext(smallBuffer->context()->platformContext(), path);
    1287     setPlatformFill(this, smallBufferContext, m_common);
    1288 
    1289     OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(smallBufferSize);
    1290     if (!shadowBuffer)
    1291         return;
    1292 
    1293     smallRect.setSize(smallBufferSize);
    1294 
    1295     PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(smallBuffer.release(), smallRect, blurRadius));
    1296 
    1297     cairo_t* shadowContext = shadowBuffer->context()->platformContext();
    1298     setColor(shadowContext, shadowColor);
    1299     cairo_mask_surface(shadowContext, shadowMask.get(), 0, 0);
    1300 
    1301     // Fill the internal part of the shadow.
    1302     shadowRect.inflate(-radiusTwice);
    1303     if (!shadowRect.isEmpty()) {
    1304         cairo_save(cr);
    1305         path.clear();
    1306         path.addRoundedRect(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    1307         appendWebCorePathToCairoContext(cr, path);
    1308         setColor(cr, shadowColor);
    1309         cairo_fill(cr);
    1310         cairo_restore(cr);
    1311     }
    1312     shadowRect.inflate(radiusTwice);
    1313 
    1314     // Draw top side.
    1315     FloatRect tileRect = FloatRect(radiusTwice + topLeftRadius.width(), 0, sideTileWidth, radiusTwice);
    1316     FloatRect destRect = tileRect;
    1317     destRect.move(shadowRect.x(), shadowRect.y());
    1318     destRect.setWidth(shadowRect.width() - topLeftRadius.width() - topRightRadius.width() - blurRadius * 4);
    1319     FloatPoint phase = getPhase(destRect, tileRect);
    1320     AffineTransform patternTransform;
    1321     patternTransform.makeIdentity();
    1322     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1323 
    1324     // Draw the bottom side.
    1325     tileRect = FloatRect(radiusTwice + bottomLeftRadius.width(), smallBufferSize.height() - radiusTwice, sideTileWidth, radiusTwice);
    1326     destRect = tileRect;
    1327     destRect.move(shadowRect.x(), shadowRect.y() + radiusTwice + rect.height() - smallBufferSize.height());
    1328     destRect.setWidth(shadowRect.width() - bottomLeftRadius.width() - bottomRightRadius.width() - blurRadius * 4);
    1329     phase = getPhase(destRect, tileRect);
    1330     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1331 
    1332     // Draw the right side.
    1333     tileRect = FloatRect(smallBufferSize.width() - radiusTwice, radiusTwice + topRightRadius.height(), radiusTwice, sideTileWidth);
    1334     destRect = tileRect;
    1335     destRect.move(shadowRect.x() + radiusTwice + rect.width() - smallBufferSize.width(), shadowRect.y());
    1336     destRect.setHeight(shadowRect.height() - topRightRadius.height() - bottomRightRadius.height() - blurRadius * 4);
    1337     phase = getPhase(destRect, tileRect);
    1338     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1339 
    1340     // Draw the left side.
    1341     tileRect = FloatRect(0, radiusTwice + topLeftRadius.height(), radiusTwice, sideTileWidth);
    1342     destRect = tileRect;
    1343     destRect.move(shadowRect.x(), shadowRect.y());
    1344     destRect.setHeight(shadowRect.height() - topLeftRadius.height() - bottomLeftRadius.height() - blurRadius * 4);
    1345     phase = FloatPoint(destRect.x() - tileRect.x(), destRect.y() - tileRect.y());
    1346     shadowBuffer->drawPattern(this, tileRect, patternTransform,
    1347                               phase, colorSpace, CompositeSourceOver, destRect);
    1348 
    1349     // Draw the top left corner.
    1350     tileRect = FloatRect(0, 0, radiusTwice + topLeftRadius.width(), radiusTwice + topLeftRadius.height());
    1351     destRect = tileRect;
    1352     destRect.move(shadowRect.x(), shadowRect.y());
    1353     phase = getPhase(destRect, tileRect);
    1354     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1355 
    1356     // Draw the top right corner.
    1357     tileRect = FloatRect(smallBufferSize.width() - radiusTwice - topRightRadius.width(), 0, radiusTwice + topRightRadius.width(), radiusTwice + topRightRadius.height());
    1358     destRect = tileRect;
    1359     destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y());
    1360     phase = getPhase(destRect, tileRect);
    1361     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1362 
    1363     // Draw the bottom right corner.
    1364     tileRect = FloatRect(smallBufferSize.width() - radiusTwice - bottomRightRadius.width(), smallBufferSize.height() - radiusTwice - bottomRightRadius.height(), radiusTwice + bottomRightRadius.width(), radiusTwice + bottomRightRadius.height());
    1365     destRect = tileRect;
    1366     destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
    1367     phase = getPhase(destRect, tileRect);
    1368     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1369 
    1370     // Draw the bottom left corner.
    1371     tileRect = FloatRect(0, smallBufferSize.height() - radiusTwice - bottomLeftRadius.height(), radiusTwice + bottomLeftRadius.width(), radiusTwice + bottomLeftRadius.height());
    1372     destRect = tileRect;
    1373     destRect.move(shadowRect.x(), shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice);
    1374     phase = getPhase(destRect, tileRect);
    1375     shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect);
    1376 #endif
    1377 }
    1378 
    13791113void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
    13801114{
    13811115    if (paintingDisabled())
    13821116        return;
     1117
     1118    if (m_data->hasShadow())
     1119        m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
    13831120
    13841121    cairo_t* cr = m_data->cr;
     
    13881125    appendWebCorePathToCairoContext(cr, path);
    13891126    setColor(cr, color);
    1390     drawPathShadow(this, m_common, true, false);
    13911127    cairo_fill(cr);
    13921128    cairo_restore(cr);
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h

    r66047 r69681  
    9999    CairoPath m_pendingPath;
    100100
     101    ContextShadow shadow;
     102    Vector<ContextShadow> shadowStack;
     103    bool hasShadow() const { return shadow.m_type != ContextShadow::NoShadow; }
     104
    101105#if PLATFORM(GTK)
    102106    GdkEventExpose* expose;
  • trunk/WebCore/platform/graphics/cairo/ImageCairo.cpp

    r69015 r69681  
    3434#include "CairoUtilities.h"
    3535#include "Color.h"
     36#include "ContextShadow.h"
    3637#include "FloatRect.h"
    3738#include "PlatformRefPtrCairo.h"
     
    135136    cairo_pattern_set_matrix(pattern, &matrix);
    136137
    137     // Draw the shadow
    138 #if ENABLE(FILTERS)
    139     FloatSize shadowOffset;
    140     float shadowBlur;
    141     Color shadowColor;
    142     if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) {
    143         IntSize shadowBufferSize;
    144         FloatRect shadowRect;
    145         float radius = 0;
    146         context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur);
    147         shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() *  context->getAlpha()) / 255.f);
    148 
    149         //draw shadow into a new ImageBuffer
    150         OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
    151         cairo_t* shadowContext = shadowBuffer->context()->platformContext();
    152         cairo_set_source(shadowContext, pattern);
    153         cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
    154         cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
    155         cairo_fill(shadowContext);
    156 
    157         context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius);
     138    ContextShadow* shadow = context->contextShadow();
     139    ASSERT(shadow);
     140    if (shadow->m_type != ContextShadow::NoShadow) {
     141        cairo_t* shadowContext = shadow->beginShadowLayer(cr, dstRect);
     142        if (shadowContext) {
     143            cairo_translate(shadowContext, dstRect.x(), dstRect.y());
     144            cairo_set_source(shadowContext, pattern);
     145            cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
     146            cairo_fill(shadowContext);
     147            shadow->endShadowLayer(cr);
     148        }
    158149    }
    159 #endif
    160150
    161151    // Draw the image.
Note: See TracChangeset for help on using the changeset viewer.