Index: third_party/WebKit/Source/core/animation/SVGPathSegInterpolationFunctions.cpp |
diff --git a/third_party/WebKit/Source/core/animation/SVGPathSegInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/SVGPathSegInterpolationFunctions.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..604411e0e4c824600ccb6330253f85ced4989991 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/animation/SVGPathSegInterpolationFunctions.cpp |
@@ -0,0 +1,315 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "core/animation/SVGPathSegInterpolationFunctions.h" |
+ |
+namespace blink { |
+ |
+ |
+PassOwnPtr<InterpolableNumber> consumeControlAxis(double value, bool isAbsolute, double currentValue) |
+{ |
+ return InterpolableNumber::create(isAbsolute ? value : currentValue + value); |
+} |
+ |
+double consumeInterpolableControlAxis(const InterpolableValue* number, bool isAbsolute, double currentValue) |
+{ |
+ double value = toInterpolableNumber(number)->value(); |
+ return isAbsolute ? value : value - currentValue; |
+} |
+ |
+PassOwnPtr<InterpolableNumber> consumeCoordinateAxis(double value, bool isAbsolute, double& currentValue) |
+{ |
+ if (isAbsolute) |
+ currentValue = value; |
+ else |
+ currentValue += value; |
+ return InterpolableNumber::create(currentValue); |
+} |
+ |
+double consumeInterpolableCoordinateAxis(const InterpolableValue* number, bool isAbsolute, double& currentValue) |
+{ |
+ double previousValue = currentValue; |
+ currentValue = toInterpolableNumber(number)->value(); |
+ return isAbsolute ? currentValue : currentValue - previousValue; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeClosePath(const PathSegmentData&, PathCoordinates& coordinates) |
+{ |
+ coordinates.currentX = coordinates.initialX; |
+ coordinates.currentY = coordinates.initialY; |
+ return InterpolableList::create(0); |
+} |
+ |
+PathSegmentData consumeInterpolableClosePath(const InterpolableValue&, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ coordinates.currentX = coordinates.initialX; |
+ coordinates.currentY = coordinates.initialY; |
+ |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeSingleCoordinate(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ OwnPtr<InterpolableList> result = InterpolableList::create(2); |
+ result->set(0, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX)); |
+ result->set(1, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY)); |
+ |
+ if (toAbsolutePathSegType(segment.command) == PathSegMoveToAbs) { |
+ // Any upcoming 'closepath' commands bring us back to the location we have just moved to. |
+ coordinates.initialX = coordinates.currentX; |
+ coordinates.initialY = coordinates.currentY; |
+ } |
+ |
+ return result.release(); |
+} |
+ |
+PathSegmentData consumeInterpolableSingleCoordinate(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ const InterpolableList& list = toInterpolableList(value); |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(list.get(0), isAbsolute, coordinates.currentX)); |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(list.get(1), isAbsolute, coordinates.currentY)); |
+ |
+ if (toAbsolutePathSegType(segType) == PathSegMoveToAbs) { |
+ // Any upcoming 'closepath' commands bring us back to the location we have just moved to. |
+ coordinates.initialX = coordinates.currentX; |
+ coordinates.initialY = coordinates.currentY; |
+ } |
+ |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeCurvetoCubic(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ OwnPtr<InterpolableList> result = InterpolableList::create(6); |
+ result->set(0, consumeControlAxis(segment.x1(), isAbsolute, coordinates.currentX)); |
+ result->set(1, consumeControlAxis(segment.y1(), isAbsolute, coordinates.currentY)); |
+ result->set(2, consumeControlAxis(segment.x2(), isAbsolute, coordinates.currentX)); |
+ result->set(3, consumeControlAxis(segment.y2(), isAbsolute, coordinates.currentY)); |
+ result->set(4, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX)); |
+ result->set(5, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY)); |
+ return result.release(); |
+} |
+ |
+PathSegmentData consumeInterpolableCurvetoCubic(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ const InterpolableList& list = toInterpolableList(value); |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.point1.setX(consumeInterpolableControlAxis(list.get(0), isAbsolute, coordinates.currentX)); |
+ segment.point1.setY(consumeInterpolableControlAxis(list.get(1), isAbsolute, coordinates.currentY)); |
+ segment.point2.setX(consumeInterpolableControlAxis(list.get(2), isAbsolute, coordinates.currentX)); |
+ segment.point2.setY(consumeInterpolableControlAxis(list.get(3), isAbsolute, coordinates.currentY)); |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(list.get(4), isAbsolute, coordinates.currentX)); |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(list.get(5), isAbsolute, coordinates.currentY)); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeCurvetoQuadratic(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ OwnPtr<InterpolableList> result = InterpolableList::create(4); |
+ result->set(0, consumeControlAxis(segment.x1(), isAbsolute, coordinates.currentX)); |
+ result->set(1, consumeControlAxis(segment.y1(), isAbsolute, coordinates.currentY)); |
+ result->set(2, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX)); |
+ result->set(3, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY)); |
+ return result.release(); |
+} |
+ |
+PathSegmentData consumeInterpolableCurvetoQuadratic(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ const InterpolableList& list = toInterpolableList(value); |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.point1.setX(consumeInterpolableControlAxis(list.get(0), isAbsolute, coordinates.currentX)); |
+ segment.point1.setY(consumeInterpolableControlAxis(list.get(1), isAbsolute, coordinates.currentY)); |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(list.get(2), isAbsolute, coordinates.currentX)); |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(list.get(3), isAbsolute, coordinates.currentY)); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeArc(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ OwnPtr<InterpolableList> result = InterpolableList::create(7); |
+ result->set(0, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX)); |
+ result->set(1, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY)); |
+ result->set(2, InterpolableNumber::create(segment.r1())); |
+ result->set(3, InterpolableNumber::create(segment.r2())); |
+ result->set(4, InterpolableNumber::create(segment.arcAngle())); |
+ result->set(5, InterpolableBool::create(segment.largeArcFlag())); |
+ result->set(6, InterpolableBool::create(segment.sweepFlag())); |
+ return result.release(); |
+} |
+ |
+PathSegmentData consumeInterpolableArc(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ const InterpolableList& list = toInterpolableList(value); |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(list.get(0), isAbsolute, coordinates.currentX)); |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(list.get(1), isAbsolute, coordinates.currentY)); |
+ segment.arcRadii().setX(toInterpolableNumber(list.get(2))->value()); |
+ segment.arcRadii().setY(toInterpolableNumber(list.get(3))->value()); |
+ segment.setArcAngle(toInterpolableNumber(list.get(4))->value()); |
+ segment.arcLarge = toInterpolableBool(list.get(5))->value(); |
+ segment.arcSweep = toInterpolableBool(list.get(6))->value(); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeLinetoHorizontal(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ return consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX); |
+} |
+ |
+PathSegmentData consumeInterpolableLinetoHorizontal(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(&value, isAbsolute, coordinates.currentX)); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeLinetoVertical(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ return consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY); |
+} |
+ |
+PathSegmentData consumeInterpolableLinetoVertical(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(&value, isAbsolute, coordinates.currentY)); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> consumeCurvetoCubicSmooth(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ bool isAbsolute = isAbsolutePathSegType(segment.command); |
+ OwnPtr<InterpolableList> result = InterpolableList::create(4); |
+ result->set(0, consumeControlAxis(segment.x2(), isAbsolute, coordinates.currentX)); |
+ result->set(1, consumeControlAxis(segment.y2(), isAbsolute, coordinates.currentY)); |
+ result->set(2, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX)); |
+ result->set(3, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY)); |
+ return result.release(); |
+} |
+ |
+PathSegmentData consumeInterpolableCurvetoCubicSmooth(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ const InterpolableList& list = toInterpolableList(value); |
+ bool isAbsolute = isAbsolutePathSegType(segType); |
+ PathSegmentData segment; |
+ segment.command = segType; |
+ segment.point2.setX(consumeInterpolableControlAxis(list.get(0), isAbsolute, coordinates.currentX)); |
+ segment.point2.setY(consumeInterpolableControlAxis(list.get(1), isAbsolute, coordinates.currentY)); |
+ segment.targetPoint.setX(consumeInterpolableCoordinateAxis(list.get(2), isAbsolute, coordinates.currentX)); |
+ segment.targetPoint.setY(consumeInterpolableCoordinateAxis(list.get(3), isAbsolute, coordinates.currentY)); |
+ return segment; |
+} |
+ |
+PassOwnPtr<InterpolableValue> SVGPathSegInterpolationFunctions::consumePathSeg(const PathSegmentData& segment, PathCoordinates& coordinates) |
+{ |
+ switch (segment.command) { |
+ case PathSegClosePath: |
+ return consumeClosePath(segment, coordinates); |
+ |
+ case PathSegMoveToAbs: |
+ case PathSegMoveToRel: |
+ case PathSegLineToAbs: |
+ case PathSegLineToRel: |
+ case PathSegCurveToQuadraticSmoothAbs: |
+ case PathSegCurveToQuadraticSmoothRel: |
+ return consumeSingleCoordinate(segment, coordinates); |
+ |
+ case PathSegCurveToCubicAbs: |
+ case PathSegCurveToCubicRel: |
+ return consumeCurvetoCubic(segment, coordinates); |
+ |
+ case PathSegCurveToQuadraticAbs: |
+ case PathSegCurveToQuadraticRel: |
+ return consumeCurvetoQuadratic(segment, coordinates); |
+ |
+ case PathSegArcAbs: |
+ case PathSegArcRel: |
+ return consumeArc(segment, coordinates); |
+ |
+ case PathSegLineToHorizontalAbs: |
+ case PathSegLineToHorizontalRel: |
+ return consumeLinetoHorizontal(segment, coordinates); |
+ |
+ case PathSegLineToVerticalAbs: |
+ case PathSegLineToVerticalRel: |
+ return consumeLinetoVertical(segment, coordinates); |
+ |
+ case PathSegCurveToCubicSmoothAbs: |
+ case PathSegCurveToCubicSmoothRel: |
+ return consumeCurvetoCubicSmooth(segment, coordinates); |
+ |
+ case PathSegUnknown: |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ return nullptr; |
+ } |
+} |
+ |
+PathSegmentData SVGPathSegInterpolationFunctions::consumeInterpolablePathSeg(const InterpolableValue& value, SVGPathSegType segType, PathCoordinates& coordinates) |
+{ |
+ switch (segType) { |
+ case PathSegClosePath: |
+ return consumeInterpolableClosePath(value, segType, coordinates); |
+ |
+ case PathSegMoveToAbs: |
+ case PathSegMoveToRel: |
+ case PathSegLineToAbs: |
+ case PathSegLineToRel: |
+ case PathSegCurveToQuadraticSmoothAbs: |
+ case PathSegCurveToQuadraticSmoothRel: |
+ return consumeInterpolableSingleCoordinate(value, segType, coordinates); |
+ |
+ case PathSegCurveToCubicAbs: |
+ case PathSegCurveToCubicRel: |
+ return consumeInterpolableCurvetoCubic(value, segType, coordinates); |
+ |
+ case PathSegCurveToQuadraticAbs: |
+ case PathSegCurveToQuadraticRel: |
+ return consumeInterpolableCurvetoQuadratic(value, segType, coordinates); |
+ |
+ case PathSegArcAbs: |
+ case PathSegArcRel: |
+ return consumeInterpolableArc(value, segType, coordinates); |
+ |
+ case PathSegLineToHorizontalAbs: |
+ case PathSegLineToHorizontalRel: |
+ return consumeInterpolableLinetoHorizontal(value, segType, coordinates); |
+ |
+ case PathSegLineToVerticalAbs: |
+ case PathSegLineToVerticalRel: |
+ return consumeInterpolableLinetoVertical(value, segType, coordinates); |
+ |
+ case PathSegCurveToCubicSmoothAbs: |
+ case PathSegCurveToCubicSmoothRel: |
+ return consumeInterpolableCurvetoCubicSmooth(value, segType, coordinates); |
+ |
+ case PathSegUnknown: |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ return PathSegmentData(); |
+ } |
+} |
+ |
+} // namespace blink |