KHTML
SVGAnimateTransformElement.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #if ENABLE(SVG) && ENABLE(SVG_ANIMATION)
00027 #include "SVGAnimateTransformElement.h"
00028
00029 #include "AffineTransform.h"
00030 #include "RenderObject.h"
00031 #include "SVGAngle.h"
00032 #include "SVGElementInstance.h"
00033 #include "SVGParserUtilities.h"
00034 #include "SVGSVGElement.h"
00035 #include "SVGStyledTransformableElement.h"
00036 #include "SVGTextElement.h"
00037 #include "SVGTransform.h"
00038 #include "SVGTransformList.h"
00039 #include "SVGUseElement.h"
00040
00041 #include <math.h>
00042 #include <wtf/MathExtras.h>
00043
00044 using namespace std;
00045
00046 namespace WebCore {
00047
00048 SVGAnimateTransformElement::SVGAnimateTransformElement(const QualifiedName& tagName, Document* doc)
00049 : SVGAnimationElement(tagName, doc)
00050 , m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN)
00051 , m_baseIndexInTransformList(0)
00052 {
00053 }
00054
00055 SVGAnimateTransformElement::~SVGAnimateTransformElement()
00056 {
00057 }
00058
00059 bool SVGAnimateTransformElement::hasValidTarget() const
00060 {
00061 SVGElement* targetElement = this->targetElement();
00062 return SVGAnimationElement::hasValidTarget() && (targetElement->isStyledTransformable() || targetElement->hasTagName(SVGNames::textTag));
00063 }
00064
00065 void SVGAnimateTransformElement::parseMappedAttribute(MappedAttribute* attr)
00066 {
00067 if (attr->name() == SVGNames::typeAttr) {
00068 if (attr->value() == "translate")
00069 m_type = SVGTransform::SVG_TRANSFORM_TRANSLATE;
00070 else if (attr->value() == "scale")
00071 m_type = SVGTransform::SVG_TRANSFORM_SCALE;
00072 else if (attr->value() == "rotate")
00073 m_type = SVGTransform::SVG_TRANSFORM_ROTATE;
00074 else if (attr->value() == "skewX")
00075 m_type = SVGTransform::SVG_TRANSFORM_SKEWX;
00076 else if (attr->value() == "skewY")
00077 m_type = SVGTransform::SVG_TRANSFORM_SKEWY;
00078 } else
00079 SVGAnimationElement::parseMappedAttribute(attr);
00080 }
00081
00082
00083 static PassRefPtr<SVGTransformList> transformListFor(SVGElement* element)
00084 {
00085 ASSERT(element);
00086 if (element->isStyledTransformable())
00087 return static_cast<SVGStyledTransformableElement*>(element)->transform();
00088 if (element->hasTagName(SVGNames::textTag))
00089 return static_cast<SVGTextElement*>(element)->transform();
00090 return 0;
00091 }
00092
00093 void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
00094 {
00095 if (!hasValidTarget())
00096 return;
00097 if (baseValue.isEmpty()) {
00098 ExceptionCode ec;
00099 RefPtr<SVGTransformList> list = transformListFor(targetElement());
00100 list->clear(ec);
00101 } else
00102 targetElement()->setAttribute(SVGNames::transformAttr, baseValue);
00103 }
00104
00105 void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
00106 {
00107 if (!hasValidTarget())
00108 return;
00109 SVGElement* targetElement = resultElement->targetElement();
00110 RefPtr<SVGTransformList> transformList = transformListFor(targetElement);
00111 ASSERT(transformList);
00112
00113 ExceptionCode ec;
00114 if (!isAdditive())
00115 transformList->clear(ec);
00116 if (isAccumulated() && repeat) {
00117 SVGTransform accumulatedTransform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(repeat).addToSVGTransform(SVGTransform());
00118 transformList->appendItem(accumulatedTransform, ec);
00119 }
00120 SVGTransform transform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
00121 transformList->appendItem(transform, ec);
00122 }
00123
00124 bool SVGAnimateTransformElement::calculateFromAndToValues(const String& fromString, const String& toString)
00125 {
00126 m_fromTransform = parseTransformValue(fromString);
00127 if (!m_fromTransform.isValid())
00128 return false;
00129 m_toTransform = parseTransformValue(toString);
00130 return m_toTransform.isValid();
00131 }
00132
00133 bool SVGAnimateTransformElement::calculateFromAndByValues(const String& fromString, const String& byString)
00134 {
00135
00136 m_fromTransform = parseTransformValue(fromString);
00137 if (!m_fromTransform.isValid())
00138 return false;
00139 m_toTransform = SVGTransformDistance::addSVGTransforms(m_fromTransform, parseTransformValue(byString));
00140 return m_toTransform.isValid();
00141 }
00142
00143 SVGTransform SVGAnimateTransformElement::parseTransformValue(const String& value) const
00144 {
00145 if (value.isEmpty())
00146 return SVGTransform(m_type);
00147 SVGTransform result;
00148
00149 String parseString("(" + value + ")");
00150 const UChar* ptr = parseString.characters();
00151 SVGTransformable::parseTransformValue(m_type, ptr, ptr + parseString.length(), result);
00152 return result;
00153 }
00154
00155 void SVGAnimateTransformElement::applyResultsToTarget()
00156 {
00157 if (!hasValidTarget())
00158 return;
00159
00160 SVGElement* targetElement = this->targetElement();
00161 if (targetElement->renderer())
00162 targetElement->renderer()->setNeedsLayout(true);
00163
00164
00165 HashSet<SVGElementInstance*>* instances = document()->accessSVGExtensions()->instancesForElement(targetElement);
00166 if (!instances)
00167 return;
00168 RefPtr<SVGTransformList> transformList = transformListFor(targetElement);
00169 HashSet<SVGElementInstance*>::iterator end = instances->end();
00170 for (HashSet<SVGElementInstance*>::iterator it = instances->begin(); it != end; ++it) {
00171 SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
00172 ASSERT(shadowTreeElement);
00173 if (shadowTreeElement->isStyledTransformable())
00174 static_cast<SVGStyledTransformableElement*>(shadowTreeElement)->setTransform(transformList.get());
00175 else if (shadowTreeElement->hasTagName(SVGNames::textTag))
00176 static_cast<SVGTextElement*>(shadowTreeElement)->setTransform(transformList.get());
00177 if (shadowTreeElement->renderer())
00178 shadowTreeElement->renderer()->setNeedsLayout(true);
00179 }
00180 }
00181
00182 float SVGAnimateTransformElement::calculateDistance(const String& fromString, const String& toString)
00183 {
00184
00185
00186 SVGTransform from = parseTransformValue(fromString);
00187 if (!from.isValid())
00188 return -1.f;
00189 SVGTransform to = parseTransformValue(toString);
00190 if (!to.isValid() || from.type() != to.type())
00191 return -1.f;
00192 if (to.type() == SVGTransform::SVG_TRANSFORM_TRANSLATE) {
00193 FloatSize diff = to.translate() - from.translate();
00194 return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
00195 }
00196 if (to.type() == SVGTransform::SVG_TRANSFORM_ROTATE)
00197 return fabsf(to.angle() - from.angle());
00198 if (to.type() == SVGTransform::SVG_TRANSFORM_SCALE) {
00199 FloatSize diff = to.scale() - from.scale();
00200 return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
00201 }
00202 return -1.f;
00203 }
00204
00205 }
00206
00207
00208 #endif // ENABLE(SVG)
00209