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

Side by Side Diff: Source/core/svg/SVGPathBlender.cpp

Issue 1056873002: Move SVG path blend state to its own object (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Re-order declarations. Created 5 years, 8 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/SVGPathBlender.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved. 2 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details. 12 * Library General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU Library General Public License 14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to 15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA. 17 * Boston, MA 02110-1301, USA.
18 */ 18 */
19 19
20 #include "config.h" 20 #include "config.h"
21 #include "core/svg/SVGPathBlender.h" 21 #include "core/svg/SVGPathBlender.h"
22 22
23 #include "core/svg/SVGPathConsumer.h" 23 #include "core/svg/SVGPathConsumer.h"
24 #include "core/svg/SVGPathSeg.h" 24 #include "core/svg/SVGPathSeg.h"
25 #include "core/svg/SVGPathSource.h" 25 #include "core/svg/SVGPathSource.h"
26 #include "platform/animation/AnimationUtilities.h" 26 #include "platform/animation/AnimationUtilities.h"
27 #include "wtf/TemporaryChange.h"
28 27
29 namespace blink { 28 namespace blink {
30 29
31 SVGPathBlender::SVGPathBlender(SVGPathSource* fromSource, SVGPathSource* toSourc e, SVGPathConsumer* consumer) 30 enum FloatBlendMode {
32 : m_fromSource(fromSource) 31 BlendHorizontal,
33 , m_toSource(toSource) 32 BlendVertical
34 , m_consumer(consumer) 33 };
35 , m_progress(0)
36 , m_addTypesCount(0)
37 , m_isInFirstHalfOfAnimation(false)
38 , m_typesAreEqual(false)
39 , m_fromIsAbsolute(false)
40 , m_toIsAbsolute(false)
41 {
42 ASSERT(m_fromSource);
43 ASSERT(m_toSource);
44 ASSERT(m_consumer);
45 }
46 34
47 DEFINE_TRACE(SVGPathBlender) 35 class SVGPathBlender::BlendState {
48 { 36 public:
49 visitor->trace(m_fromSource); 37 BlendState(float progress, unsigned addTypesCount = 0)
50 visitor->trace(m_toSource); 38 : m_progress(progress)
51 visitor->trace(m_consumer); 39 , m_addTypesCount(addTypesCount)
52 } 40 , m_isInFirstHalfOfAnimation(progress < 0.5f)
41 , m_typesAreEqual(false)
42 , m_fromIsAbsolute(false)
43 {
44 }
45
46 bool blendSegments(const PathSegmentData& fromSeg, const PathSegmentData& to Seg, PathSegmentData&);
47
48 private:
49 float blendAnimatedDimensonalFloat(float, float, FloatBlendMode);
50 FloatPoint blendAnimatedFloatPointSameCoordinates(const FloatPoint& from, co nst FloatPoint& to);
51 FloatPoint blendAnimatedFloatPoint(const FloatPoint& from, const FloatPoint& to);
52 bool canBlend(const PathSegmentData& fromSeg, const PathSegmentData& toSeg);
53
54 FloatPoint m_fromCurrentPoint;
55 FloatPoint m_toCurrentPoint;
56
57 float m_progress;
58 unsigned m_addTypesCount;
59 bool m_isInFirstHalfOfAnimation;
60 // This is per-segment blend state corresponding to the 'from' and 'to'
61 // segments currently being blended, and only used within blendSegments().
62 bool m_typesAreEqual;
63 bool m_fromIsAbsolute;
64 };
53 65
54 // Helper functions 66 // Helper functions
55 static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& b, float progress) 67 static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& b, float progress)
56 { 68 {
57 return FloatPoint(blend(a.x(), b.x(), progress), blend(a.y(), b.y(), progres s)); 69 return FloatPoint(blend(a.x(), b.x(), progress), blend(a.y(), b.y(), progres s));
58 } 70 }
59 71
60 float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBl endMode blendMode) 72 float SVGPathBlender::BlendState::blendAnimatedDimensonalFloat(float from, float to, FloatBlendMode blendMode)
61 { 73 {
62 if (m_addTypesCount) { 74 if (m_addTypesCount) {
63 ASSERT(m_typesAreEqual); 75 ASSERT(m_typesAreEqual);
64 return from + to * m_addTypesCount; 76 return from + to * m_addTypesCount;
65 } 77 }
66 78
67 if (m_typesAreEqual) 79 if (m_typesAreEqual)
68 return blend(from, to, m_progress); 80 return blend(from, to, m_progress);
69 81
70 float fromValue = blendMode == BlendHorizontal ? m_fromCurrentPoint.x() : m_ fromCurrentPoint.y(); 82 float fromValue = blendMode == BlendHorizontal ? m_fromCurrentPoint.x() : m_ fromCurrentPoint.y();
71 float toValue = blendMode == BlendHorizontal ? m_toCurrentPoint.x() : m_toCu rrentPoint.y(); 83 float toValue = blendMode == BlendHorizontal ? m_toCurrentPoint.x() : m_toCu rrentPoint.y();
72 84
73 // Transform toY to the coordinate mode of fromY 85 // Transform toY to the coordinate mode of fromY
74 float animValue = blend(from, m_fromIsAbsolute ? to + toValue : to - toValue , m_progress); 86 float animValue = blend(from, m_fromIsAbsolute ? to + toValue : to - toValue , m_progress);
75 87
76 // If we're in the first half of the animation, we should use the type of th e from segment. 88 // If we're in the first half of the animation, we should use the type of th e from segment.
77 if (m_isInFirstHalfOfAnimation) 89 if (m_isInFirstHalfOfAnimation)
78 return animValue; 90 return animValue;
79 91
80 // Transform the animated point to the coordinate mode, needed for the curre nt progress. 92 // Transform the animated point to the coordinate mode, needed for the curre nt progress.
81 float currentValue = blend(fromValue, toValue, m_progress); 93 float currentValue = blend(fromValue, toValue, m_progress);
82 return !m_fromIsAbsolute ? animValue + currentValue : animValue - currentVal ue; 94 return !m_fromIsAbsolute ? animValue + currentValue : animValue - currentVal ue;
83 } 95 }
84 96
85 FloatPoint SVGPathBlender::blendAnimatedFloatPointSameCoordinates(const FloatPoi nt& fromPoint, const FloatPoint& toPoint) 97 FloatPoint SVGPathBlender::BlendState::blendAnimatedFloatPointSameCoordinates(co nst FloatPoint& fromPoint, const FloatPoint& toPoint)
86 { 98 {
87 if (m_addTypesCount) { 99 if (m_addTypesCount) {
88 FloatPoint repeatedToPoint = toPoint; 100 FloatPoint repeatedToPoint = toPoint;
89 repeatedToPoint.scale(m_addTypesCount, m_addTypesCount); 101 repeatedToPoint.scale(m_addTypesCount, m_addTypesCount);
90 return fromPoint + repeatedToPoint; 102 return fromPoint + repeatedToPoint;
91 } 103 }
92 return blendFloatPoint(fromPoint, toPoint, m_progress); 104 return blendFloatPoint(fromPoint, toPoint, m_progress);
93 } 105 }
94 106
95 FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint) 107 FloatPoint SVGPathBlender::BlendState::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint)
96 { 108 {
97 if (m_typesAreEqual) 109 if (m_typesAreEqual)
98 return blendAnimatedFloatPointSameCoordinates(fromPoint, toPoint); 110 return blendAnimatedFloatPointSameCoordinates(fromPoint, toPoint);
99 111
100 // Transform toPoint to the coordinate mode of fromPoint 112 // Transform toPoint to the coordinate mode of fromPoint
101 FloatPoint animatedPoint = toPoint; 113 FloatPoint animatedPoint = toPoint;
102 if (m_fromIsAbsolute) 114 if (m_fromIsAbsolute)
103 animatedPoint += m_toCurrentPoint; 115 animatedPoint += m_toCurrentPoint;
104 else 116 else
105 animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y()); 117 animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y());
106 118
107 animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress); 119 animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress);
108 120
109 // If we're in the first half of the animation, we should use the type of th e from segment. 121 // If we're in the first half of the animation, we should use the type of th e from segment.
110 if (m_isInFirstHalfOfAnimation) 122 if (m_isInFirstHalfOfAnimation)
111 return animatedPoint; 123 return animatedPoint;
112 124
113 // Transform the animated point to the coordinate mode, needed for the curre nt progress. 125 // Transform the animated point to the coordinate mode, needed for the curre nt progress.
114 FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoi nt, m_progress); 126 FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoi nt, m_progress);
115 if (!m_fromIsAbsolute) 127 if (!m_fromIsAbsolute)
116 return animatedPoint + currentPoint; 128 return animatedPoint + currentPoint;
117 129
118 animatedPoint.move(-currentPoint.x(), -currentPoint.y()); 130 animatedPoint.move(-currentPoint.x(), -currentPoint.y());
119 return animatedPoint; 131 return animatedPoint;
120 } 132 }
121 133
122 PathSegmentData SVGPathBlender::blendMoveToSegment(const PathSegmentData& fromSe g, const PathSegmentData& toSeg) 134 bool SVGPathBlender::BlendState::canBlend(const PathSegmentData& fromSeg, const PathSegmentData& toSeg)
123 { 135 {
124 PathSegmentData blendedSegment; 136 // Update state first because we'll need it if we return true below.
125 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command; 137 m_typesAreEqual = fromSeg.command == toSeg.command;
126 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint); 138 m_fromIsAbsolute = isAbsolutePathSegType(fromSeg.command);
127 139
128 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint; 140 // If the types are equal, they'll blend regardless of parameters.
129 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint; 141 if (m_typesAreEqual)
130 return blendedSegment; 142 return true;
143
144 // Addition require segments with the same type.
145 if (m_addTypesCount)
146 return false;
147
148 // Allow the segments to differ in "relativeness".
149 return toAbsolutePathSegType(fromSeg.command) == toAbsolutePathSegType(toSeg .command);
131 } 150 }
132 151
133 PathSegmentData SVGPathBlender::blendLineToSegment(const PathSegmentData& fromSe g, const PathSegmentData& toSeg) 152 static void updateCurrentPoint(FloatPoint& currentPoint, const PathSegmentData& segment)
134 { 153 {
135 PathSegmentData blendedSegment; 154 switch (segment.command) {
136 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command; 155 case PathSegMoveToRel:
137 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint); 156 case PathSegLineToRel:
138 157 case PathSegCurveToCubicRel:
139 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint; 158 case PathSegCurveToQuadraticRel:
140 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint; 159 case PathSegArcRel:
141 return blendedSegment; 160 case PathSegLineToHorizontalRel:
161 case PathSegLineToVerticalRel:
162 case PathSegCurveToCubicSmoothRel:
163 case PathSegCurveToQuadraticSmoothRel:
164 currentPoint += segment.targetPoint;
165 break;
166 case PathSegMoveToAbs:
167 case PathSegLineToAbs:
168 case PathSegCurveToCubicAbs:
169 case PathSegCurveToQuadraticAbs:
170 case PathSegArcAbs:
171 case PathSegCurveToCubicSmoothAbs:
172 case PathSegCurveToQuadraticSmoothAbs:
173 currentPoint = segment.targetPoint;
174 break;
175 case PathSegLineToHorizontalAbs:
176 currentPoint.setX(segment.targetPoint.x());
177 break;
178 case PathSegLineToVerticalAbs:
179 currentPoint.setY(segment.targetPoint.y());
180 break;
181 case PathSegClosePath:
182 break;
183 default:
184 ASSERT_NOT_REACHED();
185 }
142 } 186 }
143 187
144 PathSegmentData SVGPathBlender::blendLineToHorizontalSegment(const PathSegmentDa ta& fromSeg, const PathSegmentData& toSeg) 188 bool SVGPathBlender::BlendState::blendSegments(const PathSegmentData& fromSeg, c onst PathSegmentData& toSeg, PathSegmentData& blendedSegment)
145 { 189 {
146 PathSegmentData blendedSegment; 190 if (!canBlend(fromSeg, toSeg))
191 return false;
192
147 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command; 193 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
148 blendedSegment.targetPoint.setX(blendAnimatedDimensonalFloat(fromSeg.targetP oint.x(), toSeg.targetPoint.x(), BlendHorizontal));
149 194
150 m_fromCurrentPoint.setX(m_fromIsAbsolute ? fromSeg.targetPoint.x() : m_fromC urrentPoint.x() + fromSeg.targetPoint.x());
151 m_toCurrentPoint.setX(m_toIsAbsolute ? toSeg.targetPoint.x() : m_toCurrentPo int.x() + toSeg.targetPoint.x());
152 return blendedSegment;
153 }
154
155 PathSegmentData SVGPathBlender::blendLineToVerticalSegment(const PathSegmentData & fromSeg, const PathSegmentData& toSeg)
156 {
157 PathSegmentData blendedSegment;
158 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
159 blendedSegment.targetPoint.setY(blendAnimatedDimensonalFloat(fromSeg.targetP oint.y(), toSeg.targetPoint.y(), BlendVertical));
160
161 m_fromCurrentPoint.setY(m_fromIsAbsolute ? fromSeg.targetPoint.y() : m_fromC urrentPoint.y() + fromSeg.targetPoint.y());
162 m_toCurrentPoint.setY(m_toIsAbsolute ? toSeg.targetPoint.y() : m_toCurrentPo int.y() + toSeg.targetPoint.y());
163 return blendedSegment;
164 }
165
166 PathSegmentData SVGPathBlender::blendCurveToCubicSegment(const PathSegmentData& fromSeg, const PathSegmentData& toSeg)
167 {
168 PathSegmentData blendedSegment;
169 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
170 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
171 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1 );
172 blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2 );
173
174 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint;
175 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint;
176 return blendedSegment;
177 }
178
179 PathSegmentData SVGPathBlender::blendCurveToCubicSmoothSegment(const PathSegment Data& fromSeg, const PathSegmentData& toSeg)
180 {
181 PathSegmentData blendedSegment;
182 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
183 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
184 blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2 );
185
186 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint;
187 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint;
188 return blendedSegment;
189 }
190
191 PathSegmentData SVGPathBlender::blendCurveToQuadraticSegment(const PathSegmentDa ta& fromSeg, const PathSegmentData& toSeg)
192 {
193 PathSegmentData blendedSegment;
194 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
195 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
196 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1 );
197
198 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint;
199 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint;
200 return blendedSegment;
201 }
202
203 PathSegmentData SVGPathBlender::blendCurveToQuadraticSmoothSegment(const PathSeg mentData& fromSeg, const PathSegmentData& toSeg)
204 {
205 PathSegmentData blendedSegment;
206 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
207 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
208
209 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint;
210 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint;
211 return blendedSegment;
212 }
213
214 PathSegmentData SVGPathBlender::blendArcToSegment(const PathSegmentData& fromSeg , const PathSegmentData& toSeg)
215 {
216 ASSERT(!m_addTypesCount || fromSeg.command == toSeg.command);
217
218 PathSegmentData blendedSegment;
219 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
220 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
221 blendedSegment.point1 = blendAnimatedFloatPointSameCoordinates(fromSeg.arcRa dii(), toSeg.arcRadii());
222 blendedSegment.point2 = blendAnimatedFloatPointSameCoordinates(fromSeg.point 2, toSeg.point2);
223 if (m_addTypesCount) {
224 blendedSegment.arcLarge = fromSeg.arcLarge || toSeg.arcLarge;
225 blendedSegment.arcSweep = fromSeg.arcSweep || toSeg.arcSweep;
226 } else {
227 blendedSegment.arcLarge = m_isInFirstHalfOfAnimation ? fromSeg.arcLarge : toSeg.arcLarge;
228 blendedSegment.arcSweep = m_isInFirstHalfOfAnimation ? fromSeg.arcSweep : toSeg.arcSweep;
229 }
230
231 m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentP oint + fromSeg.targetPoint;
232 m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + t oSeg.targetPoint;
233 return blendedSegment;
234 }
235
236 void SVGPathBlender::blendSegments(const PathSegmentData& fromSeg, const PathSeg mentData& toSeg)
237 {
238 PathSegmentData blendedSegment;
239 switch (toSeg.command) { 195 switch (toSeg.command) {
196 case PathSegCurveToCubicRel:
197 case PathSegCurveToCubicAbs:
198 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.po int1);
199 /* fall through */
200 case PathSegCurveToCubicSmoothRel:
201 case PathSegCurveToCubicSmoothAbs:
202 blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.po int2);
203 /* fall through */
240 case PathSegMoveToRel: 204 case PathSegMoveToRel:
241 case PathSegMoveToAbs: 205 case PathSegMoveToAbs:
242 blendedSegment = blendMoveToSegment(fromSeg, toSeg);
243 break;
244 case PathSegLineToRel: 206 case PathSegLineToRel:
245 case PathSegLineToAbs: 207 case PathSegLineToAbs:
246 blendedSegment = blendLineToSegment(fromSeg, toSeg); 208 case PathSegCurveToQuadraticSmoothRel:
209 case PathSegCurveToQuadraticSmoothAbs:
210 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint , toSeg.targetPoint);
247 break; 211 break;
248 case PathSegLineToHorizontalRel: 212 case PathSegLineToHorizontalRel:
249 case PathSegLineToHorizontalAbs: 213 case PathSegLineToHorizontalAbs:
250 blendedSegment = blendLineToHorizontalSegment(fromSeg, toSeg); 214 blendedSegment.targetPoint.setX(blendAnimatedDimensonalFloat(fromSeg.tar getPoint.x(), toSeg.targetPoint.x(), BlendHorizontal));
251 break; 215 break;
252 case PathSegLineToVerticalRel: 216 case PathSegLineToVerticalRel:
253 case PathSegLineToVerticalAbs: 217 case PathSegLineToVerticalAbs:
254 blendedSegment = blendLineToVerticalSegment(fromSeg, toSeg); 218 blendedSegment.targetPoint.setY(blendAnimatedDimensonalFloat(fromSeg.tar getPoint.y(), toSeg.targetPoint.y(), BlendVertical));
255 break; 219 break;
256 case PathSegClosePath: 220 case PathSegClosePath:
257 blendedSegment = toSeg;
258 break;
259 case PathSegCurveToCubicRel:
260 case PathSegCurveToCubicAbs:
261 blendedSegment = blendCurveToCubicSegment(fromSeg, toSeg);
262 break;
263 case PathSegCurveToCubicSmoothRel:
264 case PathSegCurveToCubicSmoothAbs:
265 blendedSegment = blendCurveToCubicSmoothSegment(fromSeg, toSeg);
266 break; 221 break;
267 case PathSegCurveToQuadraticRel: 222 case PathSegCurveToQuadraticRel:
268 case PathSegCurveToQuadraticAbs: 223 case PathSegCurveToQuadraticAbs:
269 blendedSegment = blendCurveToQuadraticSegment(fromSeg, toSeg); 224 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint , toSeg.targetPoint);
270 break; 225 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.po int1);
271 case PathSegCurveToQuadraticSmoothRel:
272 case PathSegCurveToQuadraticSmoothAbs:
273 blendedSegment = blendCurveToQuadraticSmoothSegment(fromSeg, toSeg);
274 break; 226 break;
275 case PathSegArcRel: 227 case PathSegArcRel:
276 case PathSegArcAbs: 228 case PathSegArcAbs:
277 blendedSegment = blendArcToSegment(fromSeg, toSeg); 229 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint , toSeg.targetPoint);
230 blendedSegment.point1 = blendAnimatedFloatPointSameCoordinates(fromSeg.a rcRadii(), toSeg.arcRadii());
231 blendedSegment.point2 = blendAnimatedFloatPointSameCoordinates(fromSeg.p oint2, toSeg.point2);
232 if (m_addTypesCount) {
233 blendedSegment.arcLarge = fromSeg.arcLarge || toSeg.arcLarge;
234 blendedSegment.arcSweep = fromSeg.arcSweep || toSeg.arcSweep;
235 } else {
236 blendedSegment.arcLarge = m_isInFirstHalfOfAnimation ? fromSeg.arcLa rge : toSeg.arcLarge;
237 blendedSegment.arcSweep = m_isInFirstHalfOfAnimation ? fromSeg.arcSw eep : toSeg.arcSweep;
238 }
278 break; 239 break;
279 default: 240 default:
280 ASSERT_NOT_REACHED(); 241 ASSERT_NOT_REACHED();
281 } 242 }
282 243
283 m_consumer->emitSegment(blendedSegment); 244 updateCurrentPoint(m_fromCurrentPoint, fromSeg);
245 updateCurrentPoint(m_toCurrentPoint, toSeg);
246
247 return true;
248 }
249
250 SVGPathBlender::SVGPathBlender(SVGPathSource* fromSource, SVGPathSource* toSourc e, SVGPathConsumer* consumer)
251 : m_fromSource(fromSource)
252 , m_toSource(toSource)
253 , m_consumer(consumer)
254 {
255 ASSERT(m_fromSource);
256 ASSERT(m_toSource);
257 ASSERT(m_consumer);
258 }
259
260 DEFINE_TRACE(SVGPathBlender)
261 {
262 visitor->trace(m_fromSource);
263 visitor->trace(m_toSource);
264 visitor->trace(m_consumer);
284 } 265 }
285 266
286 bool SVGPathBlender::addAnimatedPath(unsigned repeatCount) 267 bool SVGPathBlender::addAnimatedPath(unsigned repeatCount)
287 { 268 {
288 TemporaryChange<unsigned> change(m_addTypesCount, repeatCount); 269 BlendState blendState(0, repeatCount);
289 return blendAnimatedPath(0); 270 return blendAnimatedPath(blendState);
290 } 271 }
291 272
292 bool SVGPathBlender::blendAnimatedPath(float progress) 273 bool SVGPathBlender::blendAnimatedPath(float progress)
293 { 274 {
294 m_isInFirstHalfOfAnimation = progress < 0.5f; 275 BlendState blendState(progress);
295 m_progress = progress; 276 return blendAnimatedPath(blendState);
277 }
296 278
297 bool fromSourceHadData = m_fromSource->hasMoreData(); 279 bool SVGPathBlender::blendAnimatedPath(BlendState& blendState)
280 {
281 bool fromSourceIsEmpty = !m_fromSource->hasMoreData();
298 while (m_toSource->hasMoreData()) { 282 while (m_toSource->hasMoreData()) {
299 PathSegmentData toSeg = m_toSource->parseSegment(); 283 PathSegmentData toSeg = m_toSource->parseSegment();
300 if (toSeg.command == PathSegUnknown) 284 if (toSeg.command == PathSegUnknown)
301 return false; 285 return false;
302 286
303 PathSegmentData fromSeg; 287 PathSegmentData fromSeg;
304 fromSeg.command = toSeg.command; 288 fromSeg.command = toSeg.command;
305 289
306 if (m_fromSource->hasMoreData()) { 290 if (m_fromSource->hasMoreData()) {
307 fromSeg = m_fromSource->parseSegment(); 291 fromSeg = m_fromSource->parseSegment();
308 if (fromSeg.command == PathSegUnknown) 292 if (fromSeg.command == PathSegUnknown)
309 return false; 293 return false;
310 } 294 }
311 295
312 m_typesAreEqual = fromSeg.command == toSeg.command; 296 PathSegmentData blendedSeg;
297 if (!blendState.blendSegments(fromSeg, toSeg, blendedSeg))
298 return false;
313 299
314 // If the types are equal, they'll blend regardless of parameters. 300 m_consumer->emitSegment(blendedSeg);
315 if (!m_typesAreEqual) {
316 // Addition require segments with the same type.
317 if (m_addTypesCount)
318 return false;
319 // Allow the segments to differ in "relativeness".
320 if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType( toSeg.command))
321 return false;
322 }
323 301
324 m_fromIsAbsolute = isAbsolutePathSegType(fromSeg.command); 302 if (fromSourceIsEmpty)
325 m_toIsAbsolute = isAbsolutePathSegType(toSeg.command);
326
327 blendSegments(fromSeg, toSeg);
328
329 if (!fromSourceHadData)
330 continue; 303 continue;
331 if (m_fromSource->hasMoreData() != m_toSource->hasMoreData()) 304 if (m_fromSource->hasMoreData() != m_toSource->hasMoreData())
332 return false; 305 return false;
333 } 306 }
334 return true; 307 return true;
335 } 308 }
336 309
337 } 310 }
OLDNEW
« no previous file with comments | « Source/core/svg/SVGPathBlender.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698