Title: [226511] trunk/Source/WebCore
Revision
226511
Author
[email protected]
Date
2018-01-08 07:00:38 -0800 (Mon, 08 Jan 2018)

Log Message

[Cairo] Use isolated fill and stroke source containers
https://bugs.webkit.org/show_bug.cgi?id=181386

Reviewed by Carlos Garcia Campos.

Generate fill and stroke source objects upon invocation of various Cairo
operations, initializing necessary data from the GraphicsContextState
object.

Cairo::FillSource and Cairo::StrokeSource structs are introduced, both
being default-constructible as well as providing a constructor that
accepts a GraphicsContextState object from which the appropriate
resources are created.

The FillSource and StrokeSource objects are then passed to
PlatformContextCairo's prepareForFilling() and prepareForStroking()
methods. Here the helper prepareCairoContextSource() function is now
invoked with cairo_pattern_t objects as pattern or gradient sources, or
the source color if neither cairo_pattern_t object is specified.

The FillSource and StrokeSource constructors mimic the previous behavior
of prepareCairoContextSource(). In case the source is a Pattern object,
a cairo_pattern_t object is created from that. In case of FillSource,
we also retrieve pattern size, transform and repetition information. In
case the source os a Gradient object, we create a 'base' cairo_pattern_t
object for a completely opaque alpha channel. Additionally, if the alpha
value on the state is not 1, we create an alpha-adjusted cairo_pattern_t
that is potentially used for any filling or stroking operation that has
to preserve transparency. If neither Pattern or Gradient objects are set
on the GraphicsContextState, we default to the current fill or stroke
color.

Overall, there's no change in behavior, this is simply a refactoring
that enables us to construct Cairo objects for filling and stroking
sources at the time of Cairo operation dispatch, instead of pulling down
GraphicsContextState deeper into the Cairo-specific code.

No new tests -- no change in functionality.

* platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::drawPathShadow):
(WebCore::Cairo::fillCurrentCairoPath):
(WebCore::Cairo::FillSource::FillSource):
(WebCore::Cairo::StrokeSource::StrokeSource):
(WebCore::Cairo::fillRect):
(WebCore::Cairo::fillRectWithRoundedHole):
(WebCore::Cairo::fillPath):
(WebCore::Cairo::strokeRect):
(WebCore::Cairo::strokePath):
(WebCore::Cairo::drawGlyphs):
* platform/graphics/cairo/CairoOperations.h:
* platform/graphics/cairo/FontCairo.cpp:
(WebCore::FontCascade::drawGlyphs):
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
(WebCore::GraphicsContext::fillRect):
(WebCore::GraphicsContext::strokeRect):
(WebCore::GraphicsContext::fillRectWithRoundedHole):
* platform/graphics/cairo/PlatformContextCairo.cpp:
(WebCore::prepareCairoContextSource):
(WebCore::PlatformContextCairo::prepareForFilling):
(WebCore::PlatformContextCairo::prepareForStroking):
(WebCore::PlatformContextCairo::clipForPatternFilling):
* platform/graphics/cairo/PlatformContextCairo.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (226510 => 226511)


--- trunk/Source/WebCore/ChangeLog	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/ChangeLog	2018-01-08 15:00:38 UTC (rev 226511)
@@ -1,3 +1,71 @@
+2018-01-08  Zan Dobersek  <[email protected]>
+
+        [Cairo] Use isolated fill and stroke source containers
+        https://bugs.webkit.org/show_bug.cgi?id=181386
+
+        Reviewed by Carlos Garcia Campos.
+
+        Generate fill and stroke source objects upon invocation of various Cairo
+        operations, initializing necessary data from the GraphicsContextState
+        object.
+
+        Cairo::FillSource and Cairo::StrokeSource structs are introduced, both
+        being default-constructible as well as providing a constructor that
+        accepts a GraphicsContextState object from which the appropriate
+        resources are created.
+
+        The FillSource and StrokeSource objects are then passed to
+        PlatformContextCairo's prepareForFilling() and prepareForStroking()
+        methods. Here the helper prepareCairoContextSource() function is now
+        invoked with cairo_pattern_t objects as pattern or gradient sources, or
+        the source color if neither cairo_pattern_t object is specified.
+
+        The FillSource and StrokeSource constructors mimic the previous behavior
+        of prepareCairoContextSource(). In case the source is a Pattern object,
+        a cairo_pattern_t object is created from that. In case of FillSource,
+        we also retrieve pattern size, transform and repetition information. In
+        case the source os a Gradient object, we create a 'base' cairo_pattern_t
+        object for a completely opaque alpha channel. Additionally, if the alpha
+        value on the state is not 1, we create an alpha-adjusted cairo_pattern_t
+        that is potentially used for any filling or stroking operation that has
+        to preserve transparency. If neither Pattern or Gradient objects are set
+        on the GraphicsContextState, we default to the current fill or stroke
+        color.
+
+        Overall, there's no change in behavior, this is simply a refactoring
+        that enables us to construct Cairo objects for filling and stroking
+        sources at the time of Cairo operation dispatch, instead of pulling down
+        GraphicsContextState deeper into the Cairo-specific code.
+
+        No new tests -- no change in functionality.
+
+        * platform/graphics/cairo/CairoOperations.cpp:
+        (WebCore::Cairo::drawPathShadow):
+        (WebCore::Cairo::fillCurrentCairoPath):
+        (WebCore::Cairo::FillSource::FillSource):
+        (WebCore::Cairo::StrokeSource::StrokeSource):
+        (WebCore::Cairo::fillRect):
+        (WebCore::Cairo::fillRectWithRoundedHole):
+        (WebCore::Cairo::fillPath):
+        (WebCore::Cairo::strokeRect):
+        (WebCore::Cairo::strokePath):
+        (WebCore::Cairo::drawGlyphs):
+        * platform/graphics/cairo/CairoOperations.h:
+        * platform/graphics/cairo/FontCairo.cpp:
+        (WebCore::FontCascade::drawGlyphs):
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::fillPath):
+        (WebCore::GraphicsContext::strokePath):
+        (WebCore::GraphicsContext::fillRect):
+        (WebCore::GraphicsContext::strokeRect):
+        (WebCore::GraphicsContext::fillRectWithRoundedHole):
+        * platform/graphics/cairo/PlatformContextCairo.cpp:
+        (WebCore::prepareCairoContextSource):
+        (WebCore::PlatformContextCairo::prepareForFilling):
+        (WebCore::PlatformContextCairo::prepareForStroking):
+        (WebCore::PlatformContextCairo::clipForPatternFilling):
+        * platform/graphics/cairo/PlatformContextCairo.h:
+
 2018-01-08  Youenn Fablet  <[email protected]>
 
         navigator.onLine does not work inside service workers

Modified: trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2018-01-08 15:00:38 UTC (rev 226511)
@@ -66,7 +66,7 @@
     FillAndStroke = Fill + Stroke
 };
 
-static inline void drawPathShadow(PlatformContextCairo& platformContext, const GraphicsContextState& contextState, GraphicsContext& targetContext, PathDrawingStyle drawingStyle)
+static inline void drawPathShadow(PlatformContextCairo& platformContext, const FillSource& fillSource, const StrokeSource& strokeSource, GraphicsContext& targetContext, PathDrawingStyle drawingStyle)
 {
     ShadowBlur& shadow = platformContext.shadowBlur();
     if (shadow.type() == ShadowBlur::NoShadow)
@@ -106,7 +106,7 @@
     if (drawingStyle & Fill) {
         cairo_save(cairoShadowContext);
         cairo_append_path(cairoShadowContext, path.get());
-        shadowContext->platformContext()->prepareForFilling(contextState, PlatformContextCairo::NoAdjustment);
+        shadowContext->platformContext()->prepareForFilling(fillSource, PlatformContextCairo::NoAdjustment);
         cairo_fill(cairoShadowContext);
         cairo_restore(cairoShadowContext);
     }
@@ -113,7 +113,7 @@
 
     if (drawingStyle & Stroke) {
         cairo_append_path(cairoShadowContext, path.get());
-        shadowContext->platformContext()->prepareForStroking(contextState, PlatformContextCairo::DoNotPreserveAlpha);
+        shadowContext->platformContext()->prepareForStroking(strokeSource, PlatformContextCairo::DoNotPreserveAlpha);
         cairo_stroke(cairoShadowContext);
     }
 
@@ -126,12 +126,12 @@
     cairo_append_path(cairoContext, path.get());
 }
 
-static inline void fillCurrentCairoPath(PlatformContextCairo& platformContext, const GraphicsContextState& contextState)
+static inline void fillCurrentCairoPath(PlatformContextCairo& platformContext, const FillSource& fillSource)
 {
     cairo_t* cr = platformContext.cr();
     cairo_save(cr);
 
-    platformContext.prepareForFilling(contextState, PlatformContextCairo::AdjustPatternForGlobalAlpha);
+    platformContext.prepareForFilling(fillSource, PlatformContextCairo::AdjustPatternForGlobalAlpha);
     cairo_fill(cr);
 
     cairo_restore(cr);
@@ -468,6 +468,38 @@
     return true;
 }
 
+FillSource::FillSource(const GraphicsContextState& state)
+{
+    if (state.fillPattern) {
+        pattern.object = adoptRef(state.fillPattern->createPlatformPattern(AffineTransform()));
+
+        auto& patternImage = state.fillPattern->tileImage();
+        pattern.size = FloatSize(patternImage.width(), patternImage.height());
+        pattern.transform = state.fillPattern->patternSpaceTransform();
+        pattern.repeatX = state.fillPattern->repeatX();
+        pattern.repeatY = state.fillPattern->repeatY();
+    } else if (state.fillGradient) {
+        gradient.base = adoptRef(state.fillGradient->createPlatformGradient(1));
+        if (state.alpha != 1)
+            gradient.alphaAdjusted = adoptRef(state.fillGradient->createPlatformGradient(state.alpha));
+    } else
+        color = state.fillColor;
+
+    fillRule = state.fillRule;
+}
+
+StrokeSource::StrokeSource(const GraphicsContextState& state)
+{
+    if (state.strokePattern)
+        pattern = adoptRef(state.strokePattern->createPlatformPattern(AffineTransform()));
+    else if (state.strokeGradient) {
+        gradient.base = adoptRef(state.strokeGradient->createPlatformGradient(1));
+        if (state.alpha != 1)
+            gradient.alphaAdjusted = adoptRef(state.strokeGradient->createPlatformGradient(state.alpha));
+    } else
+        color = state.strokeColor;
+}
+
 void setLineCap(PlatformContextCairo& platformContext, LineCap lineCap)
 {
     cairo_line_cap_t cairoCap;
@@ -515,13 +547,13 @@
     cairo_set_miter_limit(platformContext.cr(), miterLimit);
 }
 
-void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, const FillSource& fillSource, GraphicsContext& targetContext)
 {
     cairo_t* cr = platformContext.cr();
 
     cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
-    drawPathShadow(platformContext, contextState, targetContext, Fill);
-    fillCurrentCairoPath(platformContext, contextState);
+    drawPathShadow(platformContext, fillSource, { }, targetContext, Fill);
+    fillCurrentCairoPath(platformContext, fillSource);
 }
 
 void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, const Color& color, bool hasShadow, GraphicsContext& targetContext)
@@ -558,7 +590,7 @@
     cairo_restore(cr);
 }
 
-void fillRectWithRoundedHole(PlatformContextCairo& platformContext, const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const GraphicsContextState& contextState, const ShadowBlurUsage& shadowBlurUsage, GraphicsContext& targetContext)
+void fillRectWithRoundedHole(PlatformContextCairo& platformContext, const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const FillSource& fillSource, const ShadowBlurUsage& shadowBlurUsage, GraphicsContext& targetContext)
 {
     // FIXME: this should leverage the specified color.
 
@@ -576,20 +608,20 @@
 
     cairo_save(cr);
     setPathOnCairoContext(platformContext.cr(), path.platformPath()->context());
-    fillCurrentCairoPath(platformContext, contextState);
+    fillCurrentCairoPath(platformContext, fillSource);
     cairo_restore(cr);
 }
 
-void fillPath(PlatformContextCairo& platformContext, const Path& path, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+void fillPath(PlatformContextCairo& platformContext, const Path& path, const FillSource& fillSource, GraphicsContext& targetContext)
 {
     cairo_t* cr = platformContext.cr();
 
     setPathOnCairoContext(cr, path.platformPath()->context());
-    drawPathShadow(platformContext, contextState, targetContext, Fill);
-    fillCurrentCairoPath(platformContext, contextState);
+    drawPathShadow(platformContext, fillSource, { }, targetContext, Fill);
+    fillCurrentCairoPath(platformContext, fillSource);
 }
 
-void strokeRect(PlatformContextCairo& platformContext, const FloatRect& rect, float lineWidth, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+void strokeRect(PlatformContextCairo& platformContext, const FloatRect& rect, float lineWidth, const StrokeSource& strokeSource, GraphicsContext& targetContext)
 {
     cairo_t* cr = platformContext.cr();
     cairo_save(cr);
@@ -596,20 +628,20 @@
 
     cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
     cairo_set_line_width(cr, lineWidth);
-    drawPathShadow(platformContext, contextState, targetContext, Stroke);
-    platformContext.prepareForStroking(contextState);
+    drawPathShadow(platformContext, { }, strokeSource, targetContext, Stroke);
+    platformContext.prepareForStroking(strokeSource, PlatformContextCairo::PreserveAlpha);
     cairo_stroke(cr);
 
     cairo_restore(cr);
 }
 
-void strokePath(PlatformContextCairo& platformContext, const Path& path, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+void strokePath(PlatformContextCairo& platformContext, const Path& path, const StrokeSource& strokeSource, GraphicsContext& targetContext)
 {
     cairo_t* cr = platformContext.cr();
 
     setPathOnCairoContext(cr, path.platformPath()->context());
-    drawPathShadow(platformContext, contextState, targetContext, Stroke);
-    platformContext.prepareForStroking(contextState);
+    drawPathShadow(platformContext, { }, strokeSource, targetContext, Stroke);
+    platformContext.prepareForStroking(strokeSource, PlatformContextCairo::PreserveAlpha);
     cairo_stroke(cr);
 }
 
@@ -624,7 +656,7 @@
     cairo_restore(cr);
 }
 
-void drawGlyphs(PlatformContextCairo& platformContext, const GraphicsContextState& state, const ShadowBlurUsage& shadowBlurUsage, const FloatPoint& point, cairo_scaled_font_t* scaledFont, double syntheticBoldOffset, const Vector<cairo_glyph_t>& glyphs, float xOffset, GraphicsContext& targetContext)
+void drawGlyphs(PlatformContextCairo& platformContext, const GraphicsContextState& state, const FillSource& fillSource, const StrokeSource& strokeSource, const ShadowBlurUsage& shadowBlurUsage, const FloatPoint& point, cairo_scaled_font_t* scaledFont, double syntheticBoldOffset, const Vector<cairo_glyph_t>& glyphs, float xOffset, GraphicsContext& targetContext)
 {
     drawGlyphsShadow(platformContext, state, shadowBlurUsage, point, scaledFont, syntheticBoldOffset, glyphs, targetContext);
 
@@ -632,7 +664,7 @@
     cairo_save(cr);
 
     if (state.textDrawingMode & TextModeFill) {
-        platformContext.prepareForFilling(state, PlatformContextCairo::AdjustPatternForGlobalAlpha);
+        platformContext.prepareForFilling(fillSource, PlatformContextCairo::AdjustPatternForGlobalAlpha);
         drawGlyphsToContext(cr, scaledFont, syntheticBoldOffset, glyphs);
     }
 
@@ -641,7 +673,7 @@
     // the text as even one single stroke would cover the full wdth of the text.
     //  See https://bugs.webkit.org/show_bug.cgi?id=33759.
     if (state.textDrawingMode & TextModeStroke && state.strokeThickness < 2 * xOffset) {
-        platformContext.prepareForStroking(state);
+        platformContext.prepareForStroking(strokeSource, PlatformContextCairo::PreserveAlpha);
         cairo_set_line_width(cr, state.strokeThickness);
 
         // This may disturb the CTM, but we are going to call cairo_restore soon after.

Modified: trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2018-01-08 15:00:38 UTC (rev 226511)
@@ -77,6 +77,38 @@
 
 } // namespace State
 
+struct FillSource {
+    FillSource() = default;
+    explicit FillSource(const GraphicsContextState&);
+
+    struct {
+        RefPtr<cairo_pattern_t> object;
+        FloatSize size;
+        AffineTransform transform;
+        bool repeatX { false };
+        bool repeatY { false };
+    } pattern;
+    struct {
+        RefPtr<cairo_pattern_t> base;
+        RefPtr<cairo_pattern_t> alphaAdjusted;
+    } gradient;
+    Color color;
+
+    WindRule fillRule;
+};
+
+struct StrokeSource {
+    StrokeSource() = default;
+    explicit StrokeSource(const GraphicsContextState&);
+
+    RefPtr<cairo_pattern_t> pattern;
+    struct {
+        RefPtr<cairo_pattern_t> base;
+        RefPtr<cairo_pattern_t> alphaAdjusted;
+    } gradient;
+    Color color;
+};
+
 struct ShadowBlurUsage {
     explicit ShadowBlurUsage(const GraphicsContextState&);
 
@@ -92,17 +124,17 @@
 void setLineJoin(PlatformContextCairo&, LineJoin);
 void setMiterLimit(PlatformContextCairo&, float);
 
-void fillRect(PlatformContextCairo&, const FloatRect&, const GraphicsContextState&, GraphicsContext&);
+void fillRect(PlatformContextCairo&, const FloatRect&, const FillSource&, GraphicsContext&);
 void fillRect(PlatformContextCairo&, const FloatRect&, const Color&, bool, GraphicsContext&);
 void fillRect(PlatformContextCairo&, const FloatRect&, cairo_pattern_t*);
 void fillRoundedRect(PlatformContextCairo&, const FloatRoundedRect&, const Color&, bool, GraphicsContext&);
-void fillRectWithRoundedHole(PlatformContextCairo&, const FloatRect&, const FloatRoundedRect&, const GraphicsContextState&, const ShadowBlurUsage&, GraphicsContext&);
-void fillPath(PlatformContextCairo&, const Path&, const GraphicsContextState&, GraphicsContext&);
-void strokeRect(PlatformContextCairo&, const FloatRect&, float, const GraphicsContextState&, GraphicsContext&);
-void strokePath(PlatformContextCairo&, const Path&, const GraphicsContextState&, GraphicsContext&);
+void fillRectWithRoundedHole(PlatformContextCairo&, const FloatRect&, const FloatRoundedRect&, const FillSource&, const ShadowBlurUsage&, GraphicsContext&);
+void fillPath(PlatformContextCairo&, const Path&, const FillSource&, GraphicsContext&);
+void strokeRect(PlatformContextCairo&, const FloatRect&, float, const StrokeSource&, GraphicsContext&);
+void strokePath(PlatformContextCairo&, const Path&, const StrokeSource&, GraphicsContext&);
 void clearRect(PlatformContextCairo&, const FloatRect&);
 
-void drawGlyphs(PlatformContextCairo&, const GraphicsContextState&, const ShadowBlurUsage&, const FloatPoint&, cairo_scaled_font_t*, double, const Vector<cairo_glyph_t>&, float, GraphicsContext&);
+void drawGlyphs(PlatformContextCairo&, const GraphicsContextState&, const FillSource&, const StrokeSource&, const ShadowBlurUsage&, const FloatPoint&, cairo_scaled_font_t*, double, const Vector<cairo_glyph_t>&, float, GraphicsContext&);
 
 void drawNativeImage(PlatformContextCairo&, cairo_surface_t*, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, ImageOrientation, GraphicsContext&);
 void drawPattern(PlatformContextCairo&, cairo_surface_t*, const IntSize&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, CompositeOperator, BlendMode);

Modified: trunk/Source/WebCore/platform/graphics/cairo/FontCairo.cpp (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/FontCairo.cpp	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/FontCairo.cpp	2018-01-08 15:00:38 UTC (rev 226511)
@@ -72,7 +72,7 @@
 
     ASSERT(context.hasPlatformContext());
     auto& state = context.state();
-    Cairo::drawGlyphs(*context.platformContext(), state, Cairo::ShadowBlurUsage(state), point, scaledFont, syntheticBoldOffset, glyphs, xOffset, context);
+    Cairo::drawGlyphs(*context.platformContext(), state, Cairo::FillSource(state), Cairo::StrokeSource(state), Cairo::ShadowBlurUsage(state), point, scaledFont, syntheticBoldOffset, glyphs, xOffset, context);
 }
 
 #if ENABLE(CSS3_TEXT_DECORATION_SKIP_INK)

Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2018-01-08 15:00:38 UTC (rev 226511)
@@ -188,7 +188,7 @@
     }
 
     ASSERT(hasPlatformContext());
-    Cairo::fillPath(*platformContext(), path, state(), *this);
+    Cairo::fillPath(*platformContext(), path, Cairo::FillSource(state()), *this);
 }
 
 void GraphicsContext::strokePath(const Path& path)
@@ -202,7 +202,7 @@
     }
 
     ASSERT(hasPlatformContext());
-    Cairo::strokePath(*platformContext(), path, state(), *this);
+    Cairo::strokePath(*platformContext(), path, Cairo::StrokeSource(state()), *this);
 }
 
 void GraphicsContext::fillRect(const FloatRect& rect)
@@ -216,7 +216,7 @@
     }
 
     ASSERT(hasPlatformContext());
-    Cairo::fillRect(*platformContext(), rect, state(), *this);
+    Cairo::fillRect(*platformContext(), rect, Cairo::FillSource(state()), *this);
 }
 
 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
@@ -523,7 +523,7 @@
     }
 
     ASSERT(hasPlatformContext());
-    Cairo::strokeRect(*platformContext(), rect, lineWidth, state(), *this);
+    Cairo::strokeRect(*platformContext(), rect, lineWidth, Cairo::StrokeSource(state()), *this);
 }
 
 void GraphicsContext::setLineCap(LineCap lineCap)
@@ -679,7 +679,7 @@
 
     ASSERT(hasPlatformContext());
     auto& state = this->state();
-    Cairo::fillRectWithRoundedHole(*platformContext(), rect, roundedHoleRect, state, Cairo::ShadowBlurUsage(state), *this);
+    Cairo::fillRectWithRoundedHole(*platformContext(), rect, roundedHoleRect, Cairo::FillSource(state), Cairo::ShadowBlurUsage(state), *this);
 }
 
 void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator compositeOperator, BlendMode blendMode)

Modified: trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.cpp	2018-01-08 15:00:38 UTC (rev 226511)
@@ -264,16 +264,17 @@
     cairo_pop_group_to_source(cr);
 }
 
-static void prepareCairoContextSource(cairo_t* cr, Pattern* pattern, Gradient* gradient, const Color& color, float globalAlpha)
+static void prepareCairoContextSource(cairo_t* cr, cairo_pattern_t* pattern, cairo_pattern_t* gradient, const Color& color, float globalAlpha)
 {
     if (pattern) {
-        RefPtr<cairo_pattern_t> cairoPattern = adoptRef(pattern->createPlatformPattern(AffineTransform()));
-        cairo_set_source(cr, cairoPattern.get());
+        // Pattern source
+        cairo_set_source(cr, pattern);
         reduceSourceByAlpha(cr, globalAlpha);
     } else if (gradient) {
-        RefPtr<cairo_pattern_t> cairoPattern = adoptRef(gradient->createPlatformGradient(globalAlpha));
-        cairo_set_source(cr, cairoPattern.get());
-    } else { // Solid color source.
+        // Gradient source
+        cairo_set_source(cr, gradient);
+    } else {
+        // Solid color source
         if (globalAlpha < 1)
             setSourceRGBAFromColor(cr, colorWithOverrideAlpha(color.rgb(), color.alpha() / 255.f * globalAlpha));
         else
@@ -281,32 +282,39 @@
     }
 }
 
-void PlatformContextCairo::prepareForFilling(const GraphicsContextState& state, PatternAdjustment patternAdjustment)
+void PlatformContextCairo::prepareForFilling(const Cairo::FillSource& fillSource, PatternAdjustment patternAdjustment)
 {
-    cairo_set_fill_rule(m_cr.get(), state.fillRule == RULE_EVENODD ?  CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
-    prepareCairoContextSource(m_cr.get(),
-                              state.fillPattern.get(),
-                              state.fillGradient.get(),
-                              state.fillColor,
-                              patternAdjustment == AdjustPatternForGlobalAlpha ? globalAlpha() : 1);
+    cairo_set_fill_rule(m_cr.get(), fillSource.fillRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
 
-    if (state.fillPattern)
-        clipForPatternFilling(state);
+    bool adjustForAlpha = patternAdjustment == AdjustPatternForGlobalAlpha;
+
+    auto* gradient = fillSource.gradient.base.get();
+    if (adjustForAlpha && fillSource.gradient.alphaAdjusted)
+        gradient = fillSource.gradient.alphaAdjusted.get();
+
+    prepareCairoContextSource(m_cr.get(), fillSource.pattern.object.get(), gradient,
+        fillSource.color, adjustForAlpha ? globalAlpha() : 1);
+
+    if (fillSource.pattern.object) {
+        clipForPatternFilling(fillSource.pattern.size, fillSource.pattern.transform,
+            fillSource.pattern.repeatX, fillSource.pattern.repeatY);
+    }
 }
 
-void PlatformContextCairo::prepareForStroking(const GraphicsContextState& state, AlphaPreservation alphaPreservation)
+void PlatformContextCairo::prepareForStroking(const Cairo::StrokeSource& strokeSource, AlphaPreservation alphaPreservation)
 {
-    prepareCairoContextSource(m_cr.get(),
-                              state.strokePattern.get(),
-                              state.strokeGradient.get(),
-                              state.strokeColor,
-                              alphaPreservation == PreserveAlpha ? globalAlpha() : 1);
+    bool preserveAlpha = alphaPreservation == PreserveAlpha;
+
+    auto* gradient = strokeSource.gradient.base.get();
+    if (preserveAlpha && strokeSource.gradient.alphaAdjusted)
+        gradient = strokeSource.gradient.alphaAdjusted.get();
+
+    prepareCairoContextSource(m_cr.get(), strokeSource.pattern.get(), gradient,
+        strokeSource.color, preserveAlpha ? globalAlpha() : 1);
 }
 
-void PlatformContextCairo::clipForPatternFilling(const GraphicsContextState& state)
+void PlatformContextCairo::clipForPatternFilling(const FloatSize& patternSize, const AffineTransform& patternTransform, bool repeatX, bool repeatY)
 {
-    ASSERT(state.fillPattern);
-
     // Hold current cairo path in a variable for restoring it after configuring the pattern clip rectangle.
     auto currentPath = cairo_copy_path(m_cr.get());
     cairo_new_path(m_cr.get());
@@ -317,13 +325,8 @@
     cairo_clip_extents(m_cr.get(), &x1, &y1, &x2, &y2);
     FloatRect clipRect(x1, y1, x2 - x1, y2 - y1);
 
-    auto& patternImage = state.fillPattern->tileImage();
-    const AffineTransform& patternTransform = state.fillPattern->patternSpaceTransform();
-    FloatRect patternRect = patternTransform.mapRect(FloatRect(0, 0, patternImage.width(), patternImage.height()));
+    FloatRect patternRect = patternTransform.mapRect(FloatRect(FloatPoint(), patternSize));
 
-    bool repeatX = state.fillPattern->repeatX();
-    bool repeatY = state.fillPattern->repeatY();
-
     if (!repeatX) {
         clipRect.setX(patternRect.x());
         clipRect.setWidth(patternRect.width());

Modified: trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h (226510 => 226511)


--- trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h	2018-01-08 14:43:50 UTC (rev 226510)
+++ trunk/Source/WebCore/platform/graphics/cairo/PlatformContextCairo.h	2018-01-08 15:00:38 UTC (rev 226511)
@@ -37,6 +37,11 @@
 class GraphicsContextPlatformPrivate;
 struct GraphicsContextState;
 
+namespace Cairo {
+struct FillSource;
+struct StrokeSource;
+}
+
 // Much like PlatformContextSkia in the Skia port, this class holds information that
 // would normally be private to GraphicsContext, except that we want to allow access
 // to it in Font and Image code. This allows us to separate the concerns of Cairo-specific
@@ -69,13 +74,13 @@
     InterpolationQuality imageInterpolationQuality() const;
 
     enum PatternAdjustment { NoAdjustment, AdjustPatternForGlobalAlpha };
-    void prepareForFilling(const GraphicsContextState&, PatternAdjustment);
+    void prepareForFilling(const Cairo::FillSource&, PatternAdjustment);
 
     enum AlphaPreservation { DoNotPreserveAlpha, PreserveAlpha };
-    void prepareForStroking(const GraphicsContextState&, AlphaPreservation = PreserveAlpha);
+    void prepareForStroking(const Cairo::StrokeSource&, AlphaPreservation);
 
 private:
-    void clipForPatternFilling(const GraphicsContextState&);
+    void clipForPatternFilling(const FloatSize&, const AffineTransform&, bool, bool);
 
     RefPtr<cairo_t> m_cr;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to