[Webkit-unassigned] [Bug 41732] [GTK] Bring behavior of paths on the Cairo GraphicsContext into line with the CoreGraphics port
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Mon Jul 12 11:54:56 PDT 2010
https://bugs.webkit.org/show_bug.cgi?id=41732
--- Comment #2 from Brent Fulgham <bfulgham at webkit.org> 2010-07-12 11:54:57 PST ---
(From update of attachment 61084)
> diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
> index 4c7f4a6e441aa83fac483dda6abedbffabe6a225..baef5072848f85bfbffb6df354cc3832cdd85b05 100644
> --- a/WebCore/ChangeLog
> +++ b/WebCore/ChangeLog
> @@ -1,3 +1,46 @@
> +2010-07-09 Martin Robinson <mrobinson at igalia.com>
> +
> + Reviewed by NOBODY (OOPS!).
> +
> + [GTK] Bring behavior of paths on the Cairo GraphicsContext into line with the CoreGraphics port
> + https://bugs.webkit.org/show_bug.cgi?id=41732
> +
> + Make drawing routines on the Cairo graphics context independent from path manipulation.
> + This means that drawing shapes does not affect in any way paths added to the context via
> + addPath. Furthermore, paths added to the context do not affect shapes drawn via methods
> + such as drawEllipse. cairo_save() and cairo_restore() do not affect any path that is on
> + the cairo context, so we do this manually.
> +
> + This behavior is necessary to close bug https://bugs.webkit.org/show_bug.cgi?id=41308
> + so tests for that issue will test this fix.
> +
> + * platform/graphics/cairo/GraphicsContextCairo.cpp:
> + (WebCore::GraphicsContextPlatformPrivate::saveCairoPath): Added. This method
> + saves the current cairo path to a member variable and begins a new path on
> + the context.
> + (WebCore::GraphicsContextPlatformPrivate::restoreCairoPath): Added. Restores the
> + saved cairo path to the context if one exists.
> + (WebCore::GraphicsContext::drawRect): Guard the previous path on the cairo context by
> + calling the saveCairoPath/restoreCairoPath pair.
> + (WebCore::GraphicsContext::drawLine): Ditto.
> + (WebCore::GraphicsContext::drawEllipse): Ditto
> + (WebCore::GraphicsContext::strokeArc): Ditto
> + (WebCore::GraphicsContext::drawConvexPolygon): Ditto.
> + (WebCore::GraphicsContext::fillRect): Ditto.
> + (WebCore::GraphicsContext::clip): Ditto.
> + (WebCore::GraphicsContext::clipPath): Ditto.
> + (WebCore::GraphicsContext::drawFocusRing): Ditto.
> + (WebCore::GraphicsContext::drawLineForMisspellingOrBadGrammar): Ditto
> + (WebCore::GraphicsContext::addInnerRoundedRectClip): Ditto.
> + (WebCore::GraphicsContext::clearRect): Ditto.
> + (WebCore::GraphicsContext::strokeRect): Ditto.
> + (WebCore::GraphicsContext::clipOut): Ditto.
> + (WebCore::GraphicsContext::fillRoundedRect): Ditto.
> + * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h: Added a member variable
> + for caching a cairo path so that it can be saved and restored while doing other operations.
> + (WebCore::GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate): Intialize the
> + saved path to 0.
> +
> 2010-07-08 Jon Honeycutt <jhoneycutt at apple.com>
>
> Missing plug-ins may cause an assertion failure.
> diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
> index 8b62267b365e959e67727e92f7fff614a0d1f5a7..5931039787085b71387e8e4cfa3358642d489428 100644
> --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
> +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
> @@ -143,6 +143,25 @@ static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
> cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
> }
>
> +void GraphicsContextPlatformPrivate::saveCairoPath()
> +{
> + if (m_savedCairoPath)
> + cairo_path_destroy(m_savedCairoPath);
> + m_savedCairoPath = cairo_copy_path(cr);
> + cairo_new_path(cr);
> +}
> +
> +void GraphicsContextPlatformPrivate::restoreCairoPath()
> +{
> + if (!m_savedCairoPath)
> + return;
> +
> + cairo_new_path(cr);
> + cairo_append_path(cr, m_savedCairoPath);
> + cairo_path_destroy(m_savedCairoPath);
> + m_savedCairoPath = 0;
> +}
> +
> void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur)
> {
> #if ENABLE(FILTERS)
> @@ -249,6 +268,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
>
> if (fillColor().alpha())
> fillRectSourceOver(cr, rect, fillColor());
> @@ -263,6 +283,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
> }
>
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> // This is only used to draw borders.
> @@ -277,6 +298,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
>
> float width = strokeThickness();
> if (width < 1)
> @@ -354,6 +376,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
>
> cairo_stroke(cr);
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> // This method is only used to draw the little circles used in lists.
> @@ -364,6 +387,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
> float yRadius = .5 * rect.height();
> float xRadius = .5 * rect.width();
> cairo_translate(cr, rect.x() + xRadius, rect.y() + yRadius);
> @@ -382,7 +406,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
> cairo_stroke(cr);
> }
>
> - cairo_new_path(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
> @@ -404,6 +428,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
>
> if (w != h)
> cairo_scale(cr, 1., scaleFactor);
> @@ -469,6 +494,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
>
> cairo_stroke(cr);
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
> @@ -480,8 +506,9 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
> return;
>
> cairo_t* cr = m_data->cr;
> -
> cairo_save(cr);
> + m_data->saveCairoPath();
> +
> 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++)
> @@ -502,6 +529,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
>
> cairo_new_path(cr);
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
> @@ -563,8 +591,14 @@ void GraphicsContext::fillRect(const FloatRect& rect)
> return;
>
> cairo_t* cr = m_data->cr;
> + cairo_save(cr);
> + m_data->saveCairoPath();
> +
> cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
> fillPath();
> +
> + cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
> @@ -596,9 +630,16 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
> if (paintingDisabled())
> return;
>
> + cairo_t* cr = m_data->cr;
> + cairo_save(cr);
> + m_data->saveCairoPath();
> +
> drawBorderlessRectShadow(this, rect, color);
> if (color.alpha())
> fillRectSourceOver(m_data->cr, rect, color);
> +
> + cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::clip(const FloatRect& rect)
> @@ -607,12 +648,16 @@ void GraphicsContext::clip(const FloatRect& rect)
> return;
>
> cairo_t* cr = m_data->cr;
> + m_data->saveCairoPath();
> +
> cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
> cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
> cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
> cairo_clip(cr);
> cairo_set_fill_rule(cr, savedFillRule);
> m_data->clip(rect);
> +
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::clipPath(WindRule clipRule)
> @@ -623,6 +668,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
> cairo_t* cr = m_data->cr;
> cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
> cairo_clip(cr);
> + cairo_new_path(cr);
> }
>
> void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
> @@ -639,6 +685,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
> cairo_push_group(cr);
> cairo_new_path(cr);
>
> @@ -691,6 +738,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
> cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
> cairo_paint(cr);
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
> @@ -719,6 +767,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin,
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
>
> // Convention is green for grammar, red for spelling
> // These need to become configurable
> @@ -735,6 +784,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin,
> #endif
>
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
> @@ -844,6 +894,8 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
> if (paintingDisabled())
> return;
>
> + m_data->saveCairoPath();
> +
> clip(rect);
>
> Path p;
> @@ -860,6 +912,8 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
> cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
> cairo_clip(cr);
> cairo_set_fill_rule(cr, savedFillRule);
> +
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
> @@ -949,12 +1003,15 @@ void GraphicsContext::clearRect(const FloatRect& rect)
> return;
>
> cairo_t* cr = m_data->cr;
> -
> cairo_save(cr);
> + m_data->saveCairoPath();
> +
> cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
> cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
> cairo_fill(cr);
> +
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::strokeRect(const FloatRect& rect, float width)
> @@ -964,10 +1021,14 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
>
> cairo_t* cr = m_data->cr;
> cairo_save(cr);
> + m_data->saveCairoPath();
> +
> cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
> cairo_set_line_width(cr, width);
> strokePath();
> +
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::setLineCap(LineCap lineCap)
> @@ -1104,6 +1165,8 @@ void GraphicsContext::clip(const Path& path)
> return;
>
> cairo_t* cr = m_data->cr;
> + m_data->saveCairoPath();
> +
> cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
> cairo_append_path(cr, p);
> cairo_path_destroy(p);
> @@ -1112,6 +1175,8 @@ void GraphicsContext::clip(const Path& path)
> cairo_clip(cr);
> cairo_set_fill_rule(cr, savedFillRule);
> m_data->clip(path);
> +
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::canvasClip(const Path& path)
> @@ -1125,15 +1190,18 @@ void GraphicsContext::clipOut(const Path& path)
> return;
>
> cairo_t* cr = m_data->cr;
> + m_data->saveCairoPath();
> + cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
> +
> double x1, y1, x2, y2;
> cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
> cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
> addPath(path);
> -
> - cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
> cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
> cairo_clip(cr);
> +
> cairo_set_fill_rule(cr, savedFillRule);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::rotate(float radians)
> @@ -1160,14 +1228,18 @@ void GraphicsContext::clipOut(const IntRect& r)
> return;
>
> cairo_t* cr = m_data->cr;
> + m_data->saveCairoPath();
> + cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
> +
> double x1, y1, x2, y2;
> cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
> cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
> cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
> - cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
> cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
> cairo_clip(cr);
> +
> cairo_set_fill_rule(cr, savedFillRule);
> + m_data->restoreCairoPath();
> }
>
> void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
> @@ -1186,13 +1258,17 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
> return;
>
> cairo_t* cr = m_data->cr;
> + m_data->saveCairoPath();
> +
> cairo_save(cr);
> beginPath();
> addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
> setColor(cr, color);
> drawPathShadow(this, m_common, true, false);
> cairo_fill(cr);
> +
> cairo_restore(cr);
> + m_data->restoreCairoPath();
> }
>
> #if PLATFORM(GTK)
> diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
> index 5e388324dcd6fb1e71db1ea582be69743a0b8eb3..b6c07e7ffba71291cf7279f2bb22b89c9ea31d85 100644
> --- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
> +++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
> @@ -45,6 +45,7 @@ class GraphicsContextPlatformPrivate {
> public:
> GraphicsContextPlatformPrivate()
> : cr(0)
> + , m_savedCairoPath(0)
> #if PLATFORM(GTK)
> , expose(0)
> #elif PLATFORM(WIN)
> @@ -52,6 +53,7 @@ public:
> , m_hdc(0)
> , m_transparencyCount(0)
> , m_shouldIncludeChildWindows(false)
> + , m_shouldIncludeChildWindows(false)
> #endif
> {
> }
> @@ -61,6 +63,9 @@ public:
> cairo_destroy(cr);
> }
>
> + void saveCairoPath();
> + void restoreCairoPath();
> +
> #if PLATFORM(WIN)
> // On Windows, we need to update the HDC for form controls to draw in the right place.
> void save();
> @@ -95,6 +100,7 @@ public:
>
> cairo_t* cr;
> Vector<float> layers;
> + cairo_path_t* m_savedCairoPath;
>
> #if PLATFORM(GTK)
> GdkEventExpose* expose;
WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp:149
+ cairo_path_destroy(m_savedCairoPath);
Do we know that we will only ever be one level deep? Could the 'saveCairoPath' be hit during a recursive call to the graphic context?
--
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.
More information about the webkit-unassigned
mailing list