From be6a9d6223b9a07a4563cfe63e54b93da959d8f4 Mon Sep 17 00:00:00 2001 From: Suneel BS Date: Thu, 14 May 2009 15:22:15 +0530 Subject: Fix for SVG animate-transform when additive = "replace". On animate transform if additive = "replace" then transform specified with the element should be replaced with value of animateTransform. If additive = "sum" , then apply the animateTransform on top of element level transform. Reviewed-by: Kim --- src/svg/qsvghandler.cpp | 6 ++++- src/svg/qsvgstyle.cpp | 68 +++++++++++++++++++++++++++++++++++++------------ src/svg/qsvgstyle_p.h | 44 ++++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 19 deletions(-) (limited to 'src/svg') diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index a79e4a019d..2d07a1e379 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -2025,6 +2025,7 @@ static bool parseAnimateTransformNode(QSvgNode *parent, QString fillStr = attributes.value(QLatin1String("fill")).toString(); QString fromStr = attributes.value(QLatin1String("from")).toString(); QString toStr = attributes.value(QLatin1String("to")).toString(); + QString addtv = attributes.value(QLatin1String("additive")).toString(); QVector vals; if (values.isEmpty()) { @@ -2087,8 +2088,11 @@ static bool parseAnimateTransformNode(QSvgNode *parent, return false; } + QSvgAnimateTransform::Additive additive = QSvgAnimateTransform::Replace; + if (addtv == QLatin1String("sum")) + additive = QSvgAnimateTransform::Sum; QSvgAnimateTransform *anim = new QSvgAnimateTransform(begin, end, 0); - anim->setArgs(type, vals); + anim->setArgs(type, additive, vals); anim->setFreeze(fillStr == QLatin1String("freeze")); anim->setRepeatCount( (repeatStr == QLatin1String("indefinite"))? -1 : diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 1ecf870412..85d257f29b 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -509,10 +509,36 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra //animated transforms have to be applied //_after_ the original object transformations if (!animateTransforms.isEmpty()) { - QList >::const_iterator itr; - for (itr = animateTransforms.constBegin(); itr != animateTransforms.constEnd(); - ++itr) { - (*itr)->apply(p, rect, node, states); + QList >::const_iterator itr, temp, replace; + bool replaced = false; + qreal totalTimeElapsed = 0; + for (itr = animateTransforms.constBegin(); itr!= animateTransforms.constEnd(); ++itr) { + totalTimeElapsed = node->document()->currentElapsed(); + if ((totalTimeElapsed >= (*itr)->animStartTime()) && (!(*itr)->animFinished(totalTimeElapsed) || (*itr)->frozen())) { + if ((*itr)->additiveType() == QSvgAnimateTransform::Replace) { + if (!replaced) { + //set the flag to show replace is already encountered + //store the itr, which can be used if we encounter other animateTransform with additive = "replace" + replaced = true; + replace = itr; + //revert the first animateTransform with additive = "sum" + temp = animateTransforms.constBegin(); + if (temp != itr) + (*temp)->revert(p, states); + + //revert the transform if already applied + if (transform) + transform->revert(p, states); + } else { + //if animateTransform with additive = "replace" is encountered already + //then just revert that old animateTransform + (*replace)->revert(p,states); + replace = itr; //store the latest replace transform + } + } + (*itr)->apply(p, rect, node, states); + (*itr)->setTransformApplied(true); + } } } @@ -559,11 +585,23 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states) //the native transforms if (!animateTransforms.isEmpty()) { QList >::const_iterator itr; - itr = animateTransforms.constBegin(); - //only need to rever the first one because that - //one has the original world matrix for the primitve - if (itr != animateTransforms.constEnd()) { - (*itr)->revert(p, states); + bool reverted = false; + for (itr = animateTransforms.constEnd(); itr != animateTransforms.constBegin(); --itr) { + //if there is an animate transform with additive = "replace" + //then revert the last applied animateTransform with additive = "replace" + if (((*(itr-1))->transformApplied()) && ((*(itr-1))->additiveType() == QSvgAnimateTransform::Replace)) { + reverted = true; + (*(itr-1))->revert(p,states); + break; + } + } + //if there are no animateTransform with additive = "replace" then + //revert the first applied animateTransform with additive = "sum" + if (!reverted) { + while (itr != animateTransforms.constEnd() && !(*itr)->transformApplied()) + itr++; + if (itr != animateTransforms.constEnd()) + (*itr)->revert(p, states); } } @@ -587,15 +625,16 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states) QSvgAnimateTransform::QSvgAnimateTransform(int startMs, int endMs, int byMs ) : QSvgStyleProperty(), m_from(startMs), m_to(endMs), m_by(byMs), - m_type(Empty), m_count(0), m_finished(false) + m_type(Empty), m_count(0), m_finished(false), m_additive(Replace), m_transformApplied(false) { m_totalRunningTime = m_to - m_from; } -void QSvgAnimateTransform::setArgs(TransformType type, const QVector &args) +void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector &args) { m_type = type; m_args = args; + m_additive = additive; Q_ASSERT(!(args.count()%3)); m_count = args.count() / 3; } @@ -604,15 +643,12 @@ void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QS { m_oldWorldTransform = p->worldTransform(); resolveMatrix(node); - if (!m_finished || m_freeze) - p->setWorldTransform(m_transform, true); + p->setWorldTransform(m_transform, true); } void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) { - if (!m_finished || m_freeze) { - p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); - } + p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); } void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index c18a265be9..6f565741e0 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -250,7 +250,7 @@ public: { return m_style; } - + void setGradientId(const QString &Id) { m_gradientId = Id; @@ -529,20 +529,59 @@ public: SkewX, SkewY }; + enum Additive + { + Sum, + Replace + }; public: QSvgAnimateTransform(int startMs, int endMs, int by = 0); - void setArgs(TransformType type, const QVector &args); + void setArgs(TransformType type, Additive additive, const QVector &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; + QSvgAnimateTransform::Additive additiveType() const + { + return m_additive; + } + + bool animFinished(qreal totalTimeElapsed) + { + qreal animationFrame = (totalTimeElapsed - m_from) / m_to; + if (m_repeatCount >= 0 && m_repeatCount < animationFrame) + return true; + return false; + } + + qreal animStartTime() const + { + return m_from; + } + + void setTransformApplied(bool apply) + { + m_transformApplied = apply; + } + + bool transformApplied() const + { + return m_transformApplied; + } + + bool frozen() + { + return m_freeze; + } + protected: void resolveMatrix(QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; TransformType m_type; + Additive m_additive; QVector m_args; int m_count; QTransform m_transform; @@ -550,6 +589,7 @@ private: bool m_finished; bool m_freeze; qreal m_repeatCount; + bool m_transformApplied; }; -- cgit v1.2.3