25#if ENABLE(SVG) && ENABLE(SVG_ANIMATION)
38using namespace SVGNames;
40SVGAnimateMotionElement::SVGAnimateMotionElement(
const QualifiedName& tagName, Document* doc)
41 : SVGAnimationElement(tagName, doc)
42 , m_baseIndexInTransformList(0)
47SVGAnimateMotionElement::~SVGAnimateMotionElement()
51bool SVGAnimateMotionElement::hasValidTarget()
const
53 if (!SVGAnimationElement::hasValidTarget())
55 SVGElement* targetElement = this->targetElement();
56 if (!targetElement->isStyledTransformable() && !targetElement->hasTagName(SVGNames::textTag))
59 if (targetElement->hasTagName(gTag)
60 || targetElement->hasTagName(defsTag)
61 || targetElement->hasTagName(useTag)
62 || targetElement->hasTagName(imageTag)
63 || targetElement->hasTagName(switchTag)
64 || targetElement->hasTagName(pathTag)
65 || targetElement->hasTagName(rectTag)
66 || targetElement->hasTagName(circleTag)
67 || targetElement->hasTagName(ellipseTag)
68 || targetElement->hasTagName(lineTag)
69 || targetElement->hasTagName(polylineTag)
70 || targetElement->hasTagName(polygonTag)
71 || targetElement->hasTagName(textTag)
72 || targetElement->hasTagName(clipPathTag)
73 || targetElement->hasTagName(maskTag)
74 || targetElement->hasTagName(aTag)
75#
if ENABLE(SVG_FOREIGN_OBJECT)
76 || targetElement->hasTagName(foreignObjectTag)
83void SVGAnimateMotionElement::parseMappedAttribute(MappedAttribute* attr)
85 if (attr->name() == SVGNames::pathAttr) {
87 pathFromSVGData(m_path, attr->value());
89 SVGAnimationElement::parseMappedAttribute(attr);
92SVGAnimateMotionElement::RotateMode SVGAnimateMotionElement::rotateMode()
const
94 static const AtomicString autoVal(
"auto");
95 static const AtomicString autoReverse(
"auto-reverse");
96 String rotate = getAttribute(SVGNames::rotateAttr);
97 if (rotate == autoVal)
99 if (rotate == autoReverse)
100 return RotateAutoReverse;
104Path SVGAnimateMotionElement::animationPath()
const
106 for (Node* child = firstChild(); child; child = child->nextSibling()) {
107 if (child->hasTagName(SVGNames::mpathTag)) {
108 SVGMPathElement* mPath =
static_cast<SVGMPathElement*
>(child);
109 SVGPathElement* pathElement = mPath->pathElement();
111 return pathElement->toPathData();
115 if (hasAttribute(SVGNames::pathAttr))
120static bool parsePoint(
const String& s, FloatPoint& point)
124 const UChar* cur = s.characters();
125 const UChar*
end = cur + s.length();
127 if (!skipOptionalSpaces(cur, end))
131 if (!parseNumber(cur, end, x))
135 if (!parseNumber(cur, end, y))
138 point = FloatPoint(x, y);
141 return !skipOptionalSpaces(cur, end);
144void SVGAnimateMotionElement::resetToBaseValue(
const String&)
146 if (!hasValidTarget())
148 SVGElement* target = targetElement();
149 AffineTransform* transform = target->supplementalTransform();
155bool SVGAnimateMotionElement::calculateFromAndToValues(
const String& fromString,
const String& toString)
157 parsePoint(fromString, m_fromPoint);
158 parsePoint(toString, m_toPoint);
162bool SVGAnimateMotionElement::calculateFromAndByValues(
const String& fromString,
const String& byString)
164 parsePoint(fromString, m_fromPoint);
166 parsePoint(byString, byPoint);
167 m_toPoint = FloatPoint(m_fromPoint.x() + byPoint.x(), m_fromPoint.y() + byPoint.y());
171void SVGAnimateMotionElement::calculateAnimatedValue(
float percentage,
unsigned repeat, SVGSMILElement*)
173 SVGElement* target = targetElement();
176 AffineTransform* transform = target->supplementalTransform();
185 if (animationMode() == PathAnimation) {
186 ASSERT(!animationPath().isEmpty());
187 Path path = animationPath();
188 float positionOnPath = path.length() * percentage;
190 FloatPoint position = path.pointAtLength(positionOnPath, ok);
192 transform->translate(position.x(), position.y());
193 RotateMode rotateMode = this->rotateMode();
194 if (rotateMode == RotateAuto || rotateMode == RotateAutoReverse) {
195 float angle = path.normalAngleAtLength(positionOnPath, ok);
196 if (rotateMode == RotateAutoReverse)
198 transform->rotate(angle);
203 FloatSize diff = m_toPoint - m_fromPoint;
204 transform->translate(diff.width() * percentage + m_fromPoint.x(), diff.height() * percentage + m_fromPoint.y());
207void SVGAnimateMotionElement::applyResultsToTarget()
210 SVGElement* targetElement = this->targetElement();
211 if (targetElement && targetElement->renderer())
212 targetElement->renderer()->setNeedsLayout(
true);
215 HashSet<SVGElementInstance*>* instances = document()->accessSVGExtensions()->instancesForElement(targetElement);
218 HashSet<SVGElementInstance*>::iterator
end = instances->end();
219 for (HashSet<SVGElementInstance*>::iterator it = instances->begin(); it != end; ++it) {
220 SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
221 ASSERT(shadowTreeElement);
222 AffineTransform* transform = shadowTreeElement->supplementalTransform();
223 AffineTransform* t = targetElement->supplementalTransform();
224 transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f());
225 if (shadowTreeElement->renderer())
226 shadowTreeElement->renderer()->setNeedsLayout(
true);
230float SVGAnimateMotionElement::calculateDistance(
const String& fromString,
const String& toString)
234 if (!parsePoint(fromString, from))
236 if (!parsePoint(toString, to))
238 FloatSize diff = to - from;
239 return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());