Diff
Modified: trunk/LayoutTests/ChangeLog (134351 => 134352)
--- trunk/LayoutTests/ChangeLog 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/LayoutTests/ChangeLog 2012-11-13 04:51:53 UTC (rev 134352)
@@ -1,3 +1,20 @@
+2012-11-10 Dirk Schulze <k...@webkit.org>
+
+ BasicShapes 'circle', 'rectangle', 'ellipse' should be animatable with themselves
+ https://bugs.webkit.org/show_bug.cgi?id=101854
+
+ Reviewed by Andreas Kling.
+
+ Added an animtation test for -webkit-clip-path and tested the basic shapes.
+
+ * animations/resources/animation-test-helpers.js:
+ (parseBasicShape):
+ (basicShapeParametersMatch):
+ (getPropertyValue):
+ (comparePropertyValue):
+ * css3/masking/clip-path-animation-expected.txt: Added.
+ * css3/masking/clip-path-animation.html: Added.
+
2012-11-12 Erik Arvidsson <a...@chromium.org>
Replace DOMException TYPE_MISMATCH_ERR with TypeError
Modified: trunk/LayoutTests/animations/resources/animation-test-helpers.js (134351 => 134352)
--- trunk/LayoutTests/animations/resources/animation-test-helpers.js 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/LayoutTests/animations/resources/animation-test-helpers.js 2012-11-13 04:51:53 UTC (rev 134352)
@@ -59,6 +59,58 @@
return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[3])}
}
+function parseBasicShape(s)
+{
+ var shapeFunction = s.match(/(\w+)\((.+)\)/);
+ if (!shapeFunction)
+ return null;
+
+ var matches;
+ switch (shapeFunction[1]) {
+ case "rectangle":
+ matches = s.match("rectangle\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\,\\s*(.*)\\)");
+ break;
+ case "circle":
+ matches = s.match("circle\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\)");
+ break;
+ case "ellipse":
+ matches = s.match("ellipse\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\,\\s*(.*)\\)");
+ break;
+ default:
+ return null;
+ }
+
+ if (!matches)
+ return null;
+
+ matches.shift();
+
+ // Normalize percentage values.
+ for (var i = 0; i < matches.length; ++i) {
+ var param = matches[i];
+ matches[i] = parseFloat(matches[i]);
+ if (param.indexOf('%') != -1)
+ matches[i] = matches[i] / 100;
+ }
+
+ return {"shape": shapeFunction[1], "params": matches};
+}
+
+function basicShapeParametersMatch(paramList1, paramList2, tolerance)
+{
+ if (paramList1.shape != paramList2.shape
+ || paramList1.params.length != paramList2.params.length)
+ return false;
+ for (var i = 0; i < paramList1.params.length; ++i) {
+ var param1 = paramList1.params[i],
+ param2 = paramList2.params[i];
+ var match = isCloseEnough(param1, param2, tolerance);
+ if (!match)
+ return false;
+ }
+ return true;
+}
+
// Return an array of numeric filter params in 0-1.
function getFilterParameters(s)
{
@@ -243,6 +295,7 @@
|| property == "webkitMaskImage"
|| property == "webkitMaskBoxImage"
|| property == "webkitFilter"
+ || property == "webkitClipPath"
|| !property.indexOf("webkitTransform")) {
computedValue = window.getComputedStyle(element)[property.split(".")[0]];
} else {
@@ -275,6 +328,12 @@
var filterParameters = getFilterParameters(computedValue);
var filter2Parameters = getFilterParameters(expectedValue);
result = filterParametersMatch(filterParameters, filter2Parameters, tolerance);
+ } else if (property == "webkitClipPath") {
+ var clipPathParameters = parseBasicShape(computedValue);
+ var clipPathParameters2 = parseBasicShape(expectedValue);
+ if (!clipPathParameters || !clipPathParameters2)
+ result = false;
+ result = basicShapeParametersMatch(clipPathParameters, clipPathParameters2, tolerance);
} else if (property == "backgroundImage"
|| property == "borderImageSource"
|| property == "listStyleImage"
Added: trunk/LayoutTests/css3/masking/clip-path-animation-expected.txt (0 => 134352)
--- trunk/LayoutTests/css3/masking/clip-path-animation-expected.txt (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-animation-expected.txt 2012-11-13 04:51:53 UTC (rev 134352)
@@ -0,0 +1,5 @@
+
+PASS - "webkitClipPath" property for "rectangle-box" element at 1s saw something close to: rectangle(10%, 10%, 80%, 80%)
+PASS - "webkitClipPath" property for "circle-box" element at 1s saw something close to: circle(35%, 35%, 35%)
+PASS - "webkitClipPath" property for "ellipse-box" element at 1s saw something close to: ellipse(35%, 35%, 35%, 30%)
+
Added: trunk/LayoutTests/css3/masking/clip-path-animation.html (0 => 134352)
--- trunk/LayoutTests/css3/masking/clip-path-animation.html (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-animation.html 2012-11-13 04:51:53 UTC (rev 134352)
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ .box {
+ height: 100px;
+ width: 100px;
+ margin: 10px;
+ background-color: blue;
+ display: inline-block;
+ }
+
+ #rectangle-box {
+ -webkit-animation: rectangle-anim 2s linear
+ }
+
+ #circle-box {
+ -webkit-animation: circle-anim 2s linear
+ }
+
+ #ellipse-box {
+ -webkit-animation: ellipse-anim 2s linear
+ }
+
+
+ @-webkit-keyframes rectangle-anim {
+ from { -webkit-clip-path: rectangle(0%, 0%, 100%, 100%); }
+ to { -webkit-clip-path: rectangle(20%, 20%, 60%, 60%); }
+ }
+
+ @-webkit-keyframes circle-anim {
+ from { -webkit-clip-path: circle(50%, 50%, 50%); }
+ to { -webkit-clip-path: circle(20%, 20%, 20%); }
+ }
+
+ @-webkit-keyframes ellipse-anim {
+ from { -webkit-clip-path: ellipse(50%, 50%, 50%, 40%); }
+ to { -webkit-clip-path: ellipse(20%, 20%, 20%, 20%); }
+ }
+
+ </style>
+ <script src=""
+ <script type="text/_javascript_">
+ const expectedValues = [
+ // [animation-name, time, element-id, property, expected-value, tolerance]
+ ["rectangle-anim", 1, "rectangle-box", "webkitClipPath", 'rectangle(10%, 10%, 80%, 80%)', 0.05],
+ ["circle-anim", 1, "circle-box", "webkitClipPath", 'circle(35%, 35%, 35%)', 0.05],
+ ["ellipse-anim", 1, "ellipse-box", "webkitClipPath", 'ellipse(35%, 35%, 35%, 30%)', 0.05],
+ ];
+
+ runAnimationTest(expectedValues);
+ </script>
+</head>
+<body>
+
+<div class="box" id="rectangle-box"></div>
+<div class="box" id="circle-box"></div>
+<div class="box" id="ellipse-box"></div>
+
+<div id="result">
+</div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (134351 => 134352)
--- trunk/Source/WebCore/ChangeLog 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/Source/WebCore/ChangeLog 2012-11-13 04:51:53 UTC (rev 134352)
@@ -1,3 +1,41 @@
+2012-11-10 Dirk Schulze <k...@webkit.org>
+
+ BasicShapes 'circle', 'rectangle', 'ellipse' should be animatable with themselves
+ https://bugs.webkit.org/show_bug.cgi?id=101854
+
+ Reviewed by Andreas Kling.
+
+ The basic shapes BasicShapeCircle, BasicShapeEllipse and BasicShapeRectangle should
+ blend with themselves. This patch introduces simple interpolation of BasicShapes for
+ the -webkit-clip-path property.
+
+ Test: css3/masking/clip-path-animation.html
+
+ * page/animation/CSSPropertyAnimation.cpp:
+ (WebCore::blendFunc): Added a new function that blends between two BasicShape objects.
+ It skips blending on <clipPath> references, polygons and if the shapes are not of
+ the same type.
+ (WebCore):
+ (PropertyWrapperClipPath): Added new wrapper for ClipPathShapes.
+ (WebCore::PropertyWrapperClipPath::PropertyWrapperClipPath): Ditto.
+ (WebCore::CSSPropertyAnimation::ensurePropertyMap): Add -webkit-clip-path to animatable
+ properties.
+ * rendering/style/BasicShapes.cpp:
+ The blending is done by each shape itself. This is similar to FilterOperations or
+ TransformOperations.
+ (WebCore::BasicShapeRectangle::blend):
+ (WebCore):
+ (WebCore::BasicShapeCircle::blend):
+ (WebCore::BasicShapeEllipse::blend):
+ (WebCore::BasicShapePolygon::blend):
+ * rendering/style/BasicShapes.h:
+ Added new blending functions to header.
+ (BasicShape):
+ (BasicShapeRectangle):
+ (BasicShapeCircle):
+ (BasicShapeEllipse):
+ (BasicShapePolygon):
+
2012-11-12 Adam Barth <aba...@webkit.org>
[V8] We should be able to get V8PerContextData from a v8::Context more quickly
Modified: trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp (134351 => 134352)
--- trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp 2012-11-13 04:51:53 UTC (rev 134352)
@@ -35,6 +35,7 @@
#include "CSSImageValue.h"
#include "CSSPrimitiveValue.h"
#include "CSSPropertyNames.h"
+#include "ClipPathOperation.h"
#include "FloatConversion.h"
#include "IdentityTransformOperation.h"
#include "Matrix3DTransformOperation.h"
@@ -125,6 +126,26 @@
return to.blendByUsingMatrixInterpolation(from, progress, anim->renderer()->isBox() ? toRenderBox(anim->renderer())->borderBoxRect().size() : LayoutSize());
}
+static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase*, ClipPathOperation* from, ClipPathOperation* to, double progress)
+{
+ // Other clip-path operations than BasicShapes can not be animated.
+ if (from->getOperationType() != ClipPathOperation::SHAPE || to->getOperationType() != ClipPathOperation::SHAPE)
+ return to;
+
+ const BasicShape* fromShape = static_cast<ShapeClipPathOperation*>(from)->basicShape();
+ const BasicShape* toShape = static_cast<ShapeClipPathOperation*>(to)->basicShape();
+
+ // FIXME: Support animations between different shapes in the future.
+ if (fromShape->type() != toShape->type())
+ return to;
+
+ // FIXME: Support animations between polygons in the future.
+ if (fromShape->type() == BasicShape::BASIC_SHAPE_POLYGON)
+ return to;
+
+ return ShapeClipPathOperation::create(toShape->blend(fromShape, progress));
+}
+
#if ENABLE(CSS_FILTERS)
static inline PassRefPtr<FilterOperation> blendFunc(const AnimationBase* anim, FilterOperation* fromOp, FilterOperation* toOp, double progress, bool blendToPassthrough = false)
{
@@ -368,6 +389,14 @@
};
+class PropertyWrapperClipPath : public RefCountedPropertyWrapper<ClipPathOperation> {
+public:
+ PropertyWrapperClipPath(CSSPropertyID prop, ClipPathOperation* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ClipPathOperation>))
+ : RefCountedPropertyWrapper<ClipPathOperation>(prop, getter, setter)
+ {
+ }
+};
+
class StyleImagePropertyWrapper : public RefCountedPropertyWrapper<StyleImage> {
public:
StyleImagePropertyWrapper(CSSPropertyID prop, StyleImage* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<StyleImage>))
@@ -1114,6 +1143,8 @@
#endif
#endif
+ gPropertyWrappers->append(new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath));
+
gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitColumnRuleColor, MaybeInvalidColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor));
gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitTextStrokeColor, MaybeInvalidColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::visitedLinkTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor));
gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitTextFillColor, MaybeInvalidColor, &RenderStyle::textFillColor, &RenderStyle::setTextFillColor, &RenderStyle::visitedLinkTextFillColor, &RenderStyle::setVisitedLinkTextFillColor));
Modified: trunk/Source/WebCore/rendering/style/BasicShapes.cpp (134351 => 134352)
--- trunk/Source/WebCore/rendering/style/BasicShapes.cpp 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.cpp 2012-11-13 04:51:53 UTC (rev 134352)
@@ -32,6 +32,7 @@
#include "BasicShapes.h"
#include "FloatRect.h"
#include "LengthFunctions.h"
+#include "NotImplemented.h"
#include "Path.h"
namespace WebCore {
@@ -47,6 +48,23 @@
m_cornerRadiusY.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusY, boundingBox.height())));
}
+PassRefPtr<BasicShape> BasicShapeRectangle::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeRectangle* o = static_cast<const BasicShapeRectangle*>(other);
+ RefPtr<BasicShapeRectangle> result = BasicShapeRectangle::create();
+ result->setX(m_x.blend(o->x(), progress));
+ result->setY(m_y.blend(o->y(), progress));
+ result->setWidth(m_width.blend(o->width(), progress));
+ result->setHeight(m_height.blend(o->height(), progress));
+ if (!m_cornerRadiusX.isUndefined() && !o->cornerRadiusX().isUndefined())
+ result->setCornerRadiusX(m_cornerRadiusX.blend(o->cornerRadiusX(), progress));
+ if (!m_cornerRadiusY.isUndefined() && !o->cornerRadiusY().isUndefined())
+ result->setCornerRadiusY(m_cornerRadiusY.blend(o->cornerRadiusY(), progress));
+ return result.release();
+}
+
void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -60,6 +78,18 @@
radius * 2));
}
+PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other);
+ RefPtr<BasicShapeCircle> result = BasicShapeCircle::create();
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadius(m_radius.blend(o->radius(), progress));
+ return result.release();
+}
+
void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -73,6 +103,19 @@
radiusY * 2));
}
+PassRefPtr<BasicShape> BasicShapeEllipse::blend(const BasicShape* other, double progress) const
+{
+ ASSERT(type() == other->type());
+
+ const BasicShapeEllipse* o = static_cast<const BasicShapeEllipse*>(other);
+ RefPtr<BasicShapeEllipse> result = BasicShapeEllipse::create();
+ result->setCenterX(m_centerX.blend(o->centerX(), progress));
+ result->setCenterY(m_centerY.blend(o->centerY(), progress));
+ result->setRadiusX(m_radiusX.blend(o->radiusX(), progress));
+ result->setRadiusY(m_radiusY.blend(o->radiusY(), progress));
+ return result.release();
+}
+
void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
{
ASSERT(path.isEmpty());
@@ -90,4 +133,10 @@
}
path.closeSubpath();
}
+
+PassRefPtr<BasicShape> BasicShapePolygon::blend(const BasicShape*, double) const
+{
+ notImplemented();
+ return BasicShapePolygon::create();
}
+}
Modified: trunk/Source/WebCore/rendering/style/BasicShapes.h (134351 => 134352)
--- trunk/Source/WebCore/rendering/style/BasicShapes.h 2012-11-13 04:46:20 UTC (rev 134351)
+++ trunk/Source/WebCore/rendering/style/BasicShapes.h 2012-11-13 04:51:53 UTC (rev 134352)
@@ -54,6 +54,7 @@
virtual void path(Path&, const FloatRect&) = 0;
virtual WindRule windRule() const { return RULE_NONZERO; }
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0;
virtual Type type() const = 0;
protected:
@@ -78,7 +79,8 @@
void setCornerRadiusX(Length radiusX) { m_cornerRadiusX = radiusX; }
void setCornerRadiusY(Length radiusY) { m_cornerRadiusY = radiusY; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_RECTANGLE; }
private:
@@ -107,7 +109,8 @@
void setCenterY(Length centerY) { m_centerY = centerY; }
void setRadius(Length radius) { m_radius = radius; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_CIRCLE; }
private:
@@ -132,7 +135,8 @@
void setRadiusX(Length radiusX) { m_radiusX = radiusX; }
void setRadiusY(Length radiusY) { m_radiusY = radiusY; }
- virtual void path(Path&, const FloatRect&);
+ virtual void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
virtual Type type() const { return BASIC_SHAPE_ELLIPSE; }
private:
@@ -155,7 +159,9 @@
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 void path(Path&, const FloatRect&) OVERRIDE;
+ virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
virtual WindRule windRule() const { return m_windRule; }
virtual Type type() const { return BASIC_SHAPE_POLYGON; }