Title: [224746] trunk/Source/WebCore
Revision
224746
Author
[email protected]
Date
2017-11-12 23:43:22 -0800 (Sun, 12 Nov 2017)

Log Message

[Cairo] Move rectangle and path filling, stroking, clearing operations in GraphicsContextCairo to CairoOperations
https://bugs.webkit.org/show_bug.cgi?id=179599

Reviewed by Carlos Garcia Campos.

Move operations that perform filling, stroking and clearing for
specified rectangles and paths to the CairoOperations file. This limits
operations to only work with a PlatformContextCairo object, along with
any required parameter, and will help with future work in this area.

Helper functions are copied along for the time being, but will later be
removed from the GraphicsContextCairo implementation file.

No new tests -- no change in behavior.

* platform/graphics/cairo/CairoOperations.cpp:
(WebCore::Cairo::fillRectWithColor):
(WebCore::Cairo::drawPathShadow):
(WebCore::Cairo::fillCurrentCairoPath):
(WebCore::Cairo::fillRect):
(WebCore::Cairo::fillRoundedRect):
(WebCore::Cairo::fillRectWithRoundedHole):
(WebCore::Cairo::fillPath):
(WebCore::Cairo::strokeRect):
(WebCore::Cairo::strokePath):
(WebCore::Cairo::clearRect):
* platform/graphics/cairo/CairoOperations.h:
* platform/graphics/cairo/GradientCairo.cpp:
(WebCore::Gradient::fill):
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
(WebCore::GraphicsContext::fillRect):
(WebCore::GraphicsContext::clearRect):
(WebCore::GraphicsContext::strokeRect):
(WebCore::GraphicsContext::platformFillRoundedRect):
(WebCore::GraphicsContext::fillRectWithRoundedHole):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (224745 => 224746)


--- trunk/Source/WebCore/ChangeLog	2017-11-13 07:41:18 UTC (rev 224745)
+++ trunk/Source/WebCore/ChangeLog	2017-11-13 07:43:22 UTC (rev 224746)
@@ -1,5 +1,45 @@
 2017-11-12  Zan Dobersek  <[email protected]>
 
+        [Cairo] Move rectangle and path filling, stroking, clearing operations in GraphicsContextCairo to CairoOperations
+        https://bugs.webkit.org/show_bug.cgi?id=179599
+
+        Reviewed by Carlos Garcia Campos.
+
+        Move operations that perform filling, stroking and clearing for
+        specified rectangles and paths to the CairoOperations file. This limits
+        operations to only work with a PlatformContextCairo object, along with
+        any required parameter, and will help with future work in this area.
+
+        Helper functions are copied along for the time being, but will later be
+        removed from the GraphicsContextCairo implementation file.
+
+        No new tests -- no change in behavior.
+
+        * platform/graphics/cairo/CairoOperations.cpp:
+        (WebCore::Cairo::fillRectWithColor):
+        (WebCore::Cairo::drawPathShadow):
+        (WebCore::Cairo::fillCurrentCairoPath):
+        (WebCore::Cairo::fillRect):
+        (WebCore::Cairo::fillRoundedRect):
+        (WebCore::Cairo::fillRectWithRoundedHole):
+        (WebCore::Cairo::fillPath):
+        (WebCore::Cairo::strokeRect):
+        (WebCore::Cairo::strokePath):
+        (WebCore::Cairo::clearRect):
+        * platform/graphics/cairo/CairoOperations.h:
+        * platform/graphics/cairo/GradientCairo.cpp:
+        (WebCore::Gradient::fill):
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::fillPath):
+        (WebCore::GraphicsContext::strokePath):
+        (WebCore::GraphicsContext::fillRect):
+        (WebCore::GraphicsContext::clearRect):
+        (WebCore::GraphicsContext::strokeRect):
+        (WebCore::GraphicsContext::platformFillRoundedRect):
+        (WebCore::GraphicsContext::fillRectWithRoundedHole):
+
+2017-11-12  Zan Dobersek  <[email protected]>
+
         [Cairo] Move state stack, CTM, transparency layer operations in GraphicsContextCairo to CairoOperations
         https://bugs.webkit.org/show_bug.cgi?id=179598
 

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


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2017-11-13 07:41:18 UTC (rev 224745)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.cpp	2017-11-13 07:43:22 UTC (rev 224746)
@@ -36,6 +36,7 @@
 #if USE(CAIRO)
 
 #include "FloatRect.h"
+#include "GraphicsContext.h"
 #include "Image.h"
 #include "Path.h"
 #include "PlatformContextCairo.h"
@@ -45,6 +46,93 @@
 namespace WebCore {
 namespace Cairo {
 
+static inline void fillRectWithColor(cairo_t* cr, const FloatRect& rect, const Color& color)
+{
+    if (!color.isVisible() && cairo_get_operator(cr) == CAIRO_OPERATOR_OVER)
+        return;
+
+    setSourceRGBAFromColor(cr, color);
+    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+    cairo_fill(cr);
+}
+
+enum PathDrawingStyle {
+    Fill = 1,
+    Stroke = 2,
+    FillAndStroke = Fill + Stroke
+};
+
+static inline void drawPathShadow(PlatformContextCairo& platformContext, const GraphicsContextState& contextState, GraphicsContext& targetContext, PathDrawingStyle drawingStyle)
+{
+    ShadowBlur& shadow = platformContext.shadowBlur();
+    if (shadow.type() == ShadowBlur::NoShadow)
+        return;
+
+    // Calculate the extents of the rendered solid paths.
+    cairo_t* cairoContext = platformContext.cr();
+    std::unique_ptr<cairo_path_t, void(*)(cairo_path_t*)> path(cairo_copy_path(cairoContext), [](cairo_path_t* path) {
+        cairo_path_destroy(path);
+    });
+
+    FloatRect solidFigureExtents;
+    double x0 = 0;
+    double x1 = 0;
+    double y0 = 0;
+    double y1 = 0;
+    if (drawingStyle & Stroke) {
+        cairo_stroke_extents(cairoContext, &x0, &y0, &x1, &y1);
+        solidFigureExtents = FloatRect(x0, y0, x1 - x0, y1 - y0);
+    }
+    if (drawingStyle & Fill) {
+        cairo_fill_extents(cairoContext, &x0, &y0, &x1, &y1);
+        FloatRect fillExtents(x0, y0, x1 - x0, y1 - y0);
+        solidFigureExtents.unite(fillExtents);
+    }
+
+    GraphicsContext* shadowContext = shadow.beginShadowLayer(targetContext, solidFigureExtents);
+    if (!shadowContext)
+        return;
+
+    cairo_t* cairoShadowContext = shadowContext->platformContext()->cr();
+
+    // It's important to copy the context properties to the new shadow
+    // context to preserve things such as the fill rule and stroke width.
+    copyContextProperties(cairoContext, cairoShadowContext);
+
+    if (drawingStyle & Fill) {
+        cairo_save(cairoShadowContext);
+        cairo_append_path(cairoShadowContext, path.get());
+        shadowContext->platformContext()->prepareForFilling(contextState, PlatformContextCairo::NoAdjustment);
+        cairo_fill(cairoShadowContext);
+        cairo_restore(cairoShadowContext);
+    }
+
+    if (drawingStyle & Stroke) {
+        cairo_append_path(cairoShadowContext, path.get());
+        shadowContext->platformContext()->prepareForStroking(contextState, PlatformContextCairo::DoNotPreserveAlpha);
+        cairo_stroke(cairoShadowContext);
+    }
+
+    // The original path may still be hanging around on the context and endShadowLayer
+    // will take care of properly creating a path to draw the result shadow. We remove the path
+    // temporarily and then restore it.
+    // See: https://bugs.webkit.org/show_bug.cgi?id=108897
+    cairo_new_path(cairoContext);
+    shadow.endShadowLayer(targetContext);
+    cairo_append_path(cairoContext, path.get());
+}
+
+static inline void fillCurrentCairoPath(PlatformContextCairo& platformContext, const GraphicsContextState& contextState)
+{
+    cairo_t* cr = platformContext.cr();
+    cairo_save(cr);
+
+    platformContext.prepareForFilling(contextState, PlatformContextCairo::AdjustPatternForGlobalAlpha);
+    cairo_fill(cr);
+
+    cairo_restore(cr);
+}
+
 void setLineCap(PlatformContextCairo& platformContext, LineCap lineCap)
 {
     cairo_line_cap_t cairoCap;
@@ -92,6 +180,115 @@
     cairo_set_miter_limit(platformContext.cr(), miterLimit);
 }
 
+void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, const GraphicsContextState& contextState, 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);
+}
+
+void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, const Color& color, bool hasShadow, GraphicsContext& targetContext)
+{
+    if (hasShadow)
+        platformContext.shadowBlur().drawRectShadow(targetContext, FloatRoundedRect(rect));
+
+    fillRectWithColor(platformContext.cr(), rect, color);
+}
+
+void fillRect(PlatformContextCairo& platformContext, const FloatRect& rect, cairo_pattern_t* platformPattern)
+{
+    cairo_t* cr = platformContext.cr();
+
+    cairo_set_source(cr, platformPattern);
+    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+    cairo_fill(cr);
+}
+
+void fillRoundedRect(PlatformContextCairo& platformContext, const FloatRoundedRect& rect, const Color& color, bool hasShadow, GraphicsContext& targetContext)
+{
+    if (hasShadow)
+        platformContext.shadowBlur().drawRectShadow(targetContext, rect);
+
+    cairo_t* cr = platformContext.cr();
+    cairo_save(cr);
+
+    Path path;
+    path.addRoundedRect(rect);
+    appendWebCorePathToCairoContext(cr, path);
+    setSourceRGBAFromColor(cr, color);
+    cairo_fill(cr);
+
+    cairo_restore(cr);
+}
+
+void fillRectWithRoundedHole(PlatformContextCairo& platformContext, const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const GraphicsContextState& contextState, bool mustUseShadowBlur, GraphicsContext& targetContext)
+{
+    // FIXME: this should leverage the specified color.
+
+    if (mustUseShadowBlur)
+        platformContext.shadowBlur().drawInsetShadow(targetContext, rect, roundedHoleRect);
+
+    Path path;
+    path.addRect(rect);
+    if (!roundedHoleRect.radii().isZero())
+        path.addRoundedRect(roundedHoleRect);
+    else
+        path.addRect(roundedHoleRect.rect());
+
+    cairo_t* cr = platformContext.cr();
+
+    cairo_save(cr);
+    setPathOnCairoContext(platformContext.cr(), path.platformPath()->context());
+    fillCurrentCairoPath(platformContext, contextState);
+    cairo_restore(cr);
+}
+
+void fillPath(PlatformContextCairo& platformContext, const Path& path, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+{
+    cairo_t* cr = platformContext.cr();
+
+    setPathOnCairoContext(cr, path.platformPath()->context());
+    drawPathShadow(platformContext, contextState, targetContext, Fill);
+    fillCurrentCairoPath(platformContext, contextState);
+}
+
+void strokeRect(PlatformContextCairo& platformContext, const FloatRect& rect, float lineWidth, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+{
+    cairo_t* cr = platformContext.cr();
+    cairo_save(cr);
+
+    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);
+    cairo_stroke(cr);
+
+    cairo_restore(cr);
+}
+
+void strokePath(PlatformContextCairo& platformContext, const Path& path, const GraphicsContextState& contextState, GraphicsContext& targetContext)
+{
+    cairo_t* cr = platformContext.cr();
+
+    setPathOnCairoContext(cr, path.platformPath()->context());
+    drawPathShadow(platformContext, contextState, targetContext, Stroke);
+    platformContext.prepareForStroking(contextState);
+    cairo_stroke(cr);
+}
+
+void clearRect(PlatformContextCairo& platformContext, const FloatRect& rect)
+{
+    cairo_t* cr = platformContext.cr();
+
+    cairo_save(cr);
+    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+    cairo_fill(cr);
+    cairo_restore(cr);
+}
+
 void save(PlatformContextCairo& platformContext)
 {
     platformContext.save();

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


--- trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2017-11-13 07:41:18 UTC (rev 224745)
+++ trunk/Source/WebCore/platform/graphics/cairo/CairoOperations.h	2017-11-13 07:43:22 UTC (rev 224746)
@@ -37,11 +37,17 @@
 #include "DashArray.h"
 #include "GraphicsTypes.h"
 
+typedef struct _cairo_pattern cairo_pattern_t;
+
 namespace WebCore {
 
 class AffineTransform;
+class Color;
 class FloatRect;
+class FloatRoundedRect;
 class FloatSize;
+class GraphicsContext;
+class GraphicsContextState;
 class Image;
 class Path;
 class PlatformContextCairo;
@@ -53,6 +59,16 @@
 void setLineJoin(PlatformContextCairo&, LineJoin);
 void setMiterLimit(PlatformContextCairo&, float);
 
+void fillRect(PlatformContextCairo&, const FloatRect&, const GraphicsContextState&, 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&, bool, 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 clearRect(PlatformContextCairo&, const FloatRect&);
+
 void save(PlatformContextCairo&);
 void restore(PlatformContextCairo&);
 

Modified: trunk/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp (224745 => 224746)


--- trunk/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp	2017-11-13 07:41:18 UTC (rev 224745)
+++ trunk/Source/WebCore/platform/graphics/cairo/GradientCairo.cpp	2017-11-13 07:43:22 UTC (rev 224746)
@@ -79,15 +79,11 @@
 
 void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
 {
-    RefPtr<cairo_pattern_t> gradient = adoptRef(createPlatformGradient(1.0));
+    RefPtr<cairo_pattern_t> platformGradient = adoptRef(createPlatformGradient(1.0));
 
     context->save();
-
-    cairo_t* cr = context->platformContext()->cr();
-    cairo_set_source(cr, gradient.get());
-    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
-    cairo_fill(cr);
-
+    ASSERT(context->hasPlatformContext());
+    Cairo::fillRect(*context->platformContext(), rect, platformGradient.get());
     context->restore();
 }
 

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


--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2017-11-13 07:41:18 UTC (rev 224745)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp	2017-11-13 07:43:22 UTC (rev 224746)
@@ -411,9 +411,8 @@
         return;
     }
 
-    cairo_t* cr = platformContext()->cr();
-    setPathOnCairoContext(cr, path.platformPath()->context());
-    shadowAndFillCurrentCairoPath(*this);
+    ASSERT(hasPlatformContext());
+    Cairo::fillPath(*platformContext(), path, state(), *this);
 }
 
 void GraphicsContext::strokePath(const Path& path)
@@ -426,9 +425,8 @@
         return;
     }
 
-    cairo_t* cr = platformContext()->cr();
-    setPathOnCairoContext(cr, path.platformPath()->context());
-    shadowAndStrokeCurrentCairoPath(*this);
+    ASSERT(hasPlatformContext());
+    Cairo::strokePath(*platformContext(), path, state(), *this);
 }
 
 void GraphicsContext::fillRect(const FloatRect& rect)
@@ -441,9 +439,8 @@
         return;
     }
 
-    cairo_t* cr = platformContext()->cr();
-    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
-    shadowAndFillCurrentCairoPath(*this);
+    ASSERT(hasPlatformContext());
+    Cairo::fillRect(*platformContext(), rect, state(), *this);
 }
 
 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
@@ -456,10 +453,8 @@
         return;
     }
 
-    if (hasShadow())
-        platformContext()->shadowBlur().drawRectShadow(*this, FloatRoundedRect(rect));
-
-    fillRectWithColor(platformContext()->cr(), rect, color);
+    ASSERT(hasPlatformContext());
+    Cairo::fillRect(*platformContext(), rect, color, hasShadow(), *this);
 }
 
 void GraphicsContext::clip(const FloatRect& rect)
@@ -882,31 +877,22 @@
         return;
     }
 
-    cairo_t* cr = platformContext()->cr();
-
-    cairo_save(cr);
-    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
-    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-    cairo_fill(cr);
-    cairo_restore(cr);
+    ASSERT(hasPlatformContext());
+    Cairo::clearRect(*platformContext(), rect);
 }
 
-void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
 {
     if (paintingDisabled())
         return;
 
     if (m_impl) {
-        m_impl->strokeRect(rect, width);
+        m_impl->strokeRect(rect, lineWidth);
         return;
     }
 
-    cairo_t* cr = platformContext()->cr();
-    cairo_save(cr);
-    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
-    cairo_set_line_width(cr, width);
-    shadowAndStrokeCurrentCairoPath(*this);
-    cairo_restore(cr);
+    ASSERT(hasPlatformContext());
+    Cairo::strokeRect(*platformContext(), rect, lineWidth, state(), *this);
 }
 
 void GraphicsContext::setLineCap(LineCap lineCap)
@@ -1048,18 +1034,7 @@
         return;
 
     ASSERT(hasPlatformContext());
-
-    if (hasShadow())
-        platformContext()->shadowBlur().drawRectShadow(*this, rect);
-
-    cairo_t* cr = platformContext()->cr();
-    cairo_save(cr);
-    Path path;
-    path.addRoundedRect(rect);
-    appendWebCorePathToCairoContext(cr, path);
-    setSourceRGBAFromColor(cr, color);
-    cairo_fill(cr);
-    cairo_restore(cr);
+    Cairo::fillRoundedRect(*platformContext(), rect, color, hasShadow(), *this);
 }
 
 void GraphicsContext::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
@@ -1072,21 +1047,8 @@
         return;
     }
 
-    if (this->mustUseShadowBlur())
-        platformContext()->shadowBlur().drawInsetShadow(*this, rect, roundedHoleRect);
-
-    Path path;
-    path.addRect(rect);
-    if (!roundedHoleRect.radii().isZero())
-        path.addRoundedRect(roundedHoleRect);
-    else
-        path.addRect(roundedHoleRect.rect());
-
-    cairo_t* cr = platformContext()->cr();
-    cairo_save(cr);
-    setPathOnCairoContext(platformContext()->cr(), path.platformPath()->context());
-    fillCurrentCairoPath(*this);
-    cairo_restore(cr);
+    ASSERT(hasPlatformContext());
+    Cairo::fillRectWithRoundedHole(*platformContext(), rect, roundedHoleRect, state(), mustUseShadowBlur(), *this);
 }
 
 void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to