[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