summaryrefslogtreecommitdiffstats
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.cpp288
1 files changed, 288 insertions, 0 deletions
diff --git a/Source/WebCore/svg/SVGPathBlender.cpp b/Source/WebCore/svg/SVGPathBlender.cpp
new file mode 100644
index 0000000..d46e24a
--- /dev/null
+++ b/Source/WebCore/svg/SVGPathBlender.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPathBlender.h"
+
+#include "SVGPathSeg.h"
+
+namespace WebCore {
+
+SVGPathBlender::SVGPathBlender()
+ : m_fromSource(0)
+ , m_toSource(0)
+ , m_consumer(0)
+ , m_progress(0)
+{
+}
+
+float SVGPathBlender::blendAnimatedFloat(float from, float to)
+{
+ return (to - from) * m_progress + from;
+}
+
+FloatPoint SVGPathBlender::blendAnimatedFloatPoint(FloatPoint& from, FloatPoint& to)
+{
+ return FloatPoint((to.x() - from.x()) * m_progress + from.x(), (to.y() - from.y()) * m_progress + from.y());
+}
+
+bool SVGPathBlender::blendMoveToSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint toTargetPoint;
+ if (!m_fromSource->parseMoveToSegment(fromTargetPoint)
+ || !m_toSource->parseMoveToSegment(toTargetPoint))
+ return false;
+
+ m_consumer->moveTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), false, m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendLineToSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint toTargetPoint;
+ if (!m_fromSource->parseLineToSegment(fromTargetPoint)
+ || !m_toSource->parseLineToSegment(toTargetPoint))
+ return false;
+
+ m_consumer->lineTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendLineToHorizontalSegment()
+{
+ float fromX;
+ float toX;
+ if (!m_fromSource->parseLineToHorizontalSegment(fromX)
+ || !m_toSource->parseLineToHorizontalSegment(toX))
+ return false;
+
+ m_consumer->lineToHorizontal(blendAnimatedFloat(fromX, toX), m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendLineToVerticalSegment()
+{
+ float fromY;
+ float toY;
+ if (!m_fromSource->parseLineToVerticalSegment(fromY)
+ || !m_toSource->parseLineToVerticalSegment(toY))
+ return false;
+
+ m_consumer->lineToVertical(blendAnimatedFloat(fromY, toY), m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendCurveToCubicSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint fromPoint1;
+ FloatPoint fromPoint2;
+ FloatPoint toTargetPoint;
+ FloatPoint toPoint1;
+ FloatPoint toPoint2;
+ if (!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_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendCurveToCubicSmoothSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint fromPoint2;
+ FloatPoint toTargetPoint;
+ FloatPoint toPoint2;
+ if (!m_fromSource->parseCurveToCubicSmoothSegment(fromPoint2, fromTargetPoint)
+ || !m_toSource->parseCurveToCubicSmoothSegment(toPoint2, toTargetPoint))
+ return false;
+
+ m_consumer->curveToCubicSmooth(blendAnimatedFloatPoint(fromPoint2, toPoint2),
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
+ m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendCurveToQuadraticSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint fromPoint1;
+ FloatPoint toTargetPoint;
+ FloatPoint toPoint1;
+ if (!m_fromSource->parseCurveToQuadraticSegment(fromPoint1, fromTargetPoint)
+ || !m_toSource->parseCurveToQuadraticSegment(toPoint1, toTargetPoint))
+ return false;
+
+ m_consumer->curveToQuadratic(blendAnimatedFloatPoint(fromPoint1, toPoint1),
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
+ m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendCurveToQuadraticSmoothSegment()
+{
+ FloatPoint fromTargetPoint;
+ FloatPoint toTargetPoint;
+ if (!m_fromSource->parseCurveToQuadraticSmoothSegment(fromTargetPoint)
+ || !m_toSource->parseCurveToQuadraticSmoothSegment(toTargetPoint))
+ return false;
+
+ m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendArcToSegment()
+{
+ float fromRx;
+ float fromRy;
+ float fromAngle;
+ bool fromLargeArc;
+ bool fromSweep;
+ FloatPoint fromTargetPoint;
+ float toRx;
+ float toRy;
+ float toAngle;
+ bool toLargeArc;
+ bool toSweep;
+ FloatPoint toTargetPoint;
+ if (!m_fromSource->parseArcToSegment(fromRx, fromRy, fromAngle, fromLargeArc, fromSweep, fromTargetPoint)
+ || !m_toSource->parseArcToSegment(toRx, toRy, toAngle, toLargeArc, toSweep, toTargetPoint))
+ return false;
+
+ m_consumer->arcTo(blendAnimatedFloat(fromRx, toRx),
+ blendAnimatedFloat(fromRy, toRy),
+ blendAnimatedFloat(fromAngle, toAngle),
+ m_progress < 0.5 ? fromLargeArc : toLargeArc,
+ m_progress < 0.5 ? fromSweep : toSweep,
+ blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
+ m_mode);
+ return true;
+}
+
+bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource, SVGPathSource* toSource, SVGPathConsumer* consumer)
+{
+ ASSERT(fromSource);
+ ASSERT(toSource);
+ ASSERT(consumer);
+ m_fromSource = fromSource;
+ m_toSource = toSource;
+ m_consumer = consumer;
+
+ m_progress = progress;
+ while (true) {
+ SVGPathSegType fromCommand;
+ SVGPathSegType toCommand;
+ if (!m_fromSource->parseSVGSegmentType(fromCommand) || !m_toSource->parseSVGSegmentType(toCommand))
+ return false;
+ if (fromCommand != toCommand)
+ return false;
+
+ m_mode = AbsoluteCoordinates;
+ switch (fromCommand) {
+ case PathSegMoveToRel:
+ m_mode = RelativeCoordinates;
+ case PathSegMoveToAbs:
+ if (!blendMoveToSegment())
+ return false;
+ break;
+ case PathSegLineToRel:
+ m_mode = RelativeCoordinates;
+ case PathSegLineToAbs:
+ if (!blendLineToSegment())
+ return false;
+ break;
+ case PathSegLineToHorizontalRel:
+ m_mode = RelativeCoordinates;
+ case PathSegLineToHorizontalAbs:
+ if (!blendLineToHorizontalSegment())
+ return false;
+ break;
+ case PathSegLineToVerticalRel:
+ m_mode = RelativeCoordinates;
+ case PathSegLineToVerticalAbs:
+ if (!blendLineToVerticalSegment())
+ return false;
+ break;
+ case PathSegClosePath:
+ m_consumer->closePath();
+ break;
+ case PathSegCurveToCubicRel:
+ m_mode = RelativeCoordinates;
+ case PathSegCurveToCubicAbs:
+ if (!blendCurveToCubicSegment())
+ return false;
+ break;
+ case PathSegCurveToCubicSmoothRel:
+ m_mode = RelativeCoordinates;
+ case PathSegCurveToCubicSmoothAbs:
+ if (!blendCurveToCubicSmoothSegment())
+ return false;
+ break;
+ case PathSegCurveToQuadraticRel:
+ m_mode = RelativeCoordinates;
+ case PathSegCurveToQuadraticAbs:
+ if (!blendCurveToQuadraticSegment())
+ return false;
+ break;
+ case PathSegCurveToQuadraticSmoothRel:
+ m_mode = RelativeCoordinates;
+ case PathSegCurveToQuadraticSmoothAbs:
+ if (!blendCurveToQuadraticSmoothSegment())
+ return false;
+ break;
+ case PathSegArcRel:
+ m_mode = RelativeCoordinates;
+ case PathSegArcAbs:
+ if (!blendArcToSegment())
+ return false;
+ break;
+ default:
+ return false;
+ }
+ if (m_fromSource->hasMoreData() != m_toSource->hasMoreData())
+ return false;
+ if (!m_fromSource->hasMoreData() || !m_toSource->hasMoreData())
+ break;
+ }
+ return true;
+}
+
+void SVGPathBlender::cleanup()
+{
+ ASSERT(m_toSource);
+ ASSERT(m_fromSource);
+ ASSERT(m_consumer);
+
+ m_consumer->cleanup();
+ m_toSource = 0;
+ m_fromSource = 0;
+ m_consumer = 0;
+}
+
+}
+
+#endif // ENABLE(SVG)