summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-08-04 11:41:34 +0100
committerSteve Block <steveblock@google.com>2010-08-09 12:04:44 +0100
commitdb14019a23d96bc8a444b6576a5da8bd1cfbc8b0 (patch)
tree9f793c5b0f5e1f2aca8247158920e2c4bf962bbf /WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
parentbf916837aa84f1e4b00e6ed6268516c2acd27545 (diff)
downloadexternal_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.zip
external_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.tar.gz
external_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.tar.bz2
Merge WebKit at r64523 : Initial merge by git.
Change-Id: Ibb796c6802e757b1d9b40f58205cfbe4da95fcd4
Diffstat (limited to 'WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp')
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp126
1 files changed, 84 insertions, 42 deletions
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 96cd4ee..f3fc943 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -4,6 +4,7 @@
* Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2008 Nuanti Ltd.
* Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ * Copyright (C) 2010 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -143,6 +144,35 @@ static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
}
+static void appendPathToCairoContext(cairo_t* to, cairo_t* from)
+{
+ cairo_path_t* cairoPath = cairo_copy_path(from);
+ cairo_append_path(to, cairoPath);
+ cairo_path_destroy(cairoPath);
+}
+
+// We apply the pending path built via addPath to the Cairo context
+// lazily. This prevents interaction between the path and other routines
+// such as fillRect.
+static void setPathOnCairoContext(cairo_t* to, cairo_t* from)
+{
+ cairo_new_path(to);
+ appendPathToCairoContext(to, from);
+}
+
+static void appendWebCorePathToCairoContext(cairo_t* context, const Path& path)
+{
+ appendPathToCairoContext(context, path.platformPath()->context());
+}
+
+static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const FloatPoint* points)
+{
+ cairo_move_to(context, points[0].x(), points[0].y());
+ for (size_t i = 1; i < numPoints; i++)
+ cairo_line_to(context, points[i].x(), points[i].y());
+ cairo_close_path(context);
+}
+
void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur)
{
#if ENABLE(FILTERS)
@@ -201,6 +231,22 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
#endif
}
+static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
+{
+ cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ drawPathShadow(context, gcp, true, false);
+
+ setPlatformFill(context, cairoContext, gcp);
+ cairo_new_path(cairoContext);
+}
+
+static void strokeCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
+{
+ drawPathShadow(context, gcp, false, true);
+ setPlatformStroke(context, cairoContext, gcp);
+ cairo_new_path(cairoContext);
+}
+
GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate)
@@ -380,9 +426,8 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
setColor(cr, strokeColor());
cairo_set_line_width(cr, strokeThickness());
cairo_stroke(cr);
- }
-
- cairo_new_path(cr);
+ } else
+ cairo_new_path(cr);
}
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
@@ -483,10 +528,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
cairo_save(cr);
cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
- cairo_move_to(cr, points[0].x(), points[0].y());
- for (size_t i = 1; i < npoints; i++)
- cairo_line_to(cr, points[i].x(), points[i].y());
- cairo_close_path(cr);
+ addConvexPolygonToContext(cr, npoints, points);
if (fillColor().alpha()) {
setColor(cr, fillColor());
@@ -498,9 +540,9 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
setColor(cr, strokeColor());
cairo_set_line_width(cr, strokeThickness());
cairo_stroke(cr);
- }
+ } else
+ cairo_new_path(cr);
- cairo_new_path(cr);
cairo_restore(cr);
}
@@ -511,8 +553,20 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
if (numPoints <= 1)
return;
-
- // FIXME: IMPLEMENT!
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_new_path(cr);
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_antialias_t savedAntialiasRule = cairo_get_antialias(cr);
+
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
+ addConvexPolygonToContext(cr, numPoints, points);
+ cairo_clip(cr);
+
+ cairo_set_antialias(cr, savedAntialiasRule);
+ cairo_set_fill_rule(cr, savedFillRule);
}
void GraphicsContext::fillPath()
@@ -522,11 +576,8 @@ void GraphicsContext::fillPath()
cairo_t* cr = m_data->cr;
- cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(this, m_common, true, false);
-
- setPlatformFill(this, cr, m_common);
- cairo_new_path(cr);
+ setPathOnCairoContext(cr, m_data->m_pendingPath.context());
+ fillCurrentCairoPath(this, m_common, cr);
}
void GraphicsContext::strokePath()
@@ -535,11 +586,8 @@ void GraphicsContext::strokePath()
return;
cairo_t* cr = m_data->cr;
- drawPathShadow(this, m_common, false, true);
-
- setPlatformStroke(this, cr, m_common);
- cairo_new_path(cr);
-
+ setPathOnCairoContext(cr, m_data->m_pendingPath.context());
+ strokeCurrentCairoPath(this, m_common, cr);
}
void GraphicsContext::drawPath()
@@ -549,6 +597,8 @@ void GraphicsContext::drawPath()
cairo_t* cr = m_data->cr;
+ setPathOnCairoContext(cr, m_data->m_pendingPath.context());
+
cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
drawPathShadow(this, m_common, true, true);
@@ -565,7 +615,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
cairo_t* cr = m_data->cr;
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- fillPath();
+ fillCurrentCairoPath(this, m_common, cr);
cairo_restore(cr);
}
@@ -673,7 +723,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
#else
int radius = (width - 1) / 2;
for (unsigned i = 0; i < rectCount; i++)
- addPath(Path::createRoundedRectangle(rects[i], FloatSize(radius, radius)));
+ appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(rects[i], FloatSize(radius, radius)));
// Force the alpha to 50%. This matches what the Mac does with outline rings.
Color ringColor(color.red(), color.green(), color.blue(), 127);
@@ -700,14 +750,8 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr
if (paintingDisabled())
return;
- // This is a workaround for http://bugs.webkit.org/show_bug.cgi?id=15659
- StrokeStyle savedStrokeStyle = strokeStyle();
- setStrokeStyle(SolidStroke);
-
IntPoint endPoint = origin + IntSize(width, 0);
drawLine(origin, endPoint);
-
- setStrokeStyle(savedStrokeStyle);
}
#if !PLATFORM(GTK)
@@ -846,6 +890,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
if (paintingDisabled())
return;
+ cairo_t* cr = m_data->cr;
clip(rect);
Path p;
@@ -855,9 +900,8 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
// Add inner ellipse
r.inflate(-thickness);
p.addEllipse(r);
- addPath(p);
+ appendWebCorePathToCairoContext(cr, p);
- cairo_t* cr = m_data->cr;
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip(cr);
@@ -968,7 +1012,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_set_line_width(cr, width);
- strokePath();
+ strokeCurrentCairoPath(this, m_common, cr);
cairo_restore(cr);
}
@@ -1085,8 +1129,7 @@ void GraphicsContext::beginPath()
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
- cairo_new_path(cr);
+ cairo_new_path(m_data->m_pendingPath.context());
}
void GraphicsContext::addPath(const Path& path)
@@ -1094,10 +1137,10 @@ void GraphicsContext::addPath(const Path& path)
if (paintingDisabled())
return;
- cairo_t* cr = m_data->cr;
- cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
- cairo_append_path(cr, p);
- cairo_path_destroy(p);
+ cairo_matrix_t currentMatrix;
+ cairo_get_matrix(m_data->cr, &currentMatrix);
+ cairo_set_matrix(m_data->m_pendingPath.context(), &currentMatrix);
+ appendWebCorePathToCairoContext(m_data->m_pendingPath.context(), path);
}
void GraphicsContext::clip(const Path& path)
@@ -1106,7 +1149,7 @@ void GraphicsContext::clip(const Path& path)
return;
cairo_t* cr = m_data->cr;
- cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
+ cairo_path_t* p = cairo_copy_path(path.platformPath()->context());
cairo_append_path(cr, p);
cairo_path_destroy(p);
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
@@ -1130,7 +1173,7 @@ void GraphicsContext::clipOut(const Path& path)
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
- addPath(path);
+ appendWebCorePathToCairoContext(cr, path);
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -1189,8 +1232,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
cairo_t* cr = m_data->cr;
cairo_save(cr);
- beginPath();
- addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
+ appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
setColor(cr, color);
drawPathShadow(this, m_common, true, false);
cairo_fill(cr);