Commit ae3e4f14 authored by antti@apple.com's avatar antti@apple.com

2008-04-17 Antti Koivisto <antti@apple.com>

        Reviewed by Eric.
        
        https://bugs.webkit.org/show_bug.cgi?id=12438

        More SVG animation:
        
        - Make multiple additive animations work
        - Support animating <use> instance trees

        * svg/SVGAnimateColorElement.cpp:
        (WebCore::SVGAnimateColorElement::SVGAnimateColorElement):
        * svg/SVGAnimateColorElement.h:
        
        Made this AnimateElement subclass. All functionality is now provided by AnimateElement.
        
        * svg/SVGAnimateElement.cpp:
        (WebCore::SVGAnimateElement::determinePropertyType):
        (WebCore::SVGAnimateElement::calculateAnimatedValue):
        (WebCore::SVGAnimateElement::calculateFromAndToValues):
        (WebCore::SVGAnimateElement::calculateFromAndByValues):
        (WebCore::SVGAnimateElement::resetToBaseValue):
        (WebCore::SVGAnimateElement::applyResultsToTarget):
        * svg/SVGAnimateElement.h:
        * svg/SVGAnimateMotionElement.cpp:
        (WebCore::SVGAnimateMotionElement::resetToBaseValue):
        (WebCore::SVGAnimateMotionElement::calculateAnimatedValue):
        (WebCore::SVGAnimateMotionElement::applyResultsToTarget):
        * svg/SVGAnimateMotionElement.h:
        * svg/SVGAnimateTransformElement.cpp:
        (WebCore::SVGAnimateTransformElement::resetToBaseValue):
        (WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
        (WebCore::SVGAnimateTransformElement::calculateFromAndByValues):
        (WebCore::SVGAnimateTransformElement::applyResultsToTarget):
        * svg/SVGAnimateTransformElement.h:
        
        Switch to new model where
        - resetToBaseValue() resets the animated value back to the base value
        - calculateAnimatedValue() computes the value and adds it to the element used for accumulation
        - applyResultsToTarget() sets the computed value the target element
        
        * svg/SVGAnimationElement.cpp:
        (WebCore::SVGAnimationElement::fromValue):
        (WebCore::SVGAnimationElement::attributeIsCSS):
        (WebCore::SVGAnimationElement::targetAttributeIsCSS):
        (WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue):
        
        Update instances too.
        
        (WebCore::SVGAnimationElement::startedActiveInterval):
        (WebCore::SVGAnimationElement::updateAnimation):
        (WebCore::SVGAnimationElement::endedActiveInterval):
        * svg/SVGAnimationElement.h:
        * svg/SVGSVGElement.cpp:
        (WebCore::SVGSVGElement::SVGSVGElement):
        * svg/SVGSetElement.cpp:
        (WebCore::SVGSetElement::SVGSetElement):
        * svg/SVGSetElement.h:
        
        Made this AnimateElement subclass. All functionality is now provided by AnimateElement.
        
        * svg/animation/SMILTimeContainer.cpp:
        (WebCore::SMILTimeContainer::SMILTimeContainer):
        (WebCore::SMILTimeContainer::unschedule):
        (WebCore::SMILTimeContainer::updateDocumentOrderIndexes):
        (WebCore::PriorityCompare::PriorityCompare):
        (WebCore::PriorityCompare::operator()):
        (WebCore::SMILTimeContainer::sortByPriority):
        (WebCore::applyOrderSortFunction):
        (WebCore::sortByApplyOrder):
        (WebCore::SMILTimeContainer::baseValueFor):
        (WebCore::SMILTimeContainer::updateAnimations):
        * svg/animation/SMILTimeContainer.h:
        (WebCore::SMILTimeContainer::create):
        (WebCore::SMILTimeContainer::setDocumentOrderIndexesDirty):
        
        Do additive animation with the following steps
        - sort active animations based on their priority (begin time, document order).
        - if not yet saved for each (element, attribute) pair save the base value.
        - lowest priority animation for each (element, attribute) acts as the result element.
        - animation results are resolved in priority order and results are accumulated to the result element.
        - after all active animations have been processed the values in result elements are applied to the target elements.
        
        * svg/animation/SVGSMILElement.cpp:
        (WebCore::SVGSMILElement::SVGSMILElement):
        (WebCore::SVGSMILElement::insertedIntoDocument):
        
        Invalidate document order index.
        
        (WebCore::SVGSMILElement::attributeName):
        (WebCore::SVGSMILElement::isInactive):
        (WebCore::SVGSMILElement::isFrozen):
        (WebCore::SVGSMILElement::beginListChanged):
        (WebCore::SVGSMILElement::determineActiveState):
        (WebCore::SVGSMILElement::isContributing):
        (WebCore::SVGSMILElement::progress):
        
        Take care that animations in frozen state still contribute to the total. Since we now build the result starting
        from the base value, fill="replace" works magically simply by not contributing anything.
        
        * svg/animation/SVGSMILElement.h:
        (WebCore::SVGSMILElement::previousIntervalBegin):
        (WebCore::SVGSMILElement::documentOrderIndex):
        (WebCore::SVGSMILElement::setDocumentOrderIndex):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@32044 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ebb8c990
2008-04-17 Antti Koivisto <antti@apple.com>
Reviewed by Eric.
https://bugs.webkit.org/show_bug.cgi?id=12438
More SVG animation:
- Make multiple additive animations work
- Support animating <use> instance trees
* svg/SVGAnimateColorElement.cpp:
(WebCore::SVGAnimateColorElement::SVGAnimateColorElement):
* svg/SVGAnimateColorElement.h:
Made this AnimateElement subclass. All functionality is now provided by AnimateElement.
* svg/SVGAnimateElement.cpp:
(WebCore::SVGAnimateElement::determinePropertyType):
(WebCore::SVGAnimateElement::calculateAnimatedValue):
(WebCore::SVGAnimateElement::calculateFromAndToValues):
(WebCore::SVGAnimateElement::calculateFromAndByValues):
(WebCore::SVGAnimateElement::resetToBaseValue):
(WebCore::SVGAnimateElement::applyResultsToTarget):
* svg/SVGAnimateElement.h:
* svg/SVGAnimateMotionElement.cpp:
(WebCore::SVGAnimateMotionElement::resetToBaseValue):
(WebCore::SVGAnimateMotionElement::calculateAnimatedValue):
(WebCore::SVGAnimateMotionElement::applyResultsToTarget):
* svg/SVGAnimateMotionElement.h:
* svg/SVGAnimateTransformElement.cpp:
(WebCore::SVGAnimateTransformElement::resetToBaseValue):
(WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
(WebCore::SVGAnimateTransformElement::calculateFromAndByValues):
(WebCore::SVGAnimateTransformElement::applyResultsToTarget):
* svg/SVGAnimateTransformElement.h:
Switch to new model where
- resetToBaseValue() resets the animated value back to the base value
- calculateAnimatedValue() computes the value and adds it to the element used for accumulation
- applyResultsToTarget() sets the computed value the target element
* svg/SVGAnimationElement.cpp:
(WebCore::SVGAnimationElement::fromValue):
(WebCore::SVGAnimationElement::attributeIsCSS):
(WebCore::SVGAnimationElement::targetAttributeIsCSS):
(WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue):
Update instances too.
(WebCore::SVGAnimationElement::startedActiveInterval):
(WebCore::SVGAnimationElement::updateAnimation):
(WebCore::SVGAnimationElement::endedActiveInterval):
* svg/SVGAnimationElement.h:
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::SVGSVGElement):
* svg/SVGSetElement.cpp:
(WebCore::SVGSetElement::SVGSetElement):
* svg/SVGSetElement.h:
Made this AnimateElement subclass. All functionality is now provided by AnimateElement.
* svg/animation/SMILTimeContainer.cpp:
(WebCore::SMILTimeContainer::SMILTimeContainer):
(WebCore::SMILTimeContainer::unschedule):
(WebCore::SMILTimeContainer::updateDocumentOrderIndexes):
(WebCore::PriorityCompare::PriorityCompare):
(WebCore::PriorityCompare::operator()):
(WebCore::SMILTimeContainer::sortByPriority):
(WebCore::applyOrderSortFunction):
(WebCore::sortByApplyOrder):
(WebCore::SMILTimeContainer::baseValueFor):
(WebCore::SMILTimeContainer::updateAnimations):
* svg/animation/SMILTimeContainer.h:
(WebCore::SMILTimeContainer::create):
(WebCore::SMILTimeContainer::setDocumentOrderIndexesDirty):
Do additive animation with the following steps
- sort active animations based on their priority (begin time, document order).
- if not yet saved for each (element, attribute) pair save the base value.
- lowest priority animation for each (element, attribute) acts as the result element.
- animation results are resolved in priority order and results are accumulated to the result element.
- after all active animations have been processed the values in result elements are applied to the target elements.
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::SVGSMILElement):
(WebCore::SVGSMILElement::insertedIntoDocument):
Invalidate document order index.
(WebCore::SVGSMILElement::attributeName):
(WebCore::SVGSMILElement::isInactive):
(WebCore::SVGSMILElement::isFrozen):
(WebCore::SVGSMILElement::beginListChanged):
(WebCore::SVGSMILElement::determineActiveState):
(WebCore::SVGSMILElement::isContributing):
(WebCore::SVGSMILElement::progress):
Take care that animations in frozen state still contribute to the total. Since we now build the result starting
from the base value, fill="replace" works magically simply by not contributing anything.
* svg/animation/SVGSMILElement.h:
(WebCore::SVGSMILElement::previousIntervalBegin):
(WebCore::SVGSMILElement::documentOrderIndex):
(WebCore::SVGSMILElement::setDocumentOrderIndex):
2008-04-17 Jon Honeycutt <jhoneycutt@apple.com>
Reviewed by mrowe.
......@@ -25,54 +25,11 @@
#if ENABLE(SVG_ANIMATION)
#include "SVGAnimateColorElement.h"
#include "Document.h"
#include "PlatformString.h"
#include "SVGColor.h"
#include "SVGSVGElement.h"
#include <math.h>
#include <wtf/MathExtras.h>
namespace WebCore {
// FIXME: This class needs to die. SVGAnimateElement (which has superset of the functionality) should be instantiated instead.
SVGAnimateColorElement::SVGAnimateColorElement(const QualifiedName& tagName, Document* doc)
: SVGAnimationElement(tagName, doc)
{
}
SVGAnimateColorElement::~SVGAnimateColorElement()
{
}
void SVGAnimateColorElement::applyAnimatedValueToElement(unsigned repeat)
{
if (isAdditive()) {
Color baseColor = SVGColor::colorFromRGBColorString(m_savedBaseValue);
setTargetAttributeAnimatedValue(ColorDistance::addColorsAndClamp(baseColor, m_animatedColor).name());
} else
setTargetAttributeAnimatedValue(m_animatedColor.name());
}
bool SVGAnimateColorElement::updateAnimatedValue(float percentage)
{
Color oldColor = m_animatedColor;
m_animatedColor = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentage).addToColorAndClamp(m_fromColor);
return m_animatedColor != oldColor;
}
bool SVGAnimateColorElement::calculateFromAndToValues(const String& fromString, const String& toString)
{
m_fromColor = SVGColor::colorFromRGBColorString(fromString);
m_toColor = SVGColor::colorFromRGBColorString(toString);
return true;
}
bool SVGAnimateColorElement::calculateFromAndByValues(const String& fromString, const String& byString)
: SVGAnimateElement(tagName, doc)
{
m_fromColor = SVGColor::colorFromRGBColorString(fromString);
m_toColor = ColorDistance::addColorsAndClamp(m_fromColor, SVGColor::colorFromRGBColorString(byString));
return true;
}
}
......
......@@ -25,32 +25,14 @@
#define SVGAnimateColorElement_h
#if ENABLE(SVG_ANIMATION)
#include "SVGAnimationElement.h"
#include "ColorDistance.h"
#include <wtf/RefPtr.h>
#include "SVGAnimateElement.h"
namespace WebCore {
class SVGColor;
class SVGAnimateColorElement : public SVGAnimationElement {
// SVGAnimateElement implements superset of the functionality.
class SVGAnimateColorElement : public SVGAnimateElement {
public:
SVGAnimateColorElement(const QualifiedName&, Document*);
virtual ~SVGAnimateColorElement();
protected:
virtual const SVGElement* contextElement() const { return this; }
virtual void applyAnimatedValueToElement(unsigned repeat);
virtual bool updateAnimatedValue(float percent);
virtual bool calculateFromAndToValues(const String& fromString, const String& toString);
virtual bool calculateFromAndByValues(const String& fromString, const String& byString);
private:
Color m_baseColor;
Color m_animatedColor;
Color m_toColor;
Color m_fromColor;
};
} // namespace WebCore
......
......@@ -72,76 +72,80 @@ static bool parseNumberValueAndUnit(const String& in, double& value, String& uni
return ok;
}
void SVGAnimateElement::applyAnimatedValueToElement(unsigned repeat)
SVGAnimateElement::PropertyType SVGAnimateElement::determinePropertyType(const String& attribute) const
{
// FIXME: This is entirely wrong way to do additive. It won't work with
// multiple animations on the same element.
// We need to add together all animation contributions per property and
// then apply in one go.
String valueToApply;
if (m_propertyType == NumberProperty) {
double number = m_animatedNumber;
// FIXME: This does not work for values animation.
if (isAccumulated() && repeat)
number += m_toNumber * repeat;
if (isAdditive()) {
double base;
if (!parseNumberValueAndUnit(m_savedBaseValue, base, m_numberUnit))
return;
number += base;
}
valueToApply = String::number(number) + m_numberUnit;
} else if (m_propertyType == ColorProperty) {
Color base = SVGColor::colorFromRGBColorString(m_savedBaseValue);
if (isAdditive())
valueToApply = ColorDistance::addColorsAndClamp(base, m_animatedColor).name();
else
valueToApply = m_animatedColor.name();
} else
valueToApply = m_animatedString;
setTargetAttributeAnimatedValue(valueToApply);
// FIXME: We need a full property table for figuring this out reliably.
if (hasTagName(SVGNames::animateColorTag))
return ColorProperty;
if (attribute == "color" || attribute == "fill" || attribute == "stroke")
return ColorProperty;
return NumberProperty;
}
bool SVGAnimateElement::updateAnimatedValue(float percentage)
void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
{
ASSERT(percentage >= 0.f && percentage <= 1.f);
ASSERT(resultElement);
if (hasTagName(SVGNames::setTag))
percentage = 1.f;
if (!resultElement->hasTagName(SVGNames::animateTag) && !resultElement->hasTagName(SVGNames::animateColorTag)
&& !resultElement->hasTagName(SVGNames::setTag))
return;
SVGAnimateElement* results = static_cast<SVGAnimateElement*>(resultElement);
// Can't accumulate over a string property.
if (results->m_propertyType == StringProperty && m_propertyType != StringProperty)
return;
if (m_propertyType == NumberProperty) {
double oldValue = m_animatedNumber;
m_animatedNumber = (m_toNumber - m_fromNumber) * percentage + m_fromNumber;
return oldValue == m_animatedNumber;
// To animation uses contributions from the lower priority animations as the base value.
if (animationMode() == ToAnimation)
m_fromNumber = results->m_animatedNumber;
double number = (m_toNumber - m_fromNumber) * percentage + m_fromNumber;
// FIXME: This is not correct for values animation.
if (isAccumulated() && repeat)
number += m_toNumber * repeat;
if (isAdditive() && animationMode() != ToAnimation)
results->m_animatedNumber += number;
else
results->m_animatedNumber = number;
return;
}
if (m_propertyType == ColorProperty) {
m_animatedColor = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentage).addToColorAndClamp(m_fromColor);
return true;
if (animationMode() == ToAnimation)
m_fromColor = results->m_animatedColor;
Color color = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentage).addToColorAndClamp(m_fromColor);
// FIXME: Accumulate colors.
if (isAdditive() && animationMode() != ToAnimation)
results->m_animatedColor = ColorDistance::addColorsAndClamp(results->m_animatedColor, color);
else
results->m_animatedColor = color;
return;
}
AnimationMode animationMode = this->animationMode();
ASSERT(animationMode == FromToAnimation || animationMode == ToAnimation || animationMode == ValuesAnimation);
String oldValue = m_animatedString;
if ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1.0f)
m_animatedString = m_toString;
results->m_animatedString = m_toString;
else
m_animatedString = m_fromString;
return oldValue == m_animatedString;
}
static bool isColorAttribute(const String& attribute)
{
return attribute == "color" || attribute == "fill" || attribute == "stroke";
results->m_animatedString = m_fromString;
// Higher priority replace animation overrides any additive results so far.
results->m_propertyType = StringProperty;
}
bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const String& toString)
{
// FIXME: Needs more solid way determine target attribute type.
m_propertyType = isColorAttribute(attributeName()) ? ColorProperty : NumberProperty;
m_propertyType = determinePropertyType(attributeName());
if (m_propertyType == ColorProperty) {
m_fromColor = SVGColor::colorFromRGBColorString(fromString);
m_toColor = SVGColor::colorFromRGBColorString(toString);
if (m_fromColor.isValid() && m_toColor.isValid())
return true;
} else {
} else if (m_propertyType == NumberProperty) {
m_numberUnit = String();
if (parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit)) {
if (parseNumberValueAndUnit(toString, m_toNumber, m_numberUnit))
if (parseNumberValueAndUnit(toString, m_toNumber, m_numberUnit)) {
// For to-animations the from number is calculated later
if (animationMode() == ToAnimation || parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
return true;
}
}
......@@ -153,7 +157,8 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const String& byString)
{
m_propertyType = isColorAttribute(attributeName()) ? ColorProperty : NumberProperty;
ASSERT(!hasTagName(SVGNames::setTag));
m_propertyType = determinePropertyType(attributeName());
if (m_propertyType == ColorProperty) {
m_fromColor = fromString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(fromString);
m_toColor = ColorDistance::addColorsAndClamp(m_fromColor, SVGColor::colorFromRGBColorString(byString));
......@@ -171,6 +176,39 @@ bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const
return true;
}
void SVGAnimateElement::resetToBaseValue(const String& baseString)
{
m_animatedString = baseString;
m_propertyType = determinePropertyType(attributeName());
if (m_propertyType == ColorProperty) {
m_animatedColor = baseString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(baseString);
if (m_animatedColor.isValid())
return;
} else if (m_propertyType == NumberProperty) {
if (baseString.isEmpty()) {
m_animatedNumber = 0;
m_numberUnit = String();
return;
}
if (parseNumberValueAndUnit(baseString, m_animatedNumber, m_numberUnit))
return;
}
m_propertyType = StringProperty;
}
void SVGAnimateElement::applyResultsToTarget()
{
String valueToApply;
if (m_propertyType == ColorProperty)
valueToApply = m_animatedColor.name();
else if (m_propertyType == NumberProperty)
valueToApply = String::number(m_animatedNumber) + m_numberUnit;
else
valueToApply = m_animatedString;
setTargetAttributeAnimatedValue(valueToApply);
}
}
// vim:ts=4:noet
......
......@@ -38,13 +38,15 @@ namespace WebCore {
protected:
virtual const SVGElement* contextElement() const { return this; }
virtual void resetToBaseValue(const String&);
virtual bool calculateFromAndToValues(const String& fromString, const String& toString);
virtual bool calculateFromAndByValues(const String& fromString, const String& byString);
virtual bool updateAnimatedValue(float percentage);
virtual void applyAnimatedValueToElement(unsigned repeat);
virtual void calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement);
virtual void applyResultsToTarget();
private:
enum PropertyType { NumberProperty, ColorProperty, StringProperty };
PropertyType determinePropertyType(const String& attribute) const;
PropertyType m_propertyType;
double m_fromNumber;
......
/*
Copyright (C) 2007 Eric Seidel <eric@webkit.org>
(C) 2007 Rob Buis <buis@kde.org>
Copyright (C) 2008 Apple Inc. All Rights Reserved.
This file is part of the WebKit project
......@@ -113,16 +114,6 @@ Path SVGAnimateMotionElement::animationPath()
return Path();
}
bool SVGAnimateMotionElement::updateAnimatedValue(float percentage)
{
FloatSize diff = m_toPoint - m_fromPoint;
m_animatedTranslation.setWidth(diff.width() * percentage + m_fromPoint.x());
m_animatedTranslation.setHeight(diff.height() * percentage + m_fromPoint.y());
// FIXME: Animate angles
m_animatedAngle = 0;
return true;
}
static bool parsePoint(const String& s, FloatPoint& point)
{
if (s.isEmpty())
......@@ -146,6 +137,16 @@ static bool parsePoint(const String& s, FloatPoint& point)
// disallow anything except spaces at the end
return !skipOptionalSpaces(cur, end);
}
void SVGAnimateMotionElement::resetToBaseValue(const String&)
{
if (!hasValidTarget())
return;
SVGStyledTransformableElement* transformableElement = static_cast<SVGStyledTransformableElement*>(targetElement());
// FIXME: This should modify supplemental transform, not the transform attribute!
ExceptionCode ec;
transformableElement->transform()->clear(ec);
}
bool SVGAnimateMotionElement::calculateFromAndToValues(const String& fromString, const String& toString)
{
......@@ -163,44 +164,40 @@ bool SVGAnimateMotionElement::calculateFromAndByValues(const String& fromString,
return true;
}
void SVGAnimateMotionElement::applyAnimatedValueToElement(unsigned repeat)
void SVGAnimateMotionElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
{
if (!targetElement()->isStyledTransformable())
if (!resultElement->targetElement()->isStyledTransformable())
return;
SVGStyledTransformableElement* transformableElement = static_cast<SVGStyledTransformableElement*>(targetElement());
// FIXME: This should modify supplemental transform, not the transform attribute!
SVGStyledTransformableElement* transformableElement = static_cast<SVGStyledTransformableElement*>(resultElement->targetElement());
RefPtr<SVGTransformList> transformList = transformableElement->transform();
if (!transformList)
return;
// FIXME: Handle multiple additive animations.
ExceptionCode ec;
if (isAdditive()) {
while (transformList->numberOfItems() > m_baseIndexInTransformList)
transformList->removeItem(transformList->numberOfItems() - 1, ec);
} else
if (!isAdditive()) {
ASSERT(this == resultElement);
transformList->clear(ec);
}
FloatSize diff = m_toPoint - m_fromPoint;
AffineTransform transform;
transform.rotate(m_animatedAngle);
transform.translate(m_animatedTranslation.width(), m_animatedTranslation.height());
if (!transform.isIdentity()) {
// FIXME: Animate angles
transform.translate(diff.width() * percentage + m_fromPoint.x(), diff.height() * percentage + m_fromPoint.y());
// FIXME: Accumulate.
if (!transform.isIdentity())
transformList->appendItem(SVGTransform(transform), ec);
transformableElement->setTransform(transformList.get());
}
if (transformableElement->renderer())
transformableElement->renderer()->setNeedsLayout(true); // should be part of setTransform
}
void SVGAnimateMotionElement::startedActiveInterval()
void SVGAnimateMotionElement::applyResultsToTarget()
{
// FIXME: Make multiple additive animations work.
SVGAnimationElement::startedActiveInterval();
if (!m_animationValid)
return;
SVGStyledTransformableElement* transformableElement = static_cast<SVGStyledTransformableElement*>(targetElement());
m_baseIndexInTransformList = transformableElement->transform()->numberOfItems();
}
}
......
/*
Copyright (C) 2007 Eric Seidel <eric@webkit.org>
Copyright (C) 2008 Apple Inc. All Rights Reserved.
This file is part of the WebKit project
......@@ -33,11 +34,9 @@ namespace WebCore {
public:
SVGAnimateMotionElement(const QualifiedName&, Document*);
virtual ~SVGAnimateMotionElement();
virtual bool hasValidTarget() const;
virtual void applyAnimatedValueToElement(unsigned repeat);
virtual void parseMappedAttribute(MappedAttribute*);
Path animationPath();
......@@ -45,11 +44,11 @@ namespace WebCore {
protected:
virtual const SVGElement* contextElement() const { return this; }
virtual bool updateAnimatedValue(float percent);
virtual void resetToBaseValue(const String&);
virtual bool calculateFromAndToValues(const String& fromString, const String& toString);
virtual bool calculateFromAndByValues(const String& fromString, const String& byString);
virtual void startedActiveInterval();
virtual void calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement);
virtual void applyResultsToTarget();
private:
FloatSize m_animatedTranslation;
......
......@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
Copyright (C) 2007 Eric Seidel <eric@webkit.org>
Copyright (C) 2008 Apple Inc. All Rights Reserved.
This file is part of the WebKit project
......@@ -28,12 +29,14 @@
#include "AffineTransform.h"
#include "RenderObject.h"
#include "SVGAngle.h"
#include "SVGElementInstance.h"
#include "SVGParserUtilities.h"
#include "SVGSVGElement.h"
#include "SVGStyledTransformableElement.h"
#include "SVGTextElement.h"
#include "SVGTransform.h"
#include "SVGTransformList.h"
#include "SVGUseElement.h"
#include <math.h>
#include <wtf/MathExtras.h>
......@@ -76,11 +79,6 @@ void SVGAnimateTransformElement::parseMappedAttribute(MappedAttribute* attr)
SVGAnimationElement::parseMappedAttribute(attr);
}
bool SVGAnimateTransformElement::updateAnimatedValue(float percentage)
{
m_animatedTransform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
return true;
}
static PassRefPtr<SVGTransformList> transformListFor(SVGElement* element)
{
......@@ -91,25 +89,36 @@ static PassRefPtr<SVGTransformList> transformListFor(SVGElement* element)
return static_cast<SVGTextElement*>(element)->transform();
return 0;
}
void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
{
if (!hasValidTarget())
return;
if (baseValue.isEmpty()) {
ExceptionCode ec;
RefPtr<SVGTransformList> list = transformListFor(targetElement());
list->clear(ec);
} else
targetElement()->setAttribute(SVGNames::transformAttr, baseValue);
}
void SVGAnimateTransformElement::applyAnimatedValueToElement(unsigned repeat)
void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
{
SVGElement* targetElement = this->targetElement();
if (!hasValidTarget())
return;
SVGElement* targetElement = resultElement->targetElement();
RefPtr<SVGTransformList> transformList = transformListFor(targetElement);
ASSERT(transformList);
// FIXME: Handle multiple additive tranforms.
// FIXME: Handle accumulate.
ExceptionCode ec;
if (isAdditive()) {
while (transformList->numberOfItems() > m_baseIndexInTransformList)
transformList->removeItem(transformList->numberOfItems() - 1, ec);
} else
if (!isAdditive())
transformList->clear(ec);
transformList->appendItem(m_animatedTransform, ec);
if (targetElement->renderer())
targetElement->renderer()->setNeedsLayout(true); // should really be in setTransform
if (isAccumulated() && repeat) {
SVGTransform accumulatedTransform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(repeat).addToSVGTransform(SVGTransform());
transformList->appendItem(accumulatedTransform, ec);
}
SVGTransform transform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
transformList->appendItem(transform, ec);
}
bool SVGAnimateTransformElement::calculateFromAndToValues(const String& fromString, const String& toString)
......@@ -130,18 +139,6 @@ bool SVGAnimateTransformElement::calculateFromAndByValues(const String& fromStri
m_toTransform = SVGTransformDistance::addSVGTransforms(m_fromTransform, parseTransformValue(byString));
return m_toTransform.isValid();
}