OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/animation/SVGPathInterpolationType.h" |
| 7 |
| 8 #include "core/animation/InterpolatedSVGPathSource.h" |
| 9 #include "core/animation/InterpolationEnvironment.h" |
| 10 #include "core/animation/SVGPathSegInterpolationFunctions.h" |
| 11 #include "core/svg/SVGPath.h" |
| 12 #include "core/svg/SVGPathByteStreamBuilder.h" |
| 13 #include "core/svg/SVGPathByteStreamSource.h" |
| 14 #include "core/svg/SVGPathParser.h" |
| 15 |
| 16 namespace blink { |
| 17 |
| 18 class SVGPathNonInterpolableValue : public NonInterpolableValue { |
| 19 public: |
| 20 virtual ~SVGPathNonInterpolableValue() {} |
| 21 |
| 22 static PassRefPtr<SVGPathNonInterpolableValue> create(Vector<SVGPathSegType>
& pathSegTypes) |
| 23 { |
| 24 return adoptRef(new SVGPathNonInterpolableValue(pathSegTypes)); |
| 25 } |
| 26 |
| 27 const Vector<SVGPathSegType>& pathSegTypes() const { return m_pathSegTypes;
} |
| 28 |
| 29 DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); |
| 30 |
| 31 private: |
| 32 SVGPathNonInterpolableValue(Vector<SVGPathSegType>& pathSegTypes) |
| 33 { |
| 34 m_pathSegTypes.swap(pathSegTypes); |
| 35 } |
| 36 |
| 37 Vector<SVGPathSegType> m_pathSegTypes; |
| 38 }; |
| 39 |
| 40 DEFINE_NON_INTERPOLABLE_VALUE_TYPE(SVGPathNonInterpolableValue); |
| 41 DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(SVGPathNonInterpolableValue); |
| 42 |
| 43 enum PathComponentIndex { |
| 44 PathArgsIndex, |
| 45 PathNeutralIndex, |
| 46 PathComponentIndexCount, |
| 47 }; |
| 48 |
| 49 PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertSVGValue(co
nst SVGPropertyBase& svgValue) const |
| 50 { |
| 51 if (svgValue.type() != AnimatedPath) |
| 52 return nullptr; |
| 53 |
| 54 SVGPathByteStreamSource pathSource(toSVGPath(svgValue).byteStream()); |
| 55 size_t length = 0; |
| 56 PathCoordinates currentCoordinates; |
| 57 Vector<OwnPtr<InterpolableValue>> interpolablePathSegs; |
| 58 Vector<SVGPathSegType> pathSegTypes; |
| 59 |
| 60 while (pathSource.hasMoreData()) { |
| 61 const PathSegmentData segment = pathSource.parseSegment(); |
| 62 interpolablePathSegs.append(SVGPathSegInterpolationFunctions::consumePat
hSeg(segment, currentCoordinates)); |
| 63 pathSegTypes.append(segment.command); |
| 64 length++; |
| 65 } |
| 66 |
| 67 OwnPtr<InterpolableList> pathArgs = InterpolableList::create(length); |
| 68 for (size_t i = 0; i < interpolablePathSegs.size(); i++) |
| 69 pathArgs->set(i, interpolablePathSegs[i].release()); |
| 70 |
| 71 OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentInde
xCount); |
| 72 result->set(PathArgsIndex, pathArgs.release()); |
| 73 result->set(PathNeutralIndex, InterpolableNumber::create(0)); |
| 74 |
| 75 return InterpolationValue::create(*this, result.release(), SVGPathNonInterpo
lableValue::create(pathSegTypes)); |
| 76 } |
| 77 |
| 78 class UnderlyingPathSegTypesChecker : public InterpolationType::ConversionChecke
r { |
| 79 public: |
| 80 ~UnderlyingPathSegTypesChecker() final {} |
| 81 |
| 82 static PassOwnPtr<UnderlyingPathSegTypesChecker> create(const InterpolationT
ype& type, const UnderlyingValue& underlyingValue) |
| 83 { |
| 84 return adoptPtr(new UnderlyingPathSegTypesChecker(type, getPathSegTypes(
underlyingValue))); |
| 85 } |
| 86 |
| 87 private: |
| 88 UnderlyingPathSegTypesChecker(const InterpolationType& type, const Vector<SV
GPathSegType>& pathSegTypes) |
| 89 : ConversionChecker(type) |
| 90 , m_pathSegTypes(pathSegTypes) |
| 91 { } |
| 92 |
| 93 static const Vector<SVGPathSegType>& getPathSegTypes(const UnderlyingValue&
underlyingValue) |
| 94 { |
| 95 return toSVGPathNonInterpolableValue(underlyingValue->nonInterpolableVal
ue())->pathSegTypes(); |
| 96 } |
| 97 |
| 98 bool isValid(const InterpolationEnvironment&, const UnderlyingValue& underly
ingValue) const final |
| 99 { |
| 100 return m_pathSegTypes == getPathSegTypes(underlyingValue); |
| 101 } |
| 102 |
| 103 Vector<SVGPathSegType> m_pathSegTypes; |
| 104 }; |
| 105 |
| 106 PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertNeutral(con
st UnderlyingValue& underlyingValue, ConversionCheckers& conversionCheckers) con
st |
| 107 { |
| 108 conversionCheckers.append(UnderlyingPathSegTypesChecker::create(*this, under
lyingValue)); |
| 109 OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentInde
xCount); |
| 110 result->set(PathArgsIndex, toInterpolableList(underlyingValue->interpolableV
alue()).get(PathArgsIndex)->cloneAndZero()); |
| 111 result->set(PathNeutralIndex, InterpolableNumber::create(1)); |
| 112 return InterpolationValue::create(*this, result.release(), |
| 113 const_cast<NonInterpolableValue*>(underlyingValue->nonInterpolableValue(
))); // Take ref. |
| 114 } |
| 115 |
| 116 static bool pathSegTypesMatch(const Vector<SVGPathSegType>& a, const Vector<SVGP
athSegType>& b) |
| 117 { |
| 118 if (a.size() != b.size()) |
| 119 return false; |
| 120 |
| 121 for (size_t i = 0; i < a.size(); i++) { |
| 122 if (toAbsolutePathSegType(a[i]) != toAbsolutePathSegType(b[i])) |
| 123 return false; |
| 124 } |
| 125 |
| 126 return true; |
| 127 } |
| 128 |
| 129 PassOwnPtr<PairwisePrimitiveInterpolation> SVGPathInterpolationType::mergeSingle
Conversions(InterpolationValue& startValue, InterpolationValue& endValue) const |
| 130 { |
| 131 const Vector<SVGPathSegType>& startTypes = toSVGPathNonInterpolableValue(sta
rtValue.nonInterpolableValue())->pathSegTypes(); |
| 132 const Vector<SVGPathSegType>& endTypes = toSVGPathNonInterpolableValue(endVa
lue.nonInterpolableValue())->pathSegTypes(); |
| 133 if (!pathSegTypesMatch(startTypes, endTypes)) |
| 134 return nullptr; |
| 135 |
| 136 return PairwisePrimitiveInterpolation::create(*this, |
| 137 startValue.mutableComponent().interpolableValue.release(), |
| 138 endValue.mutableComponent().interpolableValue.release(), |
| 139 const_cast<NonInterpolableValue*>(endValue.nonInterpolableValue())); //
Take ref. |
| 140 } |
| 141 |
| 142 void SVGPathInterpolationType::composite(UnderlyingValue& underlyingValue, doubl
e underlyingFraction, const InterpolationValue& value) const |
| 143 { |
| 144 const InterpolableList& list = toInterpolableList(value.interpolableValue())
; |
| 145 double neutralComponent = toInterpolableNumber(list.get(PathNeutralIndex))->
value(); |
| 146 |
| 147 if (neutralComponent == 0) { |
| 148 underlyingValue.set(&value); |
| 149 return; |
| 150 } |
| 151 |
| 152 ASSERT(pathSegTypesMatch( |
| 153 toSVGPathNonInterpolableValue(underlyingValue->nonInterpolableValue())->
pathSegTypes(), |
| 154 toSVGPathNonInterpolableValue(value.nonInterpolableValue())->pathSegType
s())); |
| 155 underlyingValue.mutableComponent().interpolableValue->scaleAndAdd(neutralCom
ponent, value.interpolableValue()); |
| 156 underlyingValue.mutableComponent().nonInterpolableValue = const_cast<NonInte
rpolableValue*>(value.nonInterpolableValue()); // Take ref. |
| 157 } |
| 158 |
| 159 PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGPathInterpolationType::appliedSVGValu
e(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInt
erpolableValue) const |
| 160 { |
| 161 OwnPtr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create(); |
| 162 InterpolatedSVGPathSource source( |
| 163 toInterpolableList(*toInterpolableList(interpolableValue).get(PathArgsIn
dex)), |
| 164 toSVGPathNonInterpolableValue(nonInterpolableValue)->pathSegTypes()); |
| 165 SVGPathByteStreamBuilder builder(*pathByteStream); |
| 166 SVGPathParser(&source, &builder).parsePathDataFromSource(UnalteredParsing, f
alse); |
| 167 return SVGPath::create(CSSPathValue::create(pathByteStream.release())); |
| 168 } |
| 169 |
| 170 } // namespace blink |
OLD | NEW |