Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp

Issue 1441853002: Web Animations: Add SVGPathInterpolationType (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@_svgNumberListInterpolationType
Patch Set: Rebased Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp
diff --git a/third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6dfafe2197dc2d43143f150f238de73aa3ca3e2b
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/SVGPathInterpolationType.cpp
@@ -0,0 +1,170 @@
+// 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/SVGPathInterpolationType.h"
+
+#include "core/animation/InterpolatedSVGPathSource.h"
+#include "core/animation/InterpolationEnvironment.h"
+#include "core/animation/SVGPathSegInterpolationFunctions.h"
+#include "core/svg/SVGPath.h"
+#include "core/svg/SVGPathByteStreamBuilder.h"
+#include "core/svg/SVGPathByteStreamSource.h"
+#include "core/svg/SVGPathParser.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);
+
+enum PathComponentIndex {
+ PathArgsIndex,
+ PathNeutralIndex,
+ PathComponentIndexCount,
+};
+
+PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const
+{
+ if (svgValue.type() != AnimatedPath)
+ return nullptr;
+
+ SVGPathByteStreamSource pathSource(toSVGPath(svgValue).byteStream());
+ size_t length = 0;
+ PathCoordinates currentCoordinates;
+ Vector<OwnPtr<InterpolableValue>> interpolablePathSegs;
+ Vector<SVGPathSegType> pathSegTypes;
+
+ while (pathSource.hasMoreData()) {
+ const PathSegmentData segment = pathSource.parseSegment();
+ interpolablePathSegs.append(SVGPathSegInterpolationFunctions::consumePathSeg(segment, currentCoordinates));
+ pathSegTypes.append(segment.command);
+ length++;
+ }
+
+ OwnPtr<InterpolableList> pathArgs = InterpolableList::create(length);
+ for (size_t i = 0; i < interpolablePathSegs.size(); i++)
+ pathArgs->set(i, interpolablePathSegs[i].release());
+
+ OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentIndexCount);
+ result->set(PathArgsIndex, pathArgs.release());
+ result->set(PathNeutralIndex, InterpolableNumber::create(0));
+
+ return InterpolationValue::create(*this, result.release(), SVGPathNonInterpolableValue::create(pathSegTypes));
+}
+
+class UnderlyingPathSegTypesChecker : public InterpolationType::ConversionChecker {
+public:
+ ~UnderlyingPathSegTypesChecker() final {}
+
+ static PassOwnPtr<UnderlyingPathSegTypesChecker> create(const InterpolationType& type, const UnderlyingValue& underlyingValue)
+ {
+ return adoptPtr(new UnderlyingPathSegTypesChecker(type, getPathSegTypes(underlyingValue)));
+ }
+
+private:
+ UnderlyingPathSegTypesChecker(const InterpolationType& type, const Vector<SVGPathSegType>& pathSegTypes)
+ : ConversionChecker(type)
+ , m_pathSegTypes(pathSegTypes)
+ { }
+
+ static const Vector<SVGPathSegType>& getPathSegTypes(const UnderlyingValue& underlyingValue)
+ {
+ return toSVGPathNonInterpolableValue(underlyingValue->nonInterpolableValue())->pathSegTypes();
+ }
+
+ bool isValid(const InterpolationEnvironment&, const UnderlyingValue& underlyingValue) const final
+ {
+ return m_pathSegTypes == getPathSegTypes(underlyingValue);
+ }
+
+ Vector<SVGPathSegType> m_pathSegTypes;
+};
+
+PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertNeutral(const UnderlyingValue& underlyingValue, ConversionCheckers& conversionCheckers) const
+{
+ conversionCheckers.append(UnderlyingPathSegTypesChecker::create(*this, underlyingValue));
+ OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentIndexCount);
+ result->set(PathArgsIndex, toInterpolableList(underlyingValue->interpolableValue()).get(PathArgsIndex)->cloneAndZero());
+ result->set(PathNeutralIndex, InterpolableNumber::create(1));
+ return InterpolationValue::create(*this, result.release(),
+ const_cast<NonInterpolableValue*>(underlyingValue->nonInterpolableValue())); // Take ref.
+}
+
+static bool pathSegTypesMatch(const Vector<SVGPathSegType>& a, const Vector<SVGPathSegType>& b)
+{
+ if (a.size() != b.size())
+ return false;
+
+ for (size_t i = 0; i < a.size(); i++) {
+ if (toAbsolutePathSegType(a[i]) != toAbsolutePathSegType(b[i]))
+ return false;
+ }
+
+ return true;
+}
+
+PassOwnPtr<PairwisePrimitiveInterpolation> SVGPathInterpolationType::mergeSingleConversions(InterpolationValue& startValue, InterpolationValue& endValue) const
+{
+ const Vector<SVGPathSegType>& startTypes = toSVGPathNonInterpolableValue(startValue.nonInterpolableValue())->pathSegTypes();
+ const Vector<SVGPathSegType>& endTypes = toSVGPathNonInterpolableValue(endValue.nonInterpolableValue())->pathSegTypes();
+ if (!pathSegTypesMatch(startTypes, endTypes))
+ return nullptr;
+
+ return PairwisePrimitiveInterpolation::create(*this,
+ startValue.mutableComponent().interpolableValue.release(),
+ endValue.mutableComponent().interpolableValue.release(),
+ const_cast<NonInterpolableValue*>(endValue.nonInterpolableValue())); // Take ref.
+}
+
+void SVGPathInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
+{
+ const InterpolableList& list = toInterpolableList(value.interpolableValue());
+ double neutralComponent = toInterpolableNumber(list.get(PathNeutralIndex))->value();
+
+ if (neutralComponent == 0) {
+ underlyingValue.set(&value);
+ return;
+ }
+
+ ASSERT(pathSegTypesMatch(
+ toSVGPathNonInterpolableValue(underlyingValue->nonInterpolableValue())->pathSegTypes(),
+ toSVGPathNonInterpolableValue(value.nonInterpolableValue())->pathSegTypes()));
+ underlyingValue.mutableComponent().interpolableValue->scaleAndAdd(neutralComponent, value.interpolableValue());
+ underlyingValue.mutableComponent().nonInterpolableValue = const_cast<NonInterpolableValue*>(value.nonInterpolableValue()); // Take ref.
+}
+
+PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGPathInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) const
+{
+ OwnPtr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create();
+ InterpolatedSVGPathSource source(
+ toInterpolableList(*toInterpolableList(interpolableValue).get(PathArgsIndex)),
+ toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes());
+ SVGPathByteStreamBuilder builder(*pathByteStream);
+ SVGPathParser(&source, &builder).parsePathDataFromSource(UnalteredParsing, false);
+ return SVGPath::create(CSSPathValue::create(pathByteStream.release()));
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698