Index: third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp |
diff --git a/third_party/WebKit/Source/core/animation/PathSVGInterpolation.cpp b/third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp |
similarity index 78% |
rename from third_party/WebKit/Source/core/animation/PathSVGInterpolation.cpp |
rename to third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp |
index faec714bc5ed886d48b6e0f8590fa8ed31e808e8..7e256b2613591def8380e991d9f263c6dd91f8a2 100644 |
--- a/third_party/WebKit/Source/core/animation/PathSVGInterpolation.cpp |
+++ b/third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp |
@@ -3,15 +3,44 @@ |
// found in the LICENSE file. |
#include "config.h" |
-#include "core/animation/PathSVGInterpolation.h" |
+#include "core/animation/SVGPathInterpolationType.h" |
+#include "core/animation/InterpolationEnvironment.h" |
+#include "core/animation/StringKeyframe.h" |
+#include "core/svg/SVGPath.h" |
#include "core/svg/SVGPathByteStreamBuilder.h" |
#include "core/svg/SVGPathByteStreamSource.h" |
#include "core/svg/SVGPathElement.h" |
#include "core/svg/SVGPathParser.h" |
+#include "core/svg/properties/SVGAnimatedProperty.h" |
namespace blink { |
+class SVGPathNonInterpolableValue : public NonInterpolableValue { |
+public: |
+ virtual ~SVGPathNonInterpolableValue() {} |
+ |
+ static PassRefPtr<SVGPathNonInterpolableValue> create(Vector<SVGPathSegType>& pathSegTypes) |
+ { |
+ return adoptRef(new SVGPathNonInterpolableValue(pathSegTypes)); |
+ } |
+ |
+ const Vector<SVGPathSegType>& pathSegTypes() const { return m_pathSegTypes; } |
+ |
+ DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
+ |
+private: |
+ SVGPathNonInterpolableValue(Vector<SVGPathSegType>& pathSegTypes) |
+ { |
+ m_pathSegTypes.swap(pathSegTypes); |
+ } |
+ |
+ Vector<SVGPathSegType> m_pathSegTypes; |
+}; |
+ |
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE(SVGPathNonInterpolableValue); |
+DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(SVGPathNonInterpolableValue); |
+ |
namespace { |
struct SubPathCoordinates { |
@@ -245,11 +274,8 @@ PathSegmentData pathSegCurvetoCubicSmoothFromInterpolableValue(const Interpolabl |
return segment; |
} |
-PassOwnPtr<InterpolableValue> pathSegToInterpolableValue(const PathSegmentData& segment, SubPathCoordinates& coordinates, SVGPathSegType* ptrSegType) |
+PassOwnPtr<InterpolableValue> pathSegToInterpolableValue(const PathSegmentData& segment, SubPathCoordinates& coordinates) |
{ |
- if (ptrSegType) |
- *ptrSegType = segment.command; |
- |
switch (segment.command) { |
case PathSegClosePath: |
return pathSegClosePathToInterpolableValue(segment, coordinates); |
@@ -388,62 +414,96 @@ size_t countPathCommands(const SVGPathByteStream& path) |
return count; |
} |
+bool canComposite(const InterpolationValue& first, const InterpolationValue& second) |
+{ |
+ const Vector<SVGPathSegType>& firstSegTypes = toSVGPathNonInterpolableValue(first.nonInterpolableValue())->pathSegTypes(); |
+ const Vector<SVGPathSegType>& secondSegTypes = toSVGPathNonInterpolableValue(second.nonInterpolableValue())->pathSegTypes(); |
+ |
+ if (firstSegTypes.size() != secondSegTypes.size()) { |
+ return false; |
+ } |
+ |
+ for (size_t i = 0; i < firstSegTypes.size(); ++i) { |
+ if (toAbsolutePathSegType(firstSegTypes[i]) != toAbsolutePathSegType(secondSegTypes[i])) |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
-PassRefPtr<PathSVGInterpolation> PathSVGInterpolation::maybeCreate(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute) |
+void SVGPathInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const |
{ |
- ASSERT(start->type() == SVGPath::classType()); |
- ASSERT(end->type() == SVGPath::classType()); |
+ if (!canComposite(*underlyingValue.get(), value)) { |
+ underlyingValue.set(&value); |
+ return; |
+ } |
- const SVGPathByteStream& startPath = static_cast<SVGPath*>(start)->byteStream(); |
- const SVGPathByteStream& endPath = static_cast<SVGPath*>(end)->byteStream(); |
+ underlyingValue.mutableComponent().interpolableValue->scaleAndAdd(underlyingFraction, value.interpolableValue()); |
+} |
- if (startPath.size() != endPath.size()) |
+PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertNeutral(const UnderlyingValue& underlyingValue) const |
+{ |
+ const InterpolationValue* underlying = underlyingValue.get(); |
+ if (!underlying) |
return nullptr; |
+ RefPtr<NonInterpolableValue> nonInterpolableValue = const_cast<NonInterpolableValue*>(underlying->nonInterpolableValue()); |
+ return InterpolationValue::create(*this, underlying->interpolableValue().cloneAndZero(), nonInterpolableValue.release()); |
+} |
- size_t length = countPathCommands(startPath); |
- |
- SVGPathByteStreamSource startPathSource(startPath); |
- SVGPathByteStreamSource endPathSource(endPath); |
+PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const |
+{ |
+ if (svgValue.type() != AnimatedPath) |
+ return nullptr; |
- Vector<SVGPathSegType> pathSegTypes(length); |
- OwnPtr<InterpolableList> startValue = InterpolableList::create(length); |
- OwnPtr<InterpolableList> endValue = InterpolableList::create(length); |
- SubPathCoordinates startCoordinates; |
- SubPathCoordinates endCoordinates; |
- size_t i = 0; |
- while (startPathSource.hasMoreData()) { |
- if (toAbsolutePathSegType(startPathSource.peekSegmentType()) != toAbsolutePathSegType(endPathSource.peekSegmentType())) |
- return nullptr; |
+ const SVGPathByteStream& path = toSVGPath(svgValue).byteStream(); |
- // Like Firefox SMIL, we use the final path seg type. |
- const PathSegmentData startSeg = startPathSource.parseSegment(); |
- startValue->set(i, pathSegToInterpolableValue(startSeg, startCoordinates, nullptr)); |
+ size_t length = countPathCommands(path); |
- const PathSegmentData endSeg = endPathSource.parseSegment(); |
- endValue->set(i, pathSegToInterpolableValue(endSeg, endCoordinates, &pathSegTypes.at(i))); |
+ SVGPathByteStreamSource pathSource(path); |
+ Vector<SVGPathSegType> pathSegTypes(length); |
+ OwnPtr<InterpolableList> value = InterpolableList::create(length); |
+ SubPathCoordinates coordinates; |
+ size_t i = 0; |
+ while (pathSource.hasMoreData()) { |
+ const PathSegmentData segment = pathSource.parseSegment(); |
+ value->set(i, pathSegToInterpolableValue(segment, coordinates)); |
+ pathSegTypes[i] = segment.command; |
++i; |
} |
- ASSERT(!endPathSource.hasMoreData()); |
+ ASSERT(!pathSource.hasMoreData()); |
ASSERT(i == length); |
- return adoptRef(new PathSVGInterpolation(startValue.release(), endValue.release(), attribute, pathSegTypes)); |
+ return InterpolationValue::create(*this, value.release(), SVGPathNonInterpolableValue::create(pathSegTypes)); |
+} |
+ |
+PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const |
+{ |
+ return maybeConvertSVGValue(environment.svgBaseValue()); |
} |
-PassRefPtrWillBeRawPtr<SVGPropertyBase> PathSVGInterpolation::fromInterpolableValue(const InterpolableValue& value, const Vector<SVGPathSegType>& pathSegTypes) |
+RefPtrWillBeRawPtr<SVGPropertyBase> SVGPathInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) const |
{ |
RefPtrWillBeRawPtr<SVGPath> result = SVGPath::create(); |
- InterpolatedPathSource source(toInterpolableList(value), pathSegTypes); |
+ InterpolatedPathSource source(toInterpolableList(interpolableValue), toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes()); |
SVGPathByteStreamBuilder builder(result->mutableByteStream()); |
+ // TODO(ericwilligers): We shouldn't be parsing at application time. |
fs
2015/11/03 10:03:12
Drive-by note: This is not really a "parsing" oper
|
SVGPathParser parser(&source, &builder); |
parser.parsePathDataFromSource(UnalteredParsing, false); |
return result.release(); |
} |
-PassRefPtrWillBeRawPtr<SVGPropertyBase> PathSVGInterpolation::interpolatedValue(SVGElement&) const |
+PassOwnPtr<PairwisePrimitiveInterpolation> SVGPathInterpolationType::mergeSingleConversions(InterpolationValue& startValue, InterpolationValue& endValue) const |
{ |
- return fromInterpolableValue(*m_cachedValue, m_pathSegTypes); |
-} |
+ if (!canComposite(startValue, endValue)) |
+ return nullptr; |
+ return PairwisePrimitiveInterpolation::create(*this, |
+ startValue.mutableComponent().interpolableValue.release(), |
+ endValue.mutableComponent().interpolableValue.release(), |
+ endValue.mutableComponent().nonInterpolableValue.release()); |
} |
+ |
+} // namespace blink |