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

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

Issue 1037463002: Rework the SVGPathConsumer interface (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 9 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
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
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 106
107 // Transform the animated point to the coordinate mode, needed for the curre nt progress. 107 // Transform the animated point to the coordinate mode, needed for the curre nt progress.
108 FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoi nt, m_progress); 108 FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoi nt, m_progress);
109 if (m_toMode == AbsoluteCoordinates) 109 if (m_toMode == AbsoluteCoordinates)
110 return animatedPoint + currentPoint; 110 return animatedPoint + currentPoint;
111 111
112 animatedPoint.move(-currentPoint.x(), -currentPoint.y()); 112 animatedPoint.move(-currentPoint.x(), -currentPoint.y());
113 return animatedPoint; 113 return animatedPoint;
114 } 114 }
115 115
116 void SVGPathBlender::blendMoveToSegment(const PathSegmentData& fromSeg, const Pa thSegmentData& toSeg) 116 PathSegmentData SVGPathBlender::blendMoveToSegment(const PathSegmentData& fromSe g, const PathSegmentData& toSeg)
117 { 117 {
118 m_consumer->moveTo(blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.target Point), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 118 PathSegmentData blendedSegment;
119 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
120 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
121
119 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 122 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
120 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 123 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
124 return blendedSegment;
121 } 125 }
122 126
123 void SVGPathBlender::blendLineToSegment(const PathSegmentData& fromSeg, const Pa thSegmentData& toSeg) 127 PathSegmentData SVGPathBlender::blendLineToSegment(const PathSegmentData& fromSe g, const PathSegmentData& toSeg)
124 { 128 {
125 m_consumer->lineTo(blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.target Point), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 129 PathSegmentData blendedSegment;
130 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
131 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
132
126 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 133 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
127 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 134 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
135 return blendedSegment;
128 } 136 }
129 137
130 void SVGPathBlender::blendLineToHorizontalSegment(const PathSegmentData& fromSeg , const PathSegmentData& toSeg) 138 PathSegmentData SVGPathBlender::blendLineToHorizontalSegment(const PathSegmentDa ta& fromSeg, const PathSegmentData& toSeg)
131 { 139 {
132 float fromX = fromSeg.targetPoint.x(); 140 PathSegmentData blendedSegment;
133 float toX = toSeg.targetPoint.x(); 141 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
134 m_consumer->lineToHorizontal(blendAnimatedDimensonalFloat(fromX, toX, BlendH orizontal), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 142 blendedSegment.targetPoint.setX(blendAnimatedDimensonalFloat(fromSeg.targetP oint.x(), toSeg.targetPoint.x(), BlendHorizontal));
135 m_fromCurrentPoint.setX(m_fromMode == AbsoluteCoordinates ? fromX : m_fromCu rrentPoint.x() + fromX); 143
136 m_toCurrentPoint.setX(m_toMode == AbsoluteCoordinates ? toX : m_toCurrentPoi nt.x() + toX); 144 m_fromCurrentPoint.setX(m_fromMode == AbsoluteCoordinates ? fromSeg.targetPo int.x() : m_fromCurrentPoint.x() + fromSeg.targetPoint.x());
145 m_toCurrentPoint.setX(m_toMode == AbsoluteCoordinates ? toSeg.targetPoint.x( ) : m_toCurrentPoint.x() + toSeg.targetPoint.x());
146 return blendedSegment;
137 } 147 }
138 148
139 void SVGPathBlender::blendLineToVerticalSegment(const PathSegmentData& fromSeg, const PathSegmentData& toSeg) 149 PathSegmentData SVGPathBlender::blendLineToVerticalSegment(const PathSegmentData & fromSeg, const PathSegmentData& toSeg)
140 { 150 {
141 float fromY = fromSeg.targetPoint.y(); 151 PathSegmentData blendedSegment;
142 float toY = toSeg.targetPoint.y(); 152 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
143 m_consumer->lineToVertical(blendAnimatedDimensonalFloat(fromY, toY, BlendVer tical), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 153 blendedSegment.targetPoint.setY(blendAnimatedDimensonalFloat(fromSeg.targetP oint.y(), toSeg.targetPoint.y(), BlendVertical));
144 m_fromCurrentPoint.setY(m_fromMode == AbsoluteCoordinates ? fromY : m_fromCu rrentPoint.y() + fromY); 154
145 m_toCurrentPoint.setY(m_toMode == AbsoluteCoordinates ? toY : m_toCurrentPoi nt.y() + toY); 155 m_fromCurrentPoint.setY(m_fromMode == AbsoluteCoordinates ? fromSeg.targetPo int.y() : m_fromCurrentPoint.y() + fromSeg.targetPoint.y());
156 m_toCurrentPoint.setY(m_toMode == AbsoluteCoordinates ? toSeg.targetPoint.y( ) : m_toCurrentPoint.y() + toSeg.targetPoint.y());
157 return blendedSegment;
146 } 158 }
147 159
148 void SVGPathBlender::blendCurveToCubicSegment(const PathSegmentData& fromSeg, co nst PathSegmentData& toSeg) 160 PathSegmentData SVGPathBlender::blendCurveToCubicSegment(const PathSegmentData& fromSeg, const PathSegmentData& toSeg)
149 { 161 {
150 m_consumer->curveToCubic( 162 PathSegmentData blendedSegment;
151 blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1), 163 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
152 blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2), 164 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
153 blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint), 165 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1 );
154 m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 166 blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2 );
167
155 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 168 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
156 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 169 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
170 return blendedSegment;
157 } 171 }
158 172
159 void SVGPathBlender::blendCurveToCubicSmoothSegment(const PathSegmentData& fromS eg, const PathSegmentData& toSeg) 173 PathSegmentData SVGPathBlender::blendCurveToCubicSmoothSegment(const PathSegment Data& fromSeg, const PathSegmentData& toSeg)
160 { 174 {
161 m_consumer->curveToCubicSmooth( 175 PathSegmentData blendedSegment;
162 blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2), 176 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
163 blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint), 177 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
164 m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 178 blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2 );
179
165 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 180 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
166 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 181 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
182 return blendedSegment;
167 } 183 }
168 184
169 void SVGPathBlender::blendCurveToQuadraticSegment(const PathSegmentData& fromSeg , const PathSegmentData& toSeg) 185 PathSegmentData SVGPathBlender::blendCurveToQuadraticSegment(const PathSegmentDa ta& fromSeg, const PathSegmentData& toSeg)
170 { 186 {
171 m_consumer->curveToQuadratic( 187 PathSegmentData blendedSegment;
172 blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1), 188 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
173 blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint), 189 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
174 m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 190 blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1 );
191
175 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 192 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
176 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 193 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
194 return blendedSegment;
177 } 195 }
178 196
179 void SVGPathBlender::blendCurveToQuadraticSmoothSegment(const PathSegmentData& f romSeg, const PathSegmentData& toSeg) 197 PathSegmentData SVGPathBlender::blendCurveToQuadraticSmoothSegment(const PathSeg mentData& fromSeg, const PathSegmentData& toSeg)
180 { 198 {
181 m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromSeg.targetPoi nt, toSeg.targetPoint), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode); 199 PathSegmentData blendedSegment;
200 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
201 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
202
182 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 203 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
183 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 204 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
205 return blendedSegment;
184 } 206 }
185 207
186 void SVGPathBlender::blendArcToSegment(const PathSegmentData& fromSeg, const Pat hSegmentData& toSeg) 208 PathSegmentData SVGPathBlender::blendArcToSegment(const PathSegmentData& fromSeg , const PathSegmentData& toSeg)
187 { 209 {
188 ASSERT(!m_addTypesCount || fromSeg.command == toSeg.command); 210 ASSERT(!m_addTypesCount || fromSeg.command == toSeg.command);
189 211
190 bool blendedLargeArc; 212 PathSegmentData blendedSegment;
191 bool blendedSweep; 213 blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSe g.command;
f(malita) 2015/03/25 15:08:15 This is common logic within all these methods - wo
fs 2015/03/25 17:08:13 Yes, I think I have a follow-up that "commons up"
192 214 blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, to Seg.targetPoint);
215 blendedSegment.point1 = blendAnimatedFloatPointSameCoordinates(fromSeg.arcRa dii(), toSeg.arcRadii());
216 blendedSegment.point2 = blendAnimatedFloatPointSameCoordinates(fromSeg.point 2, toSeg.point2);
193 if (m_addTypesCount) { 217 if (m_addTypesCount) {
194 blendedLargeArc = fromSeg.arcLarge || toSeg.arcLarge; 218 blendedSegment.arcLarge = fromSeg.arcLarge || toSeg.arcLarge;
195 blendedSweep = fromSeg.arcSweep || toSeg.arcSweep; 219 blendedSegment.arcSweep = fromSeg.arcSweep || toSeg.arcSweep;
196 } else { 220 } else {
197 blendedLargeArc = m_isInFirstHalfOfAnimation ? fromSeg.arcLarge : toSeg. arcLarge; 221 blendedSegment.arcLarge = m_isInFirstHalfOfAnimation ? fromSeg.arcLarge : toSeg.arcLarge;
198 blendedSweep = m_isInFirstHalfOfAnimation ? fromSeg.arcSweep : toSeg.arc Sweep; 222 blendedSegment.arcSweep = m_isInFirstHalfOfAnimation ? fromSeg.arcSweep : toSeg.arcSweep;
199 } 223 }
200 224
201 FloatPoint blendedRadii = blendAnimatedFloatPointSameCoordinates(fromSeg.arc Radii(), toSeg.arcRadii());
202 float blendedAngle = blendAnimatedFloatPointSameCoordinates(fromSeg.point2, toSeg.point2).x();
203
204 m_consumer->arcTo(
205 blendedRadii.x(), blendedRadii.y(), blendedAngle, blendedLargeArc, blend edSweep,
206 blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint),
207 m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
208
209 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; 225 m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint;
210 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint; 226 m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_t oCurrentPoint + toSeg.targetPoint;
227 return blendedSegment;
228 }
229
230 void SVGPathBlender::blendSegments(const PathSegmentData& fromSeg, const PathSeg mentData& toSeg)
231 {
232 PathSegmentData blendedSegment;
233 switch (toSeg.command) {
234 case PathSegMoveToRel:
235 case PathSegMoveToAbs:
236 blendedSegment = blendMoveToSegment(fromSeg, toSeg);
237 break;
238 case PathSegLineToRel:
239 case PathSegLineToAbs:
240 blendedSegment = blendLineToSegment(fromSeg, toSeg);
241 break;
242 case PathSegLineToHorizontalRel:
243 case PathSegLineToHorizontalAbs:
244 blendedSegment = blendLineToHorizontalSegment(fromSeg, toSeg);
245 break;
246 case PathSegLineToVerticalRel:
247 case PathSegLineToVerticalAbs:
248 blendedSegment = blendLineToVerticalSegment(fromSeg, toSeg);
249 break;
250 case PathSegClosePath:
251 blendedSegment = toSeg;
252 break;
253 case PathSegCurveToCubicRel:
254 case PathSegCurveToCubicAbs:
255 blendedSegment = blendCurveToCubicSegment(fromSeg, toSeg);
256 break;
257 case PathSegCurveToCubicSmoothRel:
258 case PathSegCurveToCubicSmoothAbs:
259 blendedSegment = blendCurveToCubicSmoothSegment(fromSeg, toSeg);
260 break;
261 case PathSegCurveToQuadraticRel:
262 case PathSegCurveToQuadraticAbs:
263 blendedSegment = blendCurveToQuadraticSegment(fromSeg, toSeg);
264 break;
265 case PathSegCurveToQuadraticSmoothRel:
266 case PathSegCurveToQuadraticSmoothAbs:
267 blendedSegment = blendCurveToQuadraticSmoothSegment(fromSeg, toSeg);
268 break;
269 case PathSegArcRel:
270 case PathSegArcAbs:
271 blendedSegment = blendArcToSegment(fromSeg, toSeg);
272 break;
273 default:
274 ASSERT_NOT_REACHED();
275 }
276
277 m_consumer->emitSegment(blendedSegment);
f(malita) 2015/03/25 15:08:15 Do you know if we have any perf coverage for this
fs 2015/03/25 17:08:13 I'm not aware of any tests like that, so I suppose
fs 2015/03/25 17:56:11 I extracted some path animations from some SVGs I
211 } 278 }
212 279
213 static inline PathCoordinateMode coordinateModeOfCommand(const SVGPathSegType& t ype) 280 static inline PathCoordinateMode coordinateModeOfCommand(const SVGPathSegType& t ype)
214 { 281 {
215 if (type < PathSegMoveToAbs) 282 if (type < PathSegMoveToAbs)
216 return AbsoluteCoordinates; 283 return AbsoluteCoordinates;
217 284
218 // Odd number = relative command 285 // Odd number = relative command
219 if (type % 2) 286 if (type % 2)
220 return RelativeCoordinates; 287 return RelativeCoordinates;
(...skipping 29 matching lines...) Expand all
250 317
251 if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType(toSe g.command)) 318 if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType(toSe g.command))
252 return false; 319 return false;
253 320
254 m_fromMode = coordinateModeOfCommand(fromSeg.command); 321 m_fromMode = coordinateModeOfCommand(fromSeg.command);
255 m_toMode = coordinateModeOfCommand(toSeg.command); 322 m_toMode = coordinateModeOfCommand(toSeg.command);
256 323
257 if (m_addTypesCount && m_fromMode != m_toMode) 324 if (m_addTypesCount && m_fromMode != m_toMode)
258 return false; 325 return false;
259 326
260 switch (toSeg.command) { 327 blendSegments(fromSeg, toSeg);
261 case PathSegMoveToRel:
262 case PathSegMoveToAbs:
263 blendMoveToSegment(fromSeg, toSeg);
264 break;
265 case PathSegLineToRel:
266 case PathSegLineToAbs:
267 blendLineToSegment(fromSeg, toSeg);
268 break;
269 case PathSegLineToHorizontalRel:
270 case PathSegLineToHorizontalAbs:
271 blendLineToHorizontalSegment(fromSeg, toSeg);
272 break;
273 case PathSegLineToVerticalRel:
274 case PathSegLineToVerticalAbs:
275 blendLineToVerticalSegment(fromSeg, toSeg);
276 break;
277 case PathSegClosePath:
278 m_consumer->closePath();
279 break;
280 case PathSegCurveToCubicRel:
281 case PathSegCurveToCubicAbs:
282 blendCurveToCubicSegment(fromSeg, toSeg);
283 break;
284 case PathSegCurveToCubicSmoothRel:
285 case PathSegCurveToCubicSmoothAbs:
286 blendCurveToCubicSmoothSegment(fromSeg, toSeg);
287 break;
288 case PathSegCurveToQuadraticRel:
289 case PathSegCurveToQuadraticAbs:
290 blendCurveToQuadraticSegment(fromSeg, toSeg);
291 break;
292 case PathSegCurveToQuadraticSmoothRel:
293 case PathSegCurveToQuadraticSmoothAbs:
294 blendCurveToQuadraticSmoothSegment(fromSeg, toSeg);
295 break;
296 case PathSegArcRel:
297 case PathSegArcAbs:
298 blendArcToSegment(fromSeg, toSeg);
299 break;
300 default:
301 ASSERT_NOT_REACHED();
302 }
303 328
304 if (!fromSourceHadData) 329 if (!fromSourceHadData)
305 continue; 330 continue;
306 if (m_fromSource->hasMoreData() != m_toSource->hasMoreData()) 331 if (m_fromSource->hasMoreData() != m_toSource->hasMoreData())
307 return false; 332 return false;
308 } 333 }
309 return true; 334 return true;
310 } 335 }
311 336
312 } 337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698