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)