summaryrefslogtreecommitdiff
path: root/Source/WebCore/svg/SVGPathBlender.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/svg/SVGPathBlender.cpp')
-rw-r--r--Source/WebCore/svg/SVGPathBlender.cpp331
1 files changed, 215 insertions, 116 deletions
diff --git a/Source/WebCore/svg/SVGPathBlender.cpp b/Source/WebCore/svg/SVGPathBlender.cpp
index 877d39896..8d2f636cf 100644
--- a/Source/WebCore/svg/SVGPathBlender.cpp
+++ b/Source/WebCore/svg/SVGPathBlender.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,24 +19,37 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGPathBlender.h"
#include "AnimationUtilities.h"
#include "SVGPathSeg.h"
#include "SVGPathSource.h"
-#include <wtf/TemporaryChange.h>
+#include <wtf/SetForScope.h>
namespace WebCore {
-SVGPathBlender::SVGPathBlender()
- : m_fromSource(0)
- , m_toSource(0)
- , m_consumer(0)
- , m_progress(0)
- , m_addTypesCount(0)
- , m_isInFirstHalfOfAnimation(false)
+bool SVGPathBlender::addAnimatedPath(SVGPathSource& fromSource, SVGPathSource& toSource, SVGPathConsumer& consumer, unsigned repeatCount)
+{
+ SVGPathBlender blender(fromSource, toSource, &consumer);
+ return blender.addAnimatedPath(repeatCount);
+}
+
+bool SVGPathBlender::blendAnimatedPath(SVGPathSource& fromSource, SVGPathSource& toSource, SVGPathConsumer& consumer, float progress)
+{
+ SVGPathBlender blender(fromSource, toSource, &consumer);
+ return blender.blendAnimatedPath(progress);
+}
+
+bool SVGPathBlender::canBlendPaths(SVGPathSource& fromSource, SVGPathSource& toSource)
+{
+ SVGPathBlender blender(fromSource, toSource);
+ return blender.canBlendPaths();
+}
+
+SVGPathBlender::SVGPathBlender(SVGPathSource& fromSource, SVGPathSource& toSource, SVGPathConsumer* consumer)
+ : m_fromSource(fromSource)
+ , m_toSource(toSource)
+ , m_consumer(consumer)
{
}
@@ -45,7 +59,7 @@ static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint&
return FloatPoint(blend(a.x(), b.x(), progress), blend(a.y(), b.y(), progress));
}
-float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBlendMode blendMode)
+float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBlendMode blendMode, float progress)
{
if (m_addTypesCount) {
ASSERT(m_fromMode == m_toMode);
@@ -53,33 +67,33 @@ float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBl
}
if (m_fromMode == m_toMode)
- return blend(from, to, m_progress);
+ return blend(from, to, 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_fromMode == AbsoluteCoordinates ? to + toValue : to - toValue, progress);
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);
+ float currentValue = blend(fromValue, toValue, progress);
return m_toMode == AbsoluteCoordinates ? animValue + currentValue : animValue - currentValue;
}
-FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint)
+FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint, float progress)
{
if (m_addTypesCount) {
ASSERT(m_fromMode == m_toMode);
FloatPoint repeatedToPoint = toPoint;
- repeatedToPoint.scale(m_addTypesCount, m_addTypesCount);
+ repeatedToPoint.scale(m_addTypesCount);
return fromPoint + repeatedToPoint;
}
if (m_fromMode == m_toMode)
- return blendFloatPoint(fromPoint, toPoint, m_progress);
+ return blendFloatPoint(fromPoint, toPoint, progress);
// Transform toPoint to the coordinate mode of fromPoint
FloatPoint animatedPoint = toPoint;
@@ -88,13 +102,13 @@ FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint,
else
animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y());
- animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress);
+ animatedPoint = blendFloatPoint(fromPoint, animatedPoint, progress);
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);
+ FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoint, progress);
if (m_toMode == AbsoluteCoordinates)
return animatedPoint + currentPoint;
@@ -102,63 +116,75 @@ FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint,
return animatedPoint;
}
-bool SVGPathBlender::blendMoveToSegment()
+bool SVGPathBlender::blendMoveToSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint toTargetPoint;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseMoveToSegment(fromTargetPoint))
- || !m_toSource->parseMoveToSegment(toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseMoveToSegment(fromTargetPoint))
+ || !m_toSource.parseMoveToSegment(toTargetPoint))
return false;
- m_consumer->moveTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), false, m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->moveTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress), false, m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendLineToSegment()
+bool SVGPathBlender::blendLineToSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint toTargetPoint;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseLineToSegment(fromTargetPoint))
- || !m_toSource->parseLineToSegment(toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseLineToSegment(fromTargetPoint))
+ || !m_toSource.parseLineToSegment(toTargetPoint))
return false;
- m_consumer->lineTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->lineTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendLineToHorizontalSegment()
+bool SVGPathBlender::blendLineToHorizontalSegment(float progress)
{
float fromX = 0;
float toX = 0;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseLineToHorizontalSegment(fromX))
- || !m_toSource->parseLineToHorizontalSegment(toX))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseLineToHorizontalSegment(fromX))
+ || !m_toSource.parseLineToHorizontalSegment(toX))
return false;
- m_consumer->lineToHorizontal(blendAnimatedDimensonalFloat(fromX, toX, BlendHorizontal), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->lineToHorizontal(blendAnimatedDimensonalFloat(fromX, toX, BlendHorizontal, progress), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint.setX(m_fromMode == AbsoluteCoordinates ? fromX : m_fromCurrentPoint.x() + fromX);
m_toCurrentPoint.setX(m_toMode == AbsoluteCoordinates ? toX : m_toCurrentPoint.x() + toX);
return true;
}
-bool SVGPathBlender::blendLineToVerticalSegment()
+bool SVGPathBlender::blendLineToVerticalSegment(float progress)
{
float fromY = 0;
float toY = 0;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseLineToVerticalSegment(fromY))
- || !m_toSource->parseLineToVerticalSegment(toY))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseLineToVerticalSegment(fromY))
+ || !m_toSource.parseLineToVerticalSegment(toY))
return false;
- m_consumer->lineToVertical(blendAnimatedDimensonalFloat(fromY, toY, BlendVertical), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->lineToVertical(blendAnimatedDimensonalFloat(fromY, toY, BlendVertical, progress), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint.setY(m_fromMode == AbsoluteCoordinates ? fromY : m_fromCurrentPoint.y() + fromY);
m_toCurrentPoint.setY(m_toMode == AbsoluteCoordinates ? toY : m_toCurrentPoint.y() + toY);
return true;
}
-bool SVGPathBlender::blendCurveToCubicSegment()
+bool SVGPathBlender::blendCurveToCubicSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint fromPoint1;
@@ -166,70 +192,82 @@ bool SVGPathBlender::blendCurveToCubicSegment()
FloatPoint toTargetPoint;
FloatPoint toPoint1;
FloatPoint toPoint2;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseCurveToCubicSegment(fromPoint1, fromPoint2, fromTargetPoint))
- || !m_toSource->parseCurveToCubicSegment(toPoint1, toPoint2, toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseCurveToCubicSegment(fromPoint1, fromPoint2, fromTargetPoint))
+ || !m_toSource.parseCurveToCubicSegment(toPoint1, toPoint2, toTargetPoint))
return false;
- m_consumer->curveToCubic(blendAnimatedFloatPoint(fromPoint1, toPoint1),
- blendAnimatedFloatPoint(fromPoint2, toPoint2),
- blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
- m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->curveToCubic(blendAnimatedFloatPoint(fromPoint1, toPoint1, progress),
+ blendAnimatedFloatPoint(fromPoint2, toPoint2, progress),
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress),
+ m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendCurveToCubicSmoothSegment()
+bool SVGPathBlender::blendCurveToCubicSmoothSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint fromPoint2;
FloatPoint toTargetPoint;
FloatPoint toPoint2;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseCurveToCubicSmoothSegment(fromPoint2, fromTargetPoint))
- || !m_toSource->parseCurveToCubicSmoothSegment(toPoint2, toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseCurveToCubicSmoothSegment(fromPoint2, fromTargetPoint))
+ || !m_toSource.parseCurveToCubicSmoothSegment(toPoint2, toTargetPoint))
return false;
- m_consumer->curveToCubicSmooth(blendAnimatedFloatPoint(fromPoint2, toPoint2),
- blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
- m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->curveToCubicSmooth(blendAnimatedFloatPoint(fromPoint2, toPoint2, progress),
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress),
+ m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendCurveToQuadraticSegment()
+bool SVGPathBlender::blendCurveToQuadraticSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint fromPoint1;
FloatPoint toTargetPoint;
FloatPoint toPoint1;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseCurveToQuadraticSegment(fromPoint1, fromTargetPoint))
- || !m_toSource->parseCurveToQuadraticSegment(toPoint1, toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseCurveToQuadraticSegment(fromPoint1, fromTargetPoint))
+ || !m_toSource.parseCurveToQuadraticSegment(toPoint1, toTargetPoint))
return false;
- m_consumer->curveToQuadratic(blendAnimatedFloatPoint(fromPoint1, toPoint1),
- blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
- m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->curveToQuadratic(blendAnimatedFloatPoint(fromPoint1, toPoint1, progress),
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress),
+ m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendCurveToQuadraticSmoothSegment()
+bool SVGPathBlender::blendCurveToQuadraticSmoothSegment(float progress)
{
FloatPoint fromTargetPoint;
FloatPoint toTargetPoint;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseCurveToQuadraticSmoothSegment(fromTargetPoint))
- || !m_toSource->parseCurveToQuadraticSmoothSegment(toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseCurveToQuadraticSmoothSegment(fromTargetPoint))
+ || !m_toSource.parseCurveToQuadraticSmoothSegment(toTargetPoint))
return false;
- m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ if (!m_consumer)
+ return true;
+
+ m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
return true;
}
-bool SVGPathBlender::blendArcToSegment()
+bool SVGPathBlender::blendArcToSegment(float progress)
{
float fromRx = 0;
float fromRy = 0;
@@ -243,29 +281,32 @@ bool SVGPathBlender::blendArcToSegment()
bool toLargeArc = false;
bool toSweep = false;
FloatPoint toTargetPoint;
- if ((m_fromSource->hasMoreData() && !m_fromSource->parseArcToSegment(fromRx, fromRy, fromAngle, fromLargeArc, fromSweep, fromTargetPoint))
- || !m_toSource->parseArcToSegment(toRx, toRy, toAngle, toLargeArc, toSweep, toTargetPoint))
+ if ((m_fromSource.hasMoreData() && !m_fromSource.parseArcToSegment(fromRx, fromRy, fromAngle, fromLargeArc, fromSweep, fromTargetPoint))
+ || !m_toSource.parseArcToSegment(toRx, toRy, toAngle, toLargeArc, toSweep, toTargetPoint))
return false;
+ if (!m_consumer)
+ return true;
+
if (m_addTypesCount) {
ASSERT(m_fromMode == m_toMode);
FloatPoint scaledToTargetPoint = toTargetPoint;
- scaledToTargetPoint.scale(m_addTypesCount, m_addTypesCount);
+ scaledToTargetPoint.scale(m_addTypesCount);
m_consumer->arcTo(fromRx + toRx * m_addTypesCount,
- fromRy + toRy * m_addTypesCount,
- fromAngle + toAngle * m_addTypesCount,
- fromLargeArc || toLargeArc,
- fromSweep || toSweep,
- fromTargetPoint + scaledToTargetPoint,
- m_fromMode);
+ fromRy + toRy * m_addTypesCount,
+ fromAngle + toAngle * m_addTypesCount,
+ fromLargeArc || toLargeArc,
+ fromSweep || toSweep,
+ fromTargetPoint + scaledToTargetPoint,
+ m_fromMode);
} else {
- m_consumer->arcTo(blend(fromRx, toRx, m_progress),
- blend(fromRy, toRy, m_progress),
- blend(fromAngle, toAngle, m_progress),
- m_isInFirstHalfOfAnimation ? fromLargeArc : toLargeArc,
- m_isInFirstHalfOfAnimation ? fromSweep : toSweep,
- blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
- m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+ m_consumer->arcTo(blend(fromRx, toRx, progress),
+ blend(fromRy, toRy, progress),
+ blend(fromAngle, toAngle, progress),
+ m_isInFirstHalfOfAnimation ? fromLargeArc : toLargeArc,
+ m_isInFirstHalfOfAnimation ? fromSweep : toSweep,
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint, progress),
+ m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
}
m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
@@ -298,28 +339,20 @@ static inline bool isSegmentEqual(const SVGPathSegType& fromType, const SVGPathS
return to == from - 1;
}
-bool SVGPathBlender::addAnimatedPath(SVGPathSource* fromSource, SVGPathSource* toSource, SVGPathConsumer* consumer, unsigned repeatCount)
+bool SVGPathBlender::addAnimatedPath(unsigned repeatCount)
{
- TemporaryChange<unsigned> change(m_addTypesCount, repeatCount);
- return blendAnimatedPath(0, fromSource, toSource, consumer);
+ SetForScope<unsigned> change(m_addTypesCount, repeatCount);
+ return blendAnimatedPath(0);
}
-bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource, SVGPathSource* toSource, SVGPathConsumer* consumer)
+bool SVGPathBlender::canBlendPaths()
{
- ASSERT(fromSource);
- ASSERT(toSource);
- ASSERT(consumer);
- m_fromSource = fromSource;
- m_toSource = toSource;
- m_consumer = consumer;
- m_isInFirstHalfOfAnimation = progress < 0.5f;
- m_progress = progress;
-
- bool fromSourceHadData = m_fromSource->hasMoreData();
- while (m_toSource->hasMoreData()) {
+ float progress = 0.5;
+ bool fromSourceHadData = m_fromSource.hasMoreData();
+ while (m_toSource.hasMoreData()) {
SVGPathSegType fromCommand;
SVGPathSegType toCommand;
- if ((fromSourceHadData && !m_fromSource->parseSVGSegmentType(fromCommand)) || !m_toSource->parseSVGSegmentType(toCommand))
+ if ((fromSourceHadData && !m_fromSource.parseSVGSegmentType(fromCommand)) || !m_toSource.parseSVGSegmentType(toCommand))
return false;
m_toMode = coordinateModeOfCommand(toCommand);
@@ -333,50 +366,49 @@ bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource
switch (toCommand) {
case PathSegMoveToRel:
case PathSegMoveToAbs:
- if (!blendMoveToSegment())
+ if (!blendMoveToSegment(progress))
return false;
break;
case PathSegLineToRel:
case PathSegLineToAbs:
- if (!blendLineToSegment())
+ if (!blendLineToSegment(progress))
return false;
break;
case PathSegLineToHorizontalRel:
case PathSegLineToHorizontalAbs:
- if (!blendLineToHorizontalSegment())
+ if (!blendLineToHorizontalSegment(progress))
return false;
break;
case PathSegLineToVerticalRel:
case PathSegLineToVerticalAbs:
- if (!blendLineToVerticalSegment())
+ if (!blendLineToVerticalSegment(progress))
return false;
break;
case PathSegClosePath:
- m_consumer->closePath();
break;
case PathSegCurveToCubicRel:
case PathSegCurveToCubicAbs:
- if (!blendCurveToCubicSegment())
+ if (!blendCurveToCubicSegment(progress))
return false;
break;
case PathSegCurveToCubicSmoothRel:
case PathSegCurveToCubicSmoothAbs:
- if (!blendCurveToCubicSmoothSegment())
+ if (!blendCurveToCubicSmoothSegment(progress))
return false;
break;
case PathSegCurveToQuadraticRel:
case PathSegCurveToQuadraticAbs:
- if (!blendCurveToQuadraticSegment())
+ if (!blendCurveToQuadraticSegment(progress))
return false;
break;
case PathSegCurveToQuadraticSmoothRel:
case PathSegCurveToQuadraticSmoothAbs:
- if (!blendCurveToQuadraticSmoothSegment())
+ if (!blendCurveToQuadraticSmoothSegment(progress))
return false;
break;
case PathSegArcRel:
case PathSegArcAbs:
- if (!blendArcToSegment())
+ if (!blendArcToSegment(progress))
return false;
break;
case PathSegUnknown:
@@ -385,29 +417,96 @@ bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource
if (!fromSourceHadData)
continue;
- if (m_fromSource->hasMoreData() != m_toSource->hasMoreData())
+ if (m_fromSource.hasMoreData() != m_toSource.hasMoreData())
return false;
- if (!m_fromSource->hasMoreData() || !m_toSource->hasMoreData())
+ if (!m_fromSource.hasMoreData() || !m_toSource.hasMoreData())
return true;
}
return true;
}
-void SVGPathBlender::cleanup()
+bool SVGPathBlender::blendAnimatedPath(float progress)
{
- ASSERT(m_toSource);
- ASSERT(m_fromSource);
- ASSERT(m_consumer);
-
- m_consumer->cleanup();
- m_toSource = 0;
- m_fromSource = 0;
- m_consumer = 0;
- m_fromCurrentPoint = FloatPoint();
- m_toCurrentPoint = FloatPoint();
-}
+ m_isInFirstHalfOfAnimation = progress < 0.5f;
+
+ bool fromSourceHadData = m_fromSource.hasMoreData();
+ while (m_toSource.hasMoreData()) {
+ SVGPathSegType fromCommand;
+ SVGPathSegType toCommand;
+ if ((fromSourceHadData && !m_fromSource.parseSVGSegmentType(fromCommand)) || !m_toSource.parseSVGSegmentType(toCommand))
+ return false;
+ m_toMode = coordinateModeOfCommand(toCommand);
+ m_fromMode = fromSourceHadData ? coordinateModeOfCommand(fromCommand) : m_toMode;
+ if (m_fromMode != m_toMode && m_addTypesCount)
+ return false;
+
+ if (fromSourceHadData && !isSegmentEqual(fromCommand, toCommand, m_fromMode, m_toMode))
+ return false;
+
+ switch (toCommand) {
+ case PathSegMoveToRel:
+ case PathSegMoveToAbs:
+ if (!blendMoveToSegment(progress))
+ return false;
+ break;
+ case PathSegLineToRel:
+ case PathSegLineToAbs:
+ if (!blendLineToSegment(progress))
+ return false;
+ break;
+ case PathSegLineToHorizontalRel:
+ case PathSegLineToHorizontalAbs:
+ if (!blendLineToHorizontalSegment(progress))
+ return false;
+ break;
+ case PathSegLineToVerticalRel:
+ case PathSegLineToVerticalAbs:
+ if (!blendLineToVerticalSegment(progress))
+ return false;
+ break;
+ case PathSegClosePath:
+ m_consumer->closePath();
+ break;
+ case PathSegCurveToCubicRel:
+ case PathSegCurveToCubicAbs:
+ if (!blendCurveToCubicSegment(progress))
+ return false;
+ break;
+ case PathSegCurveToCubicSmoothRel:
+ case PathSegCurveToCubicSmoothAbs:
+ if (!blendCurveToCubicSmoothSegment(progress))
+ return false;
+ break;
+ case PathSegCurveToQuadraticRel:
+ case PathSegCurveToQuadraticAbs:
+ if (!blendCurveToQuadraticSegment(progress))
+ return false;
+ break;
+ case PathSegCurveToQuadraticSmoothRel:
+ case PathSegCurveToQuadraticSmoothAbs:
+ if (!blendCurveToQuadraticSmoothSegment(progress))
+ return false;
+ break;
+ case PathSegArcRel:
+ case PathSegArcAbs:
+ if (!blendArcToSegment(progress))
+ return false;
+ break;
+ case PathSegUnknown:
+ return false;
+ }
+
+ if (!fromSourceHadData)
+ continue;
+ if (m_fromSource.hasMoreData() != m_toSource.hasMoreData())
+ return false;
+ if (!m_fromSource.hasMoreData() || !m_toSource.hasMoreData())
+ return true;
+ }
+
+ return true;
}
-#endif // ENABLE(SVG)
+}