| 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
|
|
|