summaryrefslogtreecommitdiffstats
path: root/src/svg
diff options
context:
space:
mode:
authorSuneel BS <suneel.b-s@nokia.com>2009-05-14 15:22:15 +0530
committerKim Motoyoshi Kalland <kim.kalland@nokia.com>2009-08-20 15:18:27 +0200
commitbe6a9d6223b9a07a4563cfe63e54b93da959d8f4 (patch)
treefef09a0bf111f5b6d62dcb6faac6e60d1f831978 /src/svg
parenta2d224b36be8ea23e64273b0224d1c0aba9ca9ac (diff)
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
Diffstat (limited to 'src/svg')
-rw-r--r--src/svg/qsvghandler.cpp6
-rw-r--r--src/svg/qsvgstyle.cpp68
-rw-r--r--src/svg/qsvgstyle_p.h44
3 files changed, 99 insertions, 19 deletions
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<qreal> 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<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr;
- for (itr = animateTransforms.constBegin(); itr != animateTransforms.constEnd();
- ++itr) {
- (*itr)->apply(p, rect, node, states);
+ QList<QSvgRefCounter<QSvgAnimateTransform> >::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<QSvgRefCounter<QSvgAnimateTransform> >::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<qreal> &args)
+void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector<qreal> &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<qreal> &args);
+ void setArgs(TransformType type, Additive additive, const QVector<qreal> &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<qreal> 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;
};