Commit 54eebebc authored by antti@apple.com's avatar antti@apple.com

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

        Reviewed by Eric.

        Some preparations for additive animations and animations in <use>.
        - Disallow animation elements in instance trees.
        - Fix buggy SVGUseElement::removeDisallowedElementsFromSubtree(), make it 
          public and static
        - Invoke it from SVGElementInstance::updateInstance() to clean up the instance tree
          there as well.
        - Add mechanism for blocking instance updates when an animation changes
          the referenced tree.
        
        The added assert in SVGSMILElement::insertedIntoDocument() verifies the fixes
        with the existing test cases.

        * svg/SVGAElement.cpp:
        (WebCore::SVGAElement::defaultEventHandler):
        * svg/SVGElementInstance.cpp:
        (WebCore::SVGElementInstance::updateInstance):
        * svg/SVGStyledElement.cpp:
        (WebCore::SVGStyledElement::updateElementInstance):
        (WebCore::SVGStyledElement::setInstanceUpdatesBlocked):
        * svg/SVGStyledElement.h:
        * svg/SVGUseElement.cpp:
        (WebCore::isDisallowedElement):
        (WebCore::SVGUseElement::removeDisallowedElementsFromSubtree):
        * svg/SVGUseElement.h:
        * svg/animation/SVGSMILElement.cpp:
        (WebCore::SVGSMILElement::insertedIntoDocument):
        (WebCore::SVGSMILElement::isSMILElement):
        (WebCore::SVGSMILElement::connectConditions):
        (WebCore::SVGSMILElement::disconnectConditions):
        * svg/animation/SVGSMILElement.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31891 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 222d7489
2008-04-14 Antti Koivisto <antti@apple.com>
Reviewed by Eric.
Some preparations for additive animations and animations in <use>.
- Disallow animation elements in instance trees.
- Fix buggy SVGUseElement::removeDisallowedElementsFromSubtree(), make it
public and static
- Invoke it from SVGElementInstance::updateInstance() to clean up the instance tree
there as well.
- Add mechanism for blocking instance updates when an animation changes
the referenced tree.
The added assert in SVGSMILElement::insertedIntoDocument() verifies the fixes
with the existing test cases.
* svg/SVGAElement.cpp:
(WebCore::SVGAElement::defaultEventHandler):
* svg/SVGElementInstance.cpp:
(WebCore::SVGElementInstance::updateInstance):
* svg/SVGStyledElement.cpp:
(WebCore::SVGStyledElement::updateElementInstance):
(WebCore::SVGStyledElement::setInstanceUpdatesBlocked):
* svg/SVGStyledElement.h:
* svg/SVGUseElement.cpp:
(WebCore::isDisallowedElement):
(WebCore::SVGUseElement::removeDisallowedElementsFromSubtree):
* svg/SVGUseElement.h:
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::insertedIntoDocument):
(WebCore::SVGSMILElement::isSMILElement):
(WebCore::SVGSMILElement::connectConditions):
(WebCore::SVGSMILElement::disconnectConditions):
* svg/animation/SVGSMILElement.h:
2008-04-14 Adam Roben <aroben@apple.com>
Don't let the inspected page overwrite properties of JS objects in the
......@@ -144,7 +144,7 @@ void SVGAElement::defaultEventHandler(Event* evt)
#if ENABLE(SVG_ANIMATION)
if (url.startsWith("#")) {
Element* targetElement = document()->getElementById(url.substring(1));
if (SVGSMILElement::isTimingElement(targetElement)) {
if (SVGSMILElement::isSMILElement(targetElement)) {
SVGSMILElement* timed = static_cast<SVGSMILElement*>(targetElement);
timed->beginByLinkActivation();
evt->setDefaultHandled();
......
......@@ -162,6 +162,7 @@ void SVGElementInstance::updateInstance(SVGElement* element)
// For all other nodes this logic is sufficient.
RefPtr<Node> clone = m_element->cloneNode(true);
SVGUseElement::removeDisallowedElementsFromSubtree(clone.get());
SVGElement* svgClone = 0;
if (clone && clone->isSVGElement())
svgClone = static_cast<SVGElement*>(clone.get());
......
......@@ -42,6 +42,8 @@ namespace WebCore {
using namespace SVGNames;
static HashSet<const SVGStyledElement*>* gElementsWithInstanceUpdatesBlocked = 0;
SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc)
: SVGElement(tagName, doc)
{
......@@ -236,6 +238,9 @@ void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange,
void SVGStyledElement::updateElementInstance(SVGDocumentExtensions* extensions) const
{
if (gElementsWithInstanceUpdatesBlocked && gElementsWithInstanceUpdatesBlocked->contains(this))
return;
SVGStyledElement* nonConstThis = const_cast<SVGStyledElement*>(this);
HashSet<SVGElementInstance*>* set = extensions->instancesForElement(nonConstThis);
if (!set || set->isEmpty())
......@@ -285,6 +290,19 @@ void SVGStyledElement::detach()
SVGElement::detach();
}
void SVGStyledElement::setInstanceUpdatesBlocked(bool blockUpdates)
{
if (blockUpdates) {
if (!gElementsWithInstanceUpdatesBlocked)
gElementsWithInstanceUpdatesBlocked = new HashSet<const SVGStyledElement*>;
gElementsWithInstanceUpdatesBlocked->add(this);
} else {
ASSERT(gElementsWithInstanceUpdatesBlocked);
ASSERT(gElementsWithInstanceUpdatesBlocked->contains(this));
gElementsWithInstanceUpdatesBlocked->remove(this);
}
}
}
#endif // ENABLE(SVG)
......@@ -62,6 +62,8 @@ namespace WebCore {
void invalidateResourcesInAncestorChain() const;
virtual void detach();
void setInstanceUpdatesBlocked(bool);
protected:
virtual bool hasRelativeValues() const { return true; }
......
......@@ -43,6 +43,7 @@
#include "SVGLength.h"
#include "SVGNames.h"
#include "SVGPreserveAspectRatio.h"
#include "SVGSMILElement.h"
#include "SVGSVGElement.h"
#include "SVGSymbolElement.h"
#include "XLinkNames.h"
......@@ -227,6 +228,10 @@ static bool isDisallowedElement(Node* element)
if (element->hasTagName(SVGNames::foreignObjectTag))
return true;
#endif
#if ENABLE(SVG_ANIMATION)
if (SVGSMILElement::isSMILElement(element))
return true;
#endif
return false;
}
......@@ -505,21 +510,19 @@ void SVGUseElement::alterShadowTreeForSVGTag(SVGElement* target)
target->setAttribute(SVGNames::heightAttr, heightString);
}
void SVGUseElement::removeDisallowedElementsFromSubtree(Node* element)
void SVGUseElement::removeDisallowedElementsFromSubtree(Node* subtree)
{
ExceptionCode ec = 0;
for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling()) {
if (isDisallowedElement(child.get())) {
ASSERT(child->parent());
child->parent()->removeChild(child.get(), ec);
ASSERT(ec == 0);
continue;
}
if (child->hasChildNodes())
removeDisallowedElementsFromSubtree(child.get());
ASSERT(!subtree->inDocument());
ExceptionCode ec;
Node* node = subtree->firstChild();
while (node) {
if (isDisallowedElement(node)) {
Node* next = node->traverseNextSibling(subtree);
// The subtree is not in document so this won't generate events that could mutate the tree.
node->parent()->removeChild(node, ec);
node = next;
} else
node = node->traverseNextNode(subtree);
}
}
......
......@@ -65,6 +65,8 @@ namespace WebCore {
virtual Path toClipPath() const;
static void removeDisallowedElementsFromSubtree(Node* element);
protected:
virtual const SVGElement* contextElement() const { return this; }
......@@ -89,7 +91,6 @@ namespace WebCore {
// Shadow tree handling
PassRefPtr<SVGSVGElement> buildShadowTreeForSymbolTag(SVGElement* target, SVGElementInstance* targetInstance);
void alterShadowTreeForSVGTag(SVGElement* target);
void removeDisallowedElementsFromSubtree(Node* element);
void buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance);
......
......@@ -101,6 +101,11 @@ SVGSMILElement::~SVGSMILElement()
void SVGSMILElement::insertedIntoDocument()
{
SVGElement::insertedIntoDocument();
#ifndef NDEBUG
// Verify we are not in <use> instance tree.
for (Node* n = this; n; n = n->parent())
ASSERT(!n->isShadowNode());
#endif
SVGSVGElement* owner = ownerSVGElement();
if (!owner)
return;
......@@ -265,12 +270,12 @@ bool SVGSMILElement::parseCondition(const String& value, BeginOrEnd beginOrEnd)
return true;
}
bool SVGSMILElement::isTimingElement(Element* element)
bool SVGSMILElement::isSMILElement(Node* node)
{
if (!element)
if (!node)
return false;
return element->hasTagName(SVGNames::setTag) || element->hasTagName(SVGNames::animateTag) || element->hasTagName(SVGNames::animateMotionTag)
|| element->hasTagName(SVGNames::animateTransformTag) || element->hasTagName(SVGNames::animateColorTag);
return node->hasTagName(SVGNames::setTag) || node->hasTagName(SVGNames::animateTag) || node->hasTagName(SVGNames::animateMotionTag)
|| node->hasTagName(SVGNames::animateTransformTag) || node->hasTagName(SVGNames::animateColorTag);
}
void SVGSMILElement::parseBeginOrEnd(const String& parseString, BeginOrEnd beginOrEnd)
......@@ -361,7 +366,7 @@ void SVGSMILElement::connectConditions()
} else if (condition.m_type == Condition::Syncbase) {
ASSERT(!condition.m_baseID.isEmpty());
condition.m_base = document()->getElementById(condition.m_baseID);
if (!isTimingElement(condition.m_base.get())) {
if (!isSMILElement(condition.m_base.get())) {
condition.m_base = 0;
continue;
}
......@@ -384,7 +389,7 @@ void SVGSMILElement::disconnectConditions()
condition.m_eventListener = 0;
} else if (condition.m_type == Condition::Syncbase) {
if (condition.m_base) {
ASSERT(isTimingElement(condition.m_base.get()));
ASSERT(isSMILElement(condition.m_base.get()));
static_cast<SVGSMILElement*>(condition.m_base.get())->removeTimeDependent(this);
}
}
......
......@@ -44,7 +44,7 @@ namespace WebCore {
SVGSMILElement(const QualifiedName&, Document*);
virtual ~SVGSMILElement();
static bool isTimingElement(Element* element);
static bool isSMILElement(Node* node);
virtual void parseMappedAttribute(MappedAttribute*);
virtual void attributeChanged(Attribute*, bool preserveDecls);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment