Index: Source/core/svg/SVGPathBlender.cpp |
diff --git a/Source/core/svg/SVGPathBlender.cpp b/Source/core/svg/SVGPathBlender.cpp |
index 3e0fb27661e770a10ee6c9dd825b94d8b537384a..dbd5aabda028b20d82aeb66bd3007a5044ce4e9f 100644 |
--- a/Source/core/svg/SVGPathBlender.cpp |
+++ b/Source/core/svg/SVGPathBlender.cpp |
@@ -20,6 +20,7 @@ |
#include "config.h" |
#include "core/svg/SVGPathBlender.h" |
+#include "core/svg/SVGPathConsumer.h" |
#include "core/svg/SVGPathSeg.h" |
#include "core/svg/SVGPathSource.h" |
#include "platform/animation/AnimationUtilities.h" |
@@ -34,6 +35,9 @@ SVGPathBlender::SVGPathBlender(SVGPathSource* fromSource, SVGPathSource* toSourc |
, m_progress(0) |
, m_addTypesCount(0) |
, m_isInFirstHalfOfAnimation(false) |
+ , m_typesAreEqual(false) |
+ , m_fromIsAbsolute(false) |
+ , m_toIsAbsolute(false) |
{ |
ASSERT(m_fromSource); |
ASSERT(m_toSource); |
@@ -56,25 +60,26 @@ static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& |
float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBlendMode blendMode) |
{ |
if (m_addTypesCount) { |
- ASSERT(m_fromMode == m_toMode); |
+ ASSERT(m_typesAreEqual); |
return from + to * m_addTypesCount; |
} |
- if (m_fromMode == m_toMode) |
+ if (m_typesAreEqual) |
return blend(from, to, m_progress); |
float fromValue = blendMode == BlendHorizontal ? m_fromCurrentPoint.x() : m_fromCurrentPoint.y(); |
float toValue = blendMode == BlendHorizontal ? m_toCurrentPoint.x() : m_toCurrentPoint.y(); |
// Transform toY to the coordinate mode of fromY |
- float animValue = blend(from, m_fromMode == AbsoluteCoordinates ? to + toValue : to - toValue, m_progress); |
+ float animValue = blend(from, m_fromIsAbsolute ? to + toValue : to - toValue, m_progress); |
+ // If we're in the first half of the animation, we should use the type of the from segment. |
if (m_isInFirstHalfOfAnimation) |
return animValue; |
// Transform the animated point to the coordinate mode, needed for the current progress. |
float currentValue = blend(fromValue, toValue, m_progress); |
- return m_toMode == AbsoluteCoordinates ? animValue + currentValue : animValue - currentValue; |
+ return !m_fromIsAbsolute ? animValue + currentValue : animValue - currentValue; |
} |
FloatPoint SVGPathBlender::blendAnimatedFloatPointSameCoordinates(const FloatPoint& fromPoint, const FloatPoint& toPoint) |
@@ -89,24 +94,25 @@ FloatPoint SVGPathBlender::blendAnimatedFloatPointSameCoordinates(const FloatPoi |
FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint) |
{ |
- if (m_fromMode == m_toMode) |
+ if (m_typesAreEqual) |
return blendAnimatedFloatPointSameCoordinates(fromPoint, toPoint); |
// Transform toPoint to the coordinate mode of fromPoint |
FloatPoint animatedPoint = toPoint; |
- if (m_fromMode == AbsoluteCoordinates) |
+ if (m_fromIsAbsolute) |
animatedPoint += m_toCurrentPoint; |
else |
animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y()); |
animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress); |
+ // If we're in the first half of the animation, we should use the type of the from segment. |
if (m_isInFirstHalfOfAnimation) |
return animatedPoint; |
// Transform the animated point to the coordinate mode, needed for the current progress. |
FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoint, m_progress); |
- if (m_toMode == AbsoluteCoordinates) |
+ if (!m_fromIsAbsolute) |
return animatedPoint + currentPoint; |
animatedPoint.move(-currentPoint.x(), -currentPoint.y()); |
@@ -119,8 +125,8 @@ PathSegmentData SVGPathBlender::blendMoveToSegment(const PathSegmentData& fromSe |
blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSeg.command; |
blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -130,8 +136,8 @@ PathSegmentData SVGPathBlender::blendLineToSegment(const PathSegmentData& fromSe |
blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSeg.command; |
blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -141,8 +147,8 @@ PathSegmentData SVGPathBlender::blendLineToHorizontalSegment(const PathSegmentDa |
blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSeg.command; |
blendedSegment.targetPoint.setX(blendAnimatedDimensonalFloat(fromSeg.targetPoint.x(), toSeg.targetPoint.x(), BlendHorizontal)); |
- m_fromCurrentPoint.setX(m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint.x() : m_fromCurrentPoint.x() + fromSeg.targetPoint.x()); |
- m_toCurrentPoint.setX(m_toMode == AbsoluteCoordinates ? toSeg.targetPoint.x() : m_toCurrentPoint.x() + toSeg.targetPoint.x()); |
+ m_fromCurrentPoint.setX(m_fromIsAbsolute ? fromSeg.targetPoint.x() : m_fromCurrentPoint.x() + fromSeg.targetPoint.x()); |
+ m_toCurrentPoint.setX(m_toIsAbsolute ? toSeg.targetPoint.x() : m_toCurrentPoint.x() + toSeg.targetPoint.x()); |
return blendedSegment; |
} |
@@ -152,8 +158,8 @@ PathSegmentData SVGPathBlender::blendLineToVerticalSegment(const PathSegmentData |
blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSeg.command; |
blendedSegment.targetPoint.setY(blendAnimatedDimensonalFloat(fromSeg.targetPoint.y(), toSeg.targetPoint.y(), BlendVertical)); |
- m_fromCurrentPoint.setY(m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint.y() : m_fromCurrentPoint.y() + fromSeg.targetPoint.y()); |
- m_toCurrentPoint.setY(m_toMode == AbsoluteCoordinates ? toSeg.targetPoint.y() : m_toCurrentPoint.y() + toSeg.targetPoint.y()); |
+ m_fromCurrentPoint.setY(m_fromIsAbsolute ? fromSeg.targetPoint.y() : m_fromCurrentPoint.y() + fromSeg.targetPoint.y()); |
+ m_toCurrentPoint.setY(m_toIsAbsolute ? toSeg.targetPoint.y() : m_toCurrentPoint.y() + toSeg.targetPoint.y()); |
return blendedSegment; |
} |
@@ -165,8 +171,8 @@ PathSegmentData SVGPathBlender::blendCurveToCubicSegment(const PathSegmentData& |
blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1); |
blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -177,8 +183,8 @@ PathSegmentData SVGPathBlender::blendCurveToCubicSmoothSegment(const PathSegment |
blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint); |
blendedSegment.point2 = blendAnimatedFloatPoint(fromSeg.point2, toSeg.point2); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -189,8 +195,8 @@ PathSegmentData SVGPathBlender::blendCurveToQuadraticSegment(const PathSegmentDa |
blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint); |
blendedSegment.point1 = blendAnimatedFloatPoint(fromSeg.point1, toSeg.point1); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -200,8 +206,8 @@ PathSegmentData SVGPathBlender::blendCurveToQuadraticSmoothSegment(const PathSeg |
blendedSegment.command = m_isInFirstHalfOfAnimation ? fromSeg.command : toSeg.command; |
blendedSegment.targetPoint = blendAnimatedFloatPoint(fromSeg.targetPoint, toSeg.targetPoint); |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -222,8 +228,8 @@ PathSegmentData SVGPathBlender::blendArcToSegment(const PathSegmentData& fromSeg |
blendedSegment.arcSweep = m_isInFirstHalfOfAnimation ? fromSeg.arcSweep : toSeg.arcSweep; |
} |
- m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
- m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
+ m_fromCurrentPoint = m_fromIsAbsolute ? fromSeg.targetPoint : m_fromCurrentPoint + fromSeg.targetPoint; |
+ m_toCurrentPoint = m_toIsAbsolute ? toSeg.targetPoint : m_toCurrentPoint + toSeg.targetPoint; |
return blendedSegment; |
} |
@@ -277,18 +283,6 @@ void SVGPathBlender::blendSegments(const PathSegmentData& fromSeg, const PathSeg |
m_consumer->emitSegment(blendedSegment); |
} |
-static inline PathCoordinateMode coordinateModeOfCommand(const SVGPathSegType& type) |
-{ |
- if (type < PathSegMoveToAbs) |
- return AbsoluteCoordinates; |
- |
- // Odd number = relative command |
- if (type % 2) |
- return RelativeCoordinates; |
- |
- return AbsoluteCoordinates; |
-} |
- |
bool SVGPathBlender::addAnimatedPath(unsigned repeatCount) |
{ |
TemporaryChange<unsigned> change(m_addTypesCount, repeatCount); |
@@ -315,14 +309,20 @@ bool SVGPathBlender::blendAnimatedPath(float progress) |
return false; |
} |
- if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType(toSeg.command)) |
- return false; |
+ m_typesAreEqual = fromSeg.command == toSeg.command; |
- m_fromMode = coordinateModeOfCommand(fromSeg.command); |
- m_toMode = coordinateModeOfCommand(toSeg.command); |
+ // If the types are equal, they'll blend regardless of parameters. |
+ if (!m_typesAreEqual) { |
+ // Addition require segments with the same type. |
+ if (m_addTypesCount) |
+ return false; |
+ // Allow the segments to differ in "relativeness". |
+ if (toAbsolutePathSegType(fromSeg.command) != toAbsolutePathSegType(toSeg.command)) |
+ return false; |
+ } |
- if (m_addTypesCount && m_fromMode != m_toMode) |
- return false; |
+ m_fromIsAbsolute = isAbsolutePathSegType(fromSeg.command); |
+ m_toIsAbsolute = isAbsolutePathSegType(toSeg.command); |
blendSegments(fromSeg, toSeg); |