Chromium Code Reviews| 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 |