From: krit@webkit.org Date: Sun, 2 Sep 2012 00:15:33 +0000 (+0000) Subject: [Cherry-pick] Use -webkit-clip-path shapes to clip SVG elements X-Git-Tag: 2.1_release~291 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd7d2b0768bc3e49c0a0190e0b856c9591ed9898;p=platform%2Fframework%2Fweb%2Fwebkit-efl.git [Cherry-pick] Use -webkit-clip-path shapes to clip SVG elements [Title] Use -webkit-clip-path shapes to clip SVG elements [Issues] N/A [Problem] N/A [Solution] Cherry picked. [Cherry-Picker] Sanghyup Lee Use -webkit-clip-path shapes to clip SVG elements https://bugs.webkit.org/show_bug.cgi?id=95620 Reviewed by Rob Buis. Source/WebCore: This patch adds a path segment for a BasicShape to a given Path object. This path and it's wind rule are used to clip the context of the SVG element. Tests: svg/clip-path/clip-path-shape-circle-1-expected.svg svg/clip-path/clip-path-shape-circle-1.svg svg/clip-path/clip-path-shape-circle-2-expected.svg svg/clip-path/clip-path-shape-circle-2.svg svg/clip-path/clip-path-shape-ellipse-1-expected.svg svg/clip-path/clip-path-shape-ellipse-1.svg svg/clip-path/clip-path-shape-ellipse-2-expected.svg svg/clip-path/clip-path-shape-ellipse-2.svg svg/clip-path/clip-path-shape-polygon-1-expected.svg svg/clip-path/clip-path-shape-polygon-1.svg svg/clip-path/clip-path-shape-polygon-2-expected.svg svg/clip-path/clip-path-shape-polygon-2.svg svg/clip-path/clip-path-shape-polygon-3-expected.svg svg/clip-path/clip-path-shape-polygon-3.svg svg/clip-path/clip-path-shape-rounded-rect-1-expected.svg svg/clip-path/clip-path-shape-rounded-rect-1.svg svg/clip-path/clip-path-shape-rounded-rect-2-expected.svg svg/clip-path/clip-path-shape-rounded-rect-2.svg * rendering/style/BasicShapes.cpp: Added helper functions that apply path segments to a given path. (WebCore::BasicShapeRectangle::path): (WebCore::BasicShapeCircle::path): (WebCore::BasicShapeEllipse::path): (WebCore::BasicShapePolygon::path): * rendering/style/BasicShapes.h: Make BasicShape virtualized again, since new virtual functions were added. (WebCore::BasicShape::~BasicShape): (BasicShape): (WebCore::BasicShape::windRule): Will return the wind rule of the shape - nonzero by default. (WebCore::BasicShape::BasicShape): (BasicShapeRectangle): (WebCore::BasicShapeRectangle::type): Removed member variable and return type per inheriting class directly. (WebCore::BasicShapeRectangle::BasicShapeRectangle): (BasicShapeCircle): (WebCore::BasicShapeCircle::type): Ditto. (WebCore::BasicShapeCircle::BasicShapeCircle): (BasicShapeEllipse): (WebCore::BasicShapeEllipse::type): Ditto. (WebCore::BasicShapeEllipse::BasicShapeEllipse): (BasicShapePolygon): (WebCore::BasicShapePolygon::windRule): (WebCore::BasicShapePolygon::type): Ditto. (WebCore::BasicShapePolygon::BasicShapePolygon): * rendering/svg/SVGRenderingContext.cpp: If -webkit-clip-path was defined, clip the context to the shape. Right now -webkit-clip-path overrides clip-path, so that people don't use both at the same time. Current clip-path property will be replaced, once -webkit-clip-path gets unprefixed. (WebCore::SVGRenderingContext::prepareToRenderSVGContent): LayoutTests: New tests to check behavior of -webkit-clip-path on SVG elements. * svg/clip-path/clip-path-shape-circle-1-expected.svg: Added. * svg/clip-path/clip-path-shape-circle-1.svg: Added. * svg/clip-path/clip-path-shape-circle-2-expected.svg: Added. * svg/clip-path/clip-path-shape-circle-2.svg: Added. * svg/clip-path/clip-path-shape-ellipse-1-expected.svg: Added. * svg/clip-path/clip-path-shape-ellipse-1.svg: Added. * svg/clip-path/clip-path-shape-ellipse-2-expected.svg: Added. * svg/clip-path/clip-path-shape-ellipse-2.svg: Added. * svg/clip-path/clip-path-shape-polygon-1-expected.svg: Added. * svg/clip-path/clip-path-shape-polygon-1.svg: Added. * svg/clip-path/clip-path-shape-polygon-2-expected.svg: Added. * svg/clip-path/clip-path-shape-polygon-2.svg: Added. * svg/clip-path/clip-path-shape-polygon-3-expected.svg: Added. * svg/clip-path/clip-path-shape-polygon-3.svg: Added. * svg/clip-path/clip-path-shape-rounded-rect-1-expected.svg: Added. * svg/clip-path/clip-path-shape-rounded-rect-1.svg: Added. * svg/clip-path/clip-path-shape-rounded-rect-2-expected.svg: Added. * svg/clip-path/clip-path-shape-rounded-rect-2.svg: Added. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@127383 268f45cc-cd09-0410-ab3c-d52691b4dbfc Conflicts: LayoutTests/ChangeLog Source/WebCore/ChangeLog Change-Id: I0aabeb470a8c5915120a48745bc79747531ba8d3 --- diff --git a/LayoutTests/svg/clip-path/clip-path-shape-circle-1-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-circle-1-expected.svg new file mode 100644 index 0000000..541cf5b --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-circle-1-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-circle-1.svg b/LayoutTests/svg/clip-path/clip-path-shape-circle-1.svg new file mode 100644 index 0000000..57d3326 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-circle-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-circle-2-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-circle-2-expected.svg new file mode 100644 index 0000000..a1813db --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-circle-2-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-circle-2.svg b/LayoutTests/svg/clip-path/clip-path-shape-circle-2.svg new file mode 100644 index 0000000..4533e03 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-circle-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1-expected.svg new file mode 100644 index 0000000..1996c54 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1.svg b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1.svg new file mode 100644 index 0000000..24292e6 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2-expected.svg new file mode 100644 index 0000000..1996c54 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2.svg b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2.svg new file mode 100644 index 0000000..09e1e5c --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-ellipse-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-1-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-1-expected.svg new file mode 100644 index 0000000..551a5f5 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-1-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-1.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-1.svg new file mode 100644 index 0000000..cd92706 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-2-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-2-expected.svg new file mode 100644 index 0000000..3fe05b6 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-2-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-2.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-2.svg new file mode 100644 index 0000000..e573fda --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-3-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-3-expected.svg new file mode 100644 index 0000000..4be712b --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-3-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-polygon-3.svg b/LayoutTests/svg/clip-path/clip-path-shape-polygon-3.svg new file mode 100644 index 0000000..ea2bb4c --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-polygon-3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1-expected.svg new file mode 100644 index 0000000..823897b --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1.svg b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1.svg new file mode 100644 index 0000000..5d3b059 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2-expected.svg b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2-expected.svg new file mode 100644 index 0000000..823897b --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2-expected.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2.svg b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2.svg new file mode 100644 index 0000000..f8312d4 --- /dev/null +++ b/LayoutTests/svg/clip-path/clip-path-shape-rounded-rect-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Source/WebCore/rendering/style/BasicShapes.cpp b/Source/WebCore/rendering/style/BasicShapes.cpp index 2c2b350..b5151f4 100644 --- a/Source/WebCore/rendering/style/BasicShapes.cpp +++ b/Source/WebCore/rendering/style/BasicShapes.cpp @@ -30,26 +30,64 @@ #include "config.h" #include "BasicShapes.h" +#include "FloatRect.h" +#include "LengthFunctions.h" +#include "Path.h" namespace WebCore { -void BasicShape::destroy() +void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox) { - switch (m_type) { - case BASIC_SHAPE_RECTANGLE: - delete static_cast(this); - return; - case BASIC_SHAPE_CIRCLE: - delete static_cast(this); - return; - case BASIC_SHAPE_ELLIPSE: - delete static_cast(this); - return; - case BASIC_SHAPE_POLYGON: - delete static_cast(this); + ASSERT(path.isEmpty()); + path.addRoundedRect(FloatRect(floatValueForLength(m_x, boundingBox.width()) + boundingBox.x(), + floatValueForLength(m_y, boundingBox.height()) + boundingBox.y(), + floatValueForLength(m_width, boundingBox.width()), + floatValueForLength(m_height, boundingBox.height())), + FloatSize(m_cornerRadiusX.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusX, boundingBox.width()), + m_cornerRadiusY.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusY, boundingBox.height()))); +} + +void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox) +{ + ASSERT(path.isEmpty()); + float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + boundingBox.height() * boundingBox.height()) / 2); + float centerX = floatValueForLength(m_centerX, boundingBox.width()); + float centerY = floatValueForLength(m_centerY, boundingBox.height()); + float radius = floatValueForLength(m_radius, diagonal); + path.addEllipse(FloatRect(centerX - radius + boundingBox.x(), + centerY - radius + boundingBox.y(), + radius * 2, + radius * 2)); +} + +void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox) +{ + ASSERT(path.isEmpty()); + float centerX = floatValueForLength(m_centerX, boundingBox.width()); + float centerY = floatValueForLength(m_centerY, boundingBox.height()); + float radiusX = floatValueForLength(m_radiusX, boundingBox.width()); + float radiusY = floatValueForLength(m_radiusY, boundingBox.height()); + path.addEllipse(FloatRect(centerX - radiusX + boundingBox.x(), + centerY - radiusY + boundingBox.y(), + radiusX * 2, + radiusY * 2)); +} + +void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox) +{ + ASSERT(path.isEmpty()); + ASSERT(!(m_values.size() % 2)); + size_t length = m_values.size(); + + if (!length) return; + + path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()), + floatValueForLength(m_values.at(1), boundingBox.width()))); + for (size_t i = 2; i < length; i = i + 2) { + path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()), + floatValueForLength(m_values.at(i + 1), boundingBox.width()))); } - ASSERT_NOT_REACHED(); + path.closeSubpath(); } - } diff --git a/Source/WebCore/rendering/style/BasicShapes.h b/Source/WebCore/rendering/style/BasicShapes.h index 1d79df7..9c104da 100644 --- a/Source/WebCore/rendering/style/BasicShapes.h +++ b/Source/WebCore/rendering/style/BasicShapes.h @@ -37,31 +37,26 @@ namespace WebCore { -class BasicShape : public WTF::RefCountedBase { +class FloatRect; +class Path; + +class BasicShape : public RefCounted { public: + virtual ~BasicShape() { } + enum Type { BASIC_SHAPE_RECTANGLE = 1, BASIC_SHAPE_CIRCLE = 2, BASIC_SHAPE_ELLIPSE = 3, BASIC_SHAPE_POLYGON = 4 }; - - void deref() - { - if (derefBase()) - destroy(); - } - Type type() const { return m_type; } + virtual void path(Path&, const FloatRect&) = 0; + virtual WindRule windRule() const { return RULE_NONZERO; } + virtual Type type() const = 0; protected: - BasicShape(Type type) - : m_type(type) - { } - -private: - void destroy(); - Type m_type; + BasicShape() { } }; class BasicShapeRectangle : public BasicShape { @@ -81,11 +76,13 @@ public: void setHeight(Length height) { m_height = height; } void setCornerRadiusX(Length radiusX) { m_cornerRadiusX = radiusX; } void setCornerRadiusY(Length radiusY) { m_cornerRadiusY = radiusY; } - + + virtual void path(Path&, const FloatRect&); + + virtual Type type() const { return BASIC_SHAPE_RECTANGLE; } private: BasicShapeRectangle() - : BasicShape(BASIC_SHAPE_RECTANGLE) - , m_cornerRadiusX(Undefined) + : m_cornerRadiusX(Undefined) , m_cornerRadiusY(Undefined) { } @@ -109,10 +106,11 @@ public: void setCenterY(Length centerY) { m_centerY = centerY; } void setRadius(Length radius) { m_radius = radius; } + virtual void path(Path&, const FloatRect&); + + virtual Type type() const { return BASIC_SHAPE_CIRCLE; } private: - BasicShapeCircle() - : BasicShape(BASIC_SHAPE_CIRCLE) - { } + BasicShapeCircle() { } Length m_centerX; Length m_centerY; @@ -133,10 +131,11 @@ public: void setRadiusX(Length radiusX) { m_radiusX = radiusX; } void setRadiusY(Length radiusY) { m_radiusY = radiusY; } + virtual void path(Path&, const FloatRect&); + + virtual Type type() const { return BASIC_SHAPE_ELLIPSE; } private: - BasicShapeEllipse() - : BasicShape(BASIC_SHAPE_ELLIPSE) - { } + BasicShapeEllipse() { } Length m_centerX; Length m_centerY; @@ -148,7 +147,6 @@ class BasicShapePolygon : public BasicShape { public: static PassRefPtr create() { return adoptRef(new BasicShapePolygon); } - WindRule windRule() const { return m_windRule; } const Vector& values() const { return m_values; } Length getXAt(unsigned i) const { return m_values.at(2 * i); } Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); } @@ -156,10 +154,13 @@ public: void setWindRule(WindRule windRule) { m_windRule = windRule; } void appendPoint(Length x, Length y) { m_values.append(x); m_values.append(y); } + virtual void path(Path&, const FloatRect&); + virtual WindRule windRule() const { return m_windRule; } + + virtual Type type() const { return BASIC_SHAPE_POLYGON; } private: BasicShapePolygon() - : BasicShape(BASIC_SHAPE_POLYGON) - , m_windRule(RULE_NONZERO) + : m_windRule(RULE_NONZERO) { } WindRule m_windRule; diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp index e2adb30..9124d47 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp @@ -27,6 +27,7 @@ #if ENABLE(SVG) #include "SVGRenderingContext.h" +#include "BasicShapes.h" #include "Frame.h" #include "FrameView.h" #include "RenderSVGResource.h" @@ -122,6 +123,15 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI } } + BasicShape* clipShape = style->clipPath(); + if (clipShape) { + // FIXME: Investigate if it is better to store and update a Path object in RenderStyle. + // https://bugs.webkit.org/show_bug.cgi?id=95619 + Path clipPath; + clipShape->path(clipPath, object->objectBoundingBox()); + m_paintInfo->context->clipPath(clipPath, clipShape->windRule()); + } + SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(m_object); if (!resources) { #if ENABLE(FILTERS) @@ -139,7 +149,8 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI } } - if (RenderSVGResourceClipper* clipper = resources->clipper()) { + RenderSVGResourceClipper* clipper = resources->clipper(); + if (!clipShape && clipper) { if (!clipper->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode)) return; }