Changeset 91914 in webkit


Ignore:
Timestamp:
Jul 28, 2011 1:13:23 AM (13 years ago)
Author:
Martin Robinson
Message:

[Cairo] Switch from ContextShadow to ShadowBlur
https://bugs.webkit.org/show_bug.cgi?id=64744

Source/WebCore:

Use ShadowBlur in the Cairo backend instead of ContextShadow. This allows us
to share shadowing code with Qt and Mac ports and to correct some broken
shadow rendering.

Reviewed by Dirk Schulze.

  • CMakeLists.txt: Remove ContextShadow from the build.
  • CMakeListsEfl.txt: Ditto.
  • GNUmakefile.list.am: Add ShadowBlur source files and remove ContextShadow

source files.

  • platform/graphics/GraphicsContext.cpp:Add #ifdefs to support ShadowBlur for Cairo.
  • platform/graphics/GraphicsContext.h: Remove Cairo ContextShadow code.
  • platform/graphics/ShadowBlur.cpp:

(WebCore::ShadowBlur::drawInsetShadowWithTiling): Since the ShadowBlur is a property
of the GraphicsContext, we cannot clear the GraphicsContext shadow until we have
finished using properties like m_offset. If we clear the GrahpicsContext shadow
before using these properties, they will be zero when we try to use them.
(WebCore::ShadowBlur::drawRectShadowWithTiling):Ditto.
(WebCore::ShadowBlur::drawLayerPieces): Ditto.
(WebCore::ShadowBlur::beginShadowLayer):Cairo is the first port to keep ShadowBlur
as a persistent property of GraphicsContext and use drawRectShadow and drawInsetShadow.
Thus, we must manually clear the cached tiling values so that ShadowBlur does not
try to reuse the scratch buffer for rectangular shadows after using beginShadowLayer
and endShadowLayer.
(WebCore::ShadowBlur::mustUseShadowBlur): Moved this method from the Qt port to
this cross-platform location.

  • platform/graphics/ShadowBlur.h: Added new method declaration.
  • platform/graphics/cairo/ContextShadowCairo.cpp: Removed.
  • platform/graphics/cairo/FontCairo.cpp: Switched to using ShadowBlur.

(WebCore::drawGlyphsShadow):Ditto.

  • platform/graphics/cairo/GraphicsContextCairo.cpp: Switch to using ShadowBlur.

(WebCore::drawPathShadow): ShadowBlur has slightly different semantics than
ContextShadow. When filling the shadow layer, we do not need to use the fill
alpha. We also need to restore the Cairo path to the target context after
endShadowLayer as it destroys the current path.

  • platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h: Switch to using ShadowBlur.
  • platform/graphics/cairo/ImageCairo.cpp: Ditto.
  • platform/graphics/cairo/PlatformContextCairo.cpp:

(WebCore::PlatformContextCairo::drawSurfaceToContext):Ditto.
(WebCore::PlatformContextCairo::prepareForStroking): Add a mode ignoring alpha.

  • platform/graphics/cairo/PlatformContextCairo.h: Ditto.

(WebCore::PlatformContextCairo::shadowBlur):Added.

  • platform/graphics/gtk/FontGtk.cpp: Update to use ShadowBlur.
  • platform/graphics/qt/GraphicsContextQt.cpp: Switch to using the new version of mustUseShadowBlur.

LayoutTests:

Update test results, which are now correct after switch to ShadowBlur.

Reviewed by Dirk Schulze.

  • fast/box-shadow/box-shadow-radius-expected.png: Added.
  • fast/box-shadow/box-shadow-transformed-expected.png: Added.
  • fast/box-shadow/inset-box-shadow-radius-expected.png: Added.
  • fast/box-shadow/inset-shadow-large-offset-expected.png:
  • fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png: Added.
  • fast/box-shadow/scaled-box-shadow-expected.png: Added.
  • fast/box-shadow/shadow-tiling-artifact-expected.png: Added.
  • fast/box-shadow/spread-multiple-inset-expected.png: Added.
  • fast/box-shadow/spread-multiple-normal-expected.png: Added.
  • platform/gtk/Skipped: Skip a test, which now has a bug revealed.
  • platform/gtk/fast/box-shadow/basic-shadows-expected.png:
  • platform/gtk/fast/box-shadow/border-radius-big-expected.png:
  • platform/gtk/fast/box-shadow/inset-box-shadows-expected.png:
  • platform/gtk/fast/box-shadow/inset-expected.png:
  • platform/gtk/fast/box-shadow/shadow-buffer-partial-expected.png:
  • platform/gtk/fast/box-shadow/single-pixel-shadow-expected.png:
  • platform/gtk/fast/box-shadow/spread-expected.png:
  • platform/gtk/fast/box-shadow/transform-fringing-expected.png:
Location:
trunk
Files:
8 added
1 deleted
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r91912 r91914  
     12011-07-22  Martin Robinson  <mrobinson@igalia.com>
     2
     3        [Cairo] Switch from ContextShadow to ShadowBlur
     4        https://bugs.webkit.org/show_bug.cgi?id=64744
     5
     6        Update test results, which are now correct after switch to ShadowBlur.
     7
     8        Reviewed by Dirk Schulze.
     9
     10        * fast/box-shadow/box-shadow-radius-expected.png: Added.
     11        * fast/box-shadow/box-shadow-transformed-expected.png: Added.
     12        * fast/box-shadow/inset-box-shadow-radius-expected.png: Added.
     13        * fast/box-shadow/inset-shadow-large-offset-expected.png:
     14        * fast/box-shadow/inset-with-extraordinary-radii-and-border-expected.png: Added.
     15        * fast/box-shadow/scaled-box-shadow-expected.png: Added.
     16        * fast/box-shadow/shadow-tiling-artifact-expected.png: Added.
     17        * fast/box-shadow/spread-multiple-inset-expected.png: Added.
     18        * fast/box-shadow/spread-multiple-normal-expected.png: Added.
     19        * platform/gtk/Skipped: Skip a test, which now has a bug revealed.
     20        * platform/gtk/fast/box-shadow/basic-shadows-expected.png:
     21        * platform/gtk/fast/box-shadow/border-radius-big-expected.png:
     22        * platform/gtk/fast/box-shadow/inset-box-shadows-expected.png:
     23        * platform/gtk/fast/box-shadow/inset-expected.png:
     24        * platform/gtk/fast/box-shadow/shadow-buffer-partial-expected.png:
     25        * platform/gtk/fast/box-shadow/single-pixel-shadow-expected.png:
     26        * platform/gtk/fast/box-shadow/spread-expected.png:
     27        * platform/gtk/fast/box-shadow/transform-fringing-expected.png:
     28
    1292011-07-27  Ryosuke Niwa  <rniwa@webkit.org>
    230
  • trunk/LayoutTests/platform/gtk/Skipped

    r91797 r91914  
    15671567# For now, Web Audio API is disabled
    15681568webaudio/
     1569
     1570# Text shadow extents are calculated incorrectly
     1571# https://bugs.webkit.org/show_bug.cgi?id=65035
     1572fast/canvas/fillText-shadow.html
  • trunk/Source/WebCore/CMakeLists.txt

    r91910 r91914  
    10501050    platform/graphics/BitmapImage.cpp
    10511051    platform/graphics/Color.cpp
    1052     platform/graphics/ContextShadow.cpp
    10531052    platform/graphics/FloatPoint.cpp
    10541053    platform/graphics/FloatPoint3D.cpp
  • trunk/Source/WebCore/CMakeListsEfl.txt

    r89197 r91914  
    8888  LIST(APPEND WebCore_SOURCES
    8989    platform/graphics/cairo/CairoUtilities.cpp
    90     platform/graphics/cairo/ContextShadowCairo.cpp
    9190    platform/graphics/cairo/FontCairo.cpp
    9291    platform/graphics/cairo/GradientCairo.cpp
  • trunk/Source/WebCore/ChangeLog

    r91910 r91914  
     12011-07-22  Martin Robinson  <mrobinson@igalia.com>
     2
     3        [Cairo] Switch from ContextShadow to ShadowBlur
     4        https://bugs.webkit.org/show_bug.cgi?id=64744
     5
     6        Use ShadowBlur in the Cairo backend instead of ContextShadow. This allows us
     7        to share shadowing code with Qt and Mac ports and to correct some broken
     8        shadow rendering.
     9
     10        Reviewed by Dirk Schulze.
     11
     12        * CMakeLists.txt: Remove ContextShadow from the build.
     13        * CMakeListsEfl.txt: Ditto.
     14        * GNUmakefile.list.am: Add ShadowBlur source files and remove ContextShadow
     15        source files.
     16        * platform/graphics/GraphicsContext.cpp:Add #ifdefs to support ShadowBlur for Cairo.
     17        * platform/graphics/GraphicsContext.h: Remove Cairo ContextShadow code.
     18        * platform/graphics/ShadowBlur.cpp:
     19        (WebCore::ShadowBlur::drawInsetShadowWithTiling): Since the ShadowBlur is a property
     20        of the GraphicsContext, we cannot clear the GraphicsContext shadow until we have
     21        finished using properties like m_offset. If we clear the GrahpicsContext shadow
     22        before using these properties, they will be zero when we try to use them.
     23        (WebCore::ShadowBlur::drawRectShadowWithTiling):Ditto.
     24        (WebCore::ShadowBlur::drawLayerPieces): Ditto.
     25        (WebCore::ShadowBlur::beginShadowLayer):Cairo is the first port to keep ShadowBlur
     26        as a persistent property of GraphicsContext and use drawRectShadow and drawInsetShadow.
     27        Thus, we must manually clear the cached tiling values so that ShadowBlur does not
     28        try to reuse the scratch buffer for rectangular shadows after using beginShadowLayer
     29        and endShadowLayer.
     30        (WebCore::ShadowBlur::mustUseShadowBlur): Moved this method from the Qt port to
     31        this cross-platform location.
     32        * platform/graphics/ShadowBlur.h: Added new method declaration.
     33        * platform/graphics/cairo/ContextShadowCairo.cpp: Removed.
     34        * platform/graphics/cairo/FontCairo.cpp: Switched to using ShadowBlur.
     35        (WebCore::drawGlyphsShadow):Ditto.
     36        * platform/graphics/cairo/GraphicsContextCairo.cpp: Switch to using ShadowBlur.
     37        (WebCore::drawPathShadow): ShadowBlur has slightly different semantics than
     38        ContextShadow. When filling the shadow layer, we do not need to use the fill
     39        alpha. We also need to restore the Cairo path to the target context after
     40        endShadowLayer as it destroys the current path.
     41        * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h: Switch to using ShadowBlur.
     42        * platform/graphics/cairo/ImageCairo.cpp: Ditto.
     43        * platform/graphics/cairo/PlatformContextCairo.cpp:
     44        (WebCore::PlatformContextCairo::drawSurfaceToContext):Ditto.
     45        (WebCore::PlatformContextCairo::prepareForStroking): Add a mode ignoring alpha.
     46        * platform/graphics/cairo/PlatformContextCairo.h: Ditto.
     47        (WebCore::PlatformContextCairo::shadowBlur):Added.
     48        * platform/graphics/gtk/FontGtk.cpp: Update to use ShadowBlur.
     49        * platform/graphics/qt/GraphicsContextQt.cpp: Switch to using the new version of mustUseShadowBlur.
     50
    1512011-07-27  Gyuyoung Kim  <gyuyoung.kim@samsung.com>
    252
  • trunk/Source/WebCore/GNUmakefile.list.am

    r91811 r91914  
    23952395        Source/WebCore/platform/graphics/Color.h \
    23962396        Source/WebCore/platform/graphics/ColorSpace.h \
    2397         Source/WebCore/platform/graphics/ContextShadow.cpp \
    2398         Source/WebCore/platform/graphics/ContextShadow.h \
    23992397        Source/WebCore/platform/graphics/DashArray.h \
    24002398        Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp \
    24012399        Source/WebCore/platform/graphics/cairo/CairoUtilities.h \
    2402         Source/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp \
    24032400        Source/WebCore/platform/graphics/cairo/FloatRectCairo.cpp \
    24042401        Source/WebCore/platform/graphics/cairo/FontCairo.cpp \
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp

    r91496 r91914  
    582582}
    583583
    584 #if !USE(CG) && !PLATFORM(QT)
     584#if !USE(CG) && !PLATFORM(QT) && !USE(CAIRO)
    585585IntRect GraphicsContext::clipBounds() const
    586586{
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.h

    r91496 r91914  
    4242#elif USE(CAIRO)
    4343namespace WebCore {
    44 class ContextShadow;
    4544class PlatformContextCairo;
    4645}
     
    492491#endif
    493492
    494 #if USE(CAIRO)
    495         ContextShadow* contextShadow();
    496 #endif
    497 
    498493#if PLATFORM(QT)
    499494        ShadowBlur* shadowBlur();
  • trunk/Source/WebCore/platform/graphics/ShadowBlur.cpp

    r90832 r91914  
    667667void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedRect::Radii& radii, const IntSize& templateSize, const IntSize& edgeSize)
    668668{
    669     GraphicsContextStateSaver stateSaver(*graphicsContext);
    670     graphicsContext->clearShadow();
    671 
    672669    m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
    673670    if (!m_layerImage)
     
    716713    {
    717714        GraphicsContextStateSaver fillStateSaver(*graphicsContext);
     715        graphicsContext->clearShadow();
    718716        graphicsContext->setFillRule(RULE_EVENODD);
    719717        graphicsContext->setFillColor(m_color, m_colorSpace);
     
    729727void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedRect::Radii& radii, const IntSize& templateSize, const IntSize& edgeSize)
    730728{
    731     GraphicsContextStateSaver stateSaver(*graphicsContext);
    732     graphicsContext->clearShadow();
    733 
    734729    m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
    735730    if (!m_layerImage)
     
    788783            GraphicsContextStateSaver stateSaver(*graphicsContext);
    789784            graphicsContext->setFillColor(m_color, m_colorSpace);
     785            graphicsContext->clearShadow();
    790786            graphicsContext->fillRect(shadowInterior);
    791787        }
    792788    }
     789
     790    GraphicsContextStateSaver stateSaver(*graphicsContext);
     791    graphicsContext->clearShadow();
     792    graphicsContext->setFillColor(m_color, m_colorSpace);
    793793
    794794    // Note that drawing the ImageBuffer is faster than creating a Image and drawing that,
     
    875875        return 0;
    876876
     877    // We reset the scratch buffer values here, because the buffer will no longer contain
     878    // data from any previous rectangle or inset shadows drawn via the tiling path.
     879    ScratchBuffer::shared().setLastShadowValues(FloatSize(), Color::black, ColorSpaceDeviceRGB, IntRect(), RoundedRect::Radii());
    877880    m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
    878881
    879882    GraphicsContext* shadowContext = m_layerImage->context();
    880883    shadowContext->save();
    881     shadowContext->clearRect(FloatRect(0, 0, m_layerSize.width(), m_layerSize.height()));
     884
     885    // Add a pixel to avoid later edge aliasing when rotated.
     886    shadowContext->clearRect(FloatRect(0, 0, m_layerSize.width() + 1, m_layerSize.height() + 1));
    882887
    883888    shadowContext->translate(m_layerContextTranslation);
     
    899904}
    900905
     906#if PLATFORM(QT) || USE(CAIRO)
     907bool ShadowBlur::mustUseShadowBlur(GraphicsContext* context) const
     908{
     909    // We can't avoid ShadowBlur, since the shadow has blur.
     910    if (type() == BlurShadow)
     911        return true;
     912    // We can avoid ShadowBlur and optimize, since we're not drawing on a
     913    // canvas and box shadows are affected by the transformation matrix.
     914    if (!shadowsIgnoreTransforms())
     915        return false;
     916    // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
     917    if (context->getCTM().isIdentity())
     918        return false;
     919    // Otherwise, no chance avoiding ShadowBlur.
     920    return true;
     921}
     922#endif
     923
    901924} // namespace WebCore
  • trunk/Source/WebCore/platform/graphics/ShadowBlur.h

    r90832 r91914  
    7070
    7171    ShadowType type() const { return m_type; }
     72
     73#if PLATFORM(QT) || USE(CAIRO)
     74    bool mustUseShadowBlur(GraphicsContext*) const;
     75#endif
     76
    7277private:
    7378    void updateShadowBlurValues();
  • trunk/Source/WebCore/platform/graphics/cairo/FontCairo.cpp

    r90041 r91914  
    3333#include "AffineTransform.h"
    3434#include "CairoUtilities.h"
    35 #include "ContextShadow.h"
    3635#include "GlyphBuffer.h"
    3736#include "Gradient.h"
     
    4039#include "ImageBuffer.h"
    4140#include "Pattern.h"
     41#include "ShadowBlur.h"
    4242#include "SimpleFontData.h"
    4343
     
    7777static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
    7878{
    79     ContextShadow* shadow = graphicsContext->contextShadow();
    80     ASSERT(shadow);
     79    ShadowBlur& shadow = graphicsContext->platformContext()->shadowBlur();
    8180
    82     if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow->m_type == ContextShadow::NoShadow)
     81    if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow.type() == ShadowBlur::NoShadow)
    8382        return;
    8483
    85     if (!shadow->mustUseContextShadow(graphicsContext)) {
    86         // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
     84    if (!shadow.mustUseShadowBlur(graphicsContext)) {
     85        // Optimize non-blurry shadows, by just drawing text without the ShadowBlur.
    8786        cairo_t* context = graphicsContext->platformContext()->cr();
    8887        cairo_save(context);
    89         cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
    90         setSourceRGBAFromColor(context, shadow->m_color);
     88
     89        FloatSize shadowOffset(graphicsContext->state().shadowOffset);
     90        cairo_translate(context, shadowOffset.width(), shadowOffset.height());
     91        setSourceRGBAFromColor(context, graphicsContext->state().shadowColor);
    9192        drawGlyphsToContext(context, font, glyphs, numGlyphs);
     93
    9294        cairo_restore(context);
    9395        return;
     
    9799    cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
    98100    FloatRect fontExtentsRect(point.x(), point.y() - extents.height, extents.width, extents.height);
    99     cairo_t* shadowContext = shadow->beginShadowLayer(graphicsContext, fontExtentsRect);
    100     if (shadowContext) {
    101         drawGlyphsToContext(shadowContext, font, glyphs, numGlyphs);
    102         shadow->endShadowLayer(graphicsContext);
     101    if (GraphicsContext* shadowContext = shadow.beginShadowLayer(graphicsContext, fontExtentsRect)) {
     102        drawGlyphsToContext(shadowContext->platformContext()->cr(), font, glyphs, numGlyphs);
     103        shadow.endShadowLayer(graphicsContext);
    103104    }
    104105}
  • trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r89374 r91914  
    3737#include "AffineTransform.h"
    3838#include "CairoUtilities.h"
    39 #include "ContextShadow.h"
    4039#include "FloatConversion.h"
    4140#include "FloatRect.h"
     
    5049#include "PlatformPathCairo.h"
    5150#include "RefPtrCairo.h"
     51#include "ShadowBlur.h"
    5252#include "SimpleFontData.h"
    5353#include <cairo.h>
     
    9898static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle)
    9999{
    100     ContextShadow* shadow = context->contextShadow();
    101     ASSERT(shadow);
    102     if (shadow->m_type == ContextShadow::NoShadow)
     100    ShadowBlur& shadow = context->platformContext()->shadowBlur();
     101    if (shadow.type() == ShadowBlur::NoShadow)
    103102        return;
    104103
     
    122121    }
    123122
    124     cairo_t* shadowContext = shadow->beginShadowLayer(context, solidFigureExtents);
     123    GraphicsContext* shadowContext = shadow.beginShadowLayer(context, solidFigureExtents);
    125124    if (!shadowContext)
    126125        return;
     126
     127    cairo_t* cairoShadowContext = shadowContext->platformContext()->cr();
    127128
    128129    // It's important to copy the context properties to the new shadow
    129130    // context to preserve things such as the fill rule and stroke width.
    130     copyContextProperties(cairoContext, shadowContext);
    131 
    132     PlatformContextCairo platformShadowContext(shadowContext);
     131    copyContextProperties(cairoContext, cairoShadowContext);
     132
    133133    if (drawingStyle & Fill) {
    134         cairo_append_path(shadowContext, path.get());
    135         platformShadowContext.prepareForFilling(context->state(), PlatformContextCairo::NoAdjustment);
    136         cairo_clip_preserve(shadowContext);
    137         cairo_paint_with_alpha(shadowContext, context->platformContext()->globalAlpha());
     134        cairo_save(cairoShadowContext);
     135        cairo_append_path(cairoShadowContext, path.get());
     136        shadowContext->platformContext()->prepareForFilling(context->state(), PlatformContextCairo::NoAdjustment);
     137        cairo_clip(cairoShadowContext);
     138        cairo_paint(cairoShadowContext);
     139        cairo_restore(cairoShadowContext);
    138140    }
    139141
    140142    if (drawingStyle & Stroke) {
    141         cairo_append_path(shadowContext, path.get());
    142         platformShadowContext.prepareForStroking(context->state());
    143         cairo_stroke(shadowContext);
    144     }
    145 
    146     shadow->endShadowLayer(context);
     143        cairo_append_path(cairoShadowContext, path.get());
     144        shadowContext->platformContext()->prepareForStroking(context->state(), PlatformContextCairo::DoNotPreserveAlpha);
     145        cairo_stroke(cairoShadowContext);
     146    }
     147
     148    shadow.endShadowLayer(context);
     149
     150    // ShadowBlur::endShadowLayer destroys the current path on the Cairo context. We restore it here.
     151    cairo_new_path(cairoContext);
     152    cairo_append_path(cairoContext, path.get());
    147153}
    148154
     
    205211    platformContext()->save();
    206212    m_data->save();
    207     m_data->shadowStack.append(m_data->shadow);
    208213}
    209214
    210215void GraphicsContext::restorePlatformState()
    211216{
    212     if (m_data->shadowStack.isEmpty())
    213         m_data->shadow = ContextShadow();
    214     else {
    215         m_data->shadow = m_data->shadowStack.last();
    216         m_data->shadowStack.removeLast();
    217     }
    218 
    219217    platformContext()->restore();
    220218    m_data->restore();
     219
     220    platformContext()->shadowBlur().setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur),
     221                                                    m_state.shadowOffset,
     222                                                    m_state.shadowColor,
     223                                                    m_state.shadowColorSpace,
     224                                                    m_state.shadowsIgnoreTransforms);
    221225}
    222226
     
    508512
    509513    if (hasShadow())
    510         m_data->shadow.drawRectShadow(this, enclosingIntRect(rect));
     514        platformContext()->shadowBlur().drawRectShadow(this, rect, RoundedRect::Radii());
    511515
    512516    fillRectWithColor(platformContext()->cr(), rect, color);
     
    536540    cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
    537541    cairo_clip(cr);
     542}
     543
     544IntRect GraphicsContext::clipBounds() const
     545{
     546    double x1, x2, y1, y2;
     547    cairo_clip_extents(platformContext()->cr(), &x1, &y1, &x2, &y2);
     548    return enclosingIntRect(FloatRect(x1, y1, x2 - x1, y2 - y1));
    538549}
    539550
     
    656667    FloatRect lineExtents(origin, FloatSize(width, strokeThickness()));
    657668
    658     ContextShadow* shadow = contextShadow();
    659     ASSERT(shadow);
    660     cairo_t* shadowContext = shadow->beginShadowLayer(this, lineExtents);
    661     if (shadowContext) {
    662         drawLineOnCairoContext(this, shadowContext, origin, endPoint);
    663         shadow->endShadowLayer(this);
     669    ShadowBlur& shadow = platformContext()->shadowBlur();
     670    if (GraphicsContext* shadowContext = shadow.beginShadowLayer(this, lineExtents)) {
     671        drawLineOnCairoContext(this, shadowContext->platformContext()->cr(), origin, endPoint);
     672        shadow.endShadowLayer(this);
    664673    }
    665674
     
    846855void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
    847856{
    848     // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
     857    if (paintingDisabled())
     858        return;
     859
    849860    if (m_state.shadowsIgnoreTransforms) {
    850861        // Meaning that this graphics context is associated with a CanvasRenderingContext
    851862        // We flip the height since CG and HTML5 Canvas have opposite Y axis
    852863        m_state.shadowOffset = FloatSize(size.width(), -size.height());
    853         m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
    854     } else
    855         m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
    856 
    857     m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
    858 }
    859 
    860 ContextShadow* GraphicsContext::contextShadow()
    861 {
    862     return &m_data->shadow;
     864    }
     865
     866    // Cairo doesn't support shadows natively, they are drawn manually in the draw* functions using ShadowBlur.
     867    platformContext()->shadowBlur().setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur),
     868                                                    m_state.shadowOffset,
     869                                                    m_state.shadowColor,
     870                                                    m_state.shadowColorSpace,
     871                                                    m_state.shadowsIgnoreTransforms);
    863872}
    864873
    865874void GraphicsContext::clearPlatformShadow()
    866875{
    867     m_data->shadow.clear();
     876    if (paintingDisabled())
     877        return;
     878
     879    platformContext()->shadowBlur().clear();
    868880}
    869881
     
    10701082
    10711083    if (hasShadow())
    1072         m_data->shadow.drawRectShadow(this, r, topLeft, topRight, bottomLeft, bottomRight);
     1084        platformContext()->shadowBlur().drawRectShadow(this, r, RoundedRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
    10731085
    10741086    cairo_t* cr = platformContext()->cr();
  • trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h

    r87151 r91914  
    3131#include "GraphicsContext.h"
    3232
    33 #include "ContextShadow.h"
    3433#include "PlatformContextCairo.h"
    3534#include "RefPtrCairo.h"
     
    101100    PlatformContextCairo* platformContext;
    102101    Vector<float> layers;
    103     ContextShadow shadow;
    104     Vector<ContextShadow> shadowStack;
    105102    InterpolationQuality imageInterpolationQuality;
    106103
  • trunk/Source/WebCore/platform/graphics/cairo/ImageCairo.cpp

    r86174 r91914  
    3434#include "CairoUtilities.h"
    3535#include "Color.h"
    36 #include "ContextShadow.h"
    3736#include "FloatRect.h"
    3837#include "GraphicsContext.h"
  • trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp

    r89314 r91914  
    175175    cairo_pattern_set_matrix(pattern.get(), &matrix);
    176176
    177     ContextShadow* shadow = context->contextShadow();
    178     if (shadow && shadow->m_type != ContextShadow::NoShadow) {
    179         if (cairo_t* shadowContext = shadow->beginShadowLayer(context, destRect)) {
    180             drawPatternToCairoContext(shadowContext, pattern.get(), destRect, 1);
    181             shadow->endShadowLayer(context);
     177    ShadowBlur& shadow = context->platformContext()->shadowBlur();
     178    if (shadow.type() != ShadowBlur::NoShadow) {
     179        if (GraphicsContext* shadowContext = shadow.beginShadowLayer(context, destRect)) {
     180            drawPatternToCairoContext(shadowContext->platformContext()->cr(), pattern.get(), destRect, 1);
     181            shadow.endShadowLayer(context);
    182182        }
    183183    }
     
    238238}
    239239
    240 void PlatformContextCairo::prepareForStroking(const GraphicsContextState& state)
     240void PlatformContextCairo::prepareForStroking(const GraphicsContextState& state, AlphaPreservation alphaPreservation)
    241241{
    242242    prepareCairoContextSource(m_cr.get(),
     
    244244                              state.strokeGradient.get(),
    245245                              state.strokeColor,
    246                               globalAlpha());
     246                              alphaPreservation == PreserveAlpha ? globalAlpha() : 1);
    247247}
    248248
  • trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h

    r89314 r91914  
    2727#define PlatformContextCairo_h
    2828
    29 #include "ContextShadow.h"
    3029#include "GraphicsContext.h"
    3130#include "RefPtrCairo.h"
     31#include "ShadowBlur.h"
    3232
    3333namespace WebCore {
     
    4949    void setCr(cairo_t* cr) { m_cr = cr; }
    5050
     51    ShadowBlur& shadowBlur() { return m_shadowBlur; }
     52
    5153    void save();
    5254    void restore();
     
    6264    enum PatternAdjustment { NoAdjustment, AdjustPatternForGlobalAlpha };
    6365    void prepareForFilling(const GraphicsContextState&, PatternAdjustment);
    64     void prepareForStroking(const GraphicsContextState&);
     66
     67    enum AlphaPreservation { DoNotPreserveAlpha, PreserveAlpha };
     68    void prepareForStroking(const GraphicsContextState&, AlphaPreservation = PreserveAlpha);
    6569
    6670private:
     
    7175    WTF::Vector<State> m_stateStack;
    7276
     77    // GraphicsContext is responsible for managing the state of the ShadowBlur,
     78    // so it does not need to be on the state stack.
     79    ShadowBlur m_shadowBlur;
     80
    7381    InterpolationQuality m_imageInterpolationQuality;
    7482};
  • trunk/Source/WebCore/platform/graphics/gtk/FontGtk.cpp

    r82962 r91914  
    3535
    3636#include "CairoUtilities.h"
    37 #include "ContextShadow.h"
    3837#include "GOwnPtr.h"
    3938#include "GraphicsContext.h"
    4039#include "NotImplemented.h"
    4140#include "PlatformContextCairo.h"
     41#include "ShadowBlur.h"
    4242#include "SimpleFontData.h"
    4343#include "TextRun.h"
     
    221221static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
    222222{
    223     ContextShadow* shadow = graphicsContext->contextShadow();
    224     ASSERT(shadow);
    225 
    226     if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow->m_type == ContextShadow::NoShadow)
     223    ShadowBlur& shadow = graphicsContext->platformContext()->shadowBlur();
     224
     225    if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow.type() == ShadowBlur::NoShadow)
    227226        return;
    228227
    229     FloatPoint totalOffset(point + shadow->m_offset);
    230 
    231     // Optimize non-blurry shadows, by just drawing text without the ContextShadow.
    232     if (!shadow->mustUseContextShadow(graphicsContext)) {
     228    FloatPoint totalOffset(point + graphicsContext->state().shadowOffset);
     229
     230    // Optimize non-blurry shadows, by just drawing text without the ShadowBlur.
     231    if (!shadow.mustUseShadowBlur(graphicsContext)) {
    233232        cairo_t* context = graphicsContext->platformContext()->cr();
    234233        cairo_save(context);
    235234        cairo_translate(context, totalOffset.x(), totalOffset.y());
    236235
    237         setSourceRGBAFromColor(context, shadow->m_color);
     236        setSourceRGBAFromColor(context, graphicsContext->state().shadowColor);
    238237        gdk_cairo_region(context, renderRegion);
    239238        cairo_clip(context);
     
    246245    FloatRect extents(getPangoRegionExtents(renderRegion));
    247246    extents.setLocation(FloatPoint(point.x(), point.y() - extents.height()));
    248     cairo_t* shadowContext = shadow->beginShadowLayer(graphicsContext, extents);
    249     if (shadowContext) {
    250         cairo_translate(shadowContext, point.x(), point.y());
    251         pango_cairo_show_layout_line(shadowContext, layoutLine);
     247    if (GraphicsContext* shadowContext = shadow.beginShadowLayer(graphicsContext, extents)) {
     248        cairo_t* cairoShadowContext = shadowContext->platformContext()->cr();
     249        cairo_translate(cairoShadowContext, point.x(), point.y());
     250        pango_cairo_show_layout_line(cairoShadowContext, layoutLine);
    252251
    253252        // We need the clipping region to be active when we blit the blurred shadow back,
    254253        // because we don't want any bits and pieces of characters out of range to be
    255         // drawn. Since ContextShadow expects a consistent transform, we have to undo the
     254        // drawn. Since ShadowBlur expects a consistent transform, we have to undo the
    256255        // translation before calling endShadowLayer as well.
    257256        cairo_t* context = graphicsContext->platformContext()->cr();
     
    262261        cairo_translate(context, -totalOffset.x(), -totalOffset.y());
    263262
    264         shadow->endShadowLayer(graphicsContext);
     263        shadow.endShadowLayer(graphicsContext);
    265264        cairo_restore(context);
    266265    }
  • trunk/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r90454 r91914  
    199199    ShadowBlur* shadow;
    200200
    201     bool mustUseShadowBlur() const
    202     {
    203         // We can't avoid ShadowBlur, since the shadow has blur.
    204         if (shadow->type() == ShadowBlur::BlurShadow)
    205             return true;
    206         // We can avoid ShadowBlur and optimize, since we're not drawing on a
    207         // canvas and box shadows are affected by the transformation matrix.
    208         if (!shadow->shadowsIgnoreTransforms())
    209             return false;
    210         // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
    211         if (p()->combinedTransform().isIdentity())
    212             return false;
    213         // Otherwise, no chance avoiding ShadowBlur.
    214         return true;
    215     }
    216 
    217201    QRectF clipBoundingRect() const
    218202    {
     
    511495    if (hasShadow()) {
    512496        ShadowBlur* shadow = shadowBlur();
    513         if (m_data->mustUseShadowBlur() || m_state.fillPattern || m_state.fillGradient)
     497        if (shadow->mustUseShadowBlur(this) || m_state.fillPattern || m_state.fillGradient)
    514498        {
    515499            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, platformPath.controlPointRect());
     
    560544    if (hasShadow()) {
    561545        ShadowBlur* shadow = shadowBlur();
    562         if (m_data->mustUseShadowBlur() || m_state.strokePattern || m_state.strokeGradient)
     546        if (shadow->mustUseShadowBlur(this) || m_state.strokePattern || m_state.strokeGradient)
    563547        {
    564548            FloatRect boundingRect = platformPath.controlPointRect();
     
    702686    } else {
    703687        if (hasShadow()) {
    704             if (m_data->mustUseShadowBlur()) {
     688            if (shadow->mustUseShadowBlur(this)) {
    705689                GraphicsContext* shadowContext = shadow->beginShadowLayer(this, normalizedRect);
    706690                if (shadowContext) {
     
    734718    if (hasShadow()) {
    735719        ShadowBlur* shadow = shadowBlur();
    736         if (m_data->mustUseShadowBlur()) {
     720        if (shadow->mustUseShadowBlur(this)) {
    737721            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, normalizedRect);
    738722            if (shadowContext) {
     
    762746    if (hasShadow()) {
    763747        ShadowBlur* shadow = shadowBlur();
    764         if (m_data->mustUseShadowBlur()) {
     748        if (shadow->mustUseShadowBlur(this)) {
    765749            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, rect);
    766750            if (shadowContext) {
Note: See TracChangeset for help on using the changeset viewer.