⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svguseelement.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*    Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>                  2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>    This file is part of the KDE project    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public License    along with this library; see the file COPYING.LIB.  If not, write to    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,    Boston, MA 02110-1301, USA.*/#include "config.h"// Dump SVGElementInstance object tree - useful to debug instanceRoot problems// #define DUMP_INSTANCE_TREE// Dump the deep-expanded shadow tree (where the renderes are built from)// #define DUMP_SHADOW_TREE#if ENABLE(SVG)#include "SVGUseElement.h"#include "CSSStyleSelector.h"#include "CString.h"#include "Document.h"#include "Event.h"#include "EventListener.h"#include "HTMLNames.h"#include "NodeRenderStyle.h"#include "RegisteredEventListener.h"#include "RenderSVGTransformableContainer.h"#include "SVGElementInstance.h"#include "SVGElementInstanceList.h"#include "SVGGElement.h"#include "SVGLength.h"#include "SVGPreserveAspectRatio.h"#include "SVGSMILElement.h"#include "SVGSVGElement.h"#include "SVGSymbolElement.h"#include "XLinkNames.h"#include "XMLSerializer.h"namespace WebCore {SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document* doc)    : SVGStyledTransformableElement(tagName, doc)    , SVGTests()    , SVGLangSpace()    , SVGExternalResourcesRequired()    , SVGURIReference()    , m_x(this, SVGNames::xAttr, LengthModeWidth)    , m_y(this, SVGNames::yAttr, LengthModeHeight)    , m_width(this, SVGNames::widthAttr, LengthModeWidth)    , m_height(this, SVGNames::heightAttr, LengthModeHeight){}SVGUseElement::~SVGUseElement(){}SVGElementInstance* SVGUseElement::instanceRoot() const{    return m_targetElementInstance.get();}SVGElementInstance* SVGUseElement::animatedInstanceRoot() const{    // FIXME: Implement me.    return 0;} void SVGUseElement::parseMappedAttribute(MappedAttribute* attr){    if (attr->name() == SVGNames::xAttr)        setXBaseValue(SVGLength(LengthModeWidth, attr->value()));    else if (attr->name() == SVGNames::yAttr)        setYBaseValue(SVGLength(LengthModeHeight, attr->value()));    else if (attr->name() == SVGNames::widthAttr) {        setWidthBaseValue(SVGLength(LengthModeWidth, attr->value()));        if (widthBaseValue().value(this) < 0.0)            document()->accessSVGExtensions()->reportError("A negative value for use attribute <width> is not allowed");    } else if (attr->name() == SVGNames::heightAttr) {        setHeightBaseValue(SVGLength(LengthModeHeight, attr->value()));        if (heightBaseValue().value(this) < 0.0)            document()->accessSVGExtensions()->reportError("A negative value for use attribute <height> is not allowed");    } else {        if (SVGTests::parseMappedAttribute(attr))            return;        if (SVGLangSpace::parseMappedAttribute(attr))            return;        if (SVGExternalResourcesRequired::parseMappedAttribute(attr))            return;        if (SVGURIReference::parseMappedAttribute(attr))            return;        SVGStyledTransformableElement::parseMappedAttribute(attr);    }}void SVGUseElement::insertedIntoDocument(){    SVGElement::insertedIntoDocument();    buildPendingResource();}void SVGUseElement::removedFromDocument(){    m_targetElementInstance = 0;    m_shadowTreeRootElement = 0;    SVGElement::removedFromDocument();}void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName){    SVGStyledTransformableElement::svgAttributeChanged(attrName);    if (!attached())        return;    if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||        attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||        SVGTests::isKnownAttribute(attrName) ||        SVGLangSpace::isKnownAttribute(attrName) ||        SVGExternalResourcesRequired::isKnownAttribute(attrName) ||        SVGURIReference::isKnownAttribute(attrName) ||        SVGStyledTransformableElement::isKnownAttribute(attrName)) {        buildPendingResource();        if (m_shadowTreeRootElement)            m_shadowTreeRootElement->setChanged();    }}void SVGUseElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta){    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);    if (!attached())        return;    buildPendingResource();    if (m_shadowTreeRootElement)        m_shadowTreeRootElement->setChanged();} static bool shadowTreeContainsChangedNodes(SVGElementInstance* target){    if (target->needsUpdate())        return true;    for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())        if (shadowTreeContainsChangedNodes(instance))            return true;    return false;}void SVGUseElement::recalcStyle(StyleChange change){    if (attached() && changed() && shadowTreeContainsChangedNodes(m_targetElementInstance.get())) {        buildPendingResource();        if (m_shadowTreeRootElement)            m_shadowTreeRootElement->setChanged();    }    SVGStyledElement::recalcStyle(change);    // The shadow tree root element is NOT a direct child element of us.    // So we have to take care it receives style updates, manually.    if (!m_shadowTreeRootElement || !m_shadowTreeRootElement->attached())        return;    // Mimic Element::recalcStyle(). The main difference is that we don't call attach() on the    // shadow tree root element, but call attachShadowTree() here. Calling attach() will crash    // as the shadow tree root element has no (direct) parent node. Yes, shadow trees are tricky.    if (change >= Inherit || m_shadowTreeRootElement->changed()) {        RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(m_shadowTreeRootElement.get());        StyleChange ch = Node::diff(m_shadowTreeRootElement->renderStyle(), newStyle.get());        if (ch == Detach) {            ASSERT(m_shadowTreeRootElement->attached());            m_shadowTreeRootElement->detach();            attachShadowTree();            // attach recalulates the style for all children. No need to do it twice.            m_shadowTreeRootElement->setChanged(NoStyleChange);            m_shadowTreeRootElement->setHasChangedChild(false);            return;        }    }    // Only change==Detach needs special treatment, for anything else recalcStyle() works.    m_shadowTreeRootElement->recalcStyle(change);}#ifdef DUMP_INSTANCE_TREEvoid dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance){    SVGElement* element = targetInstance->correspondingElement();    ASSERT(element);    String elementId = element->getIDAttribute();    String elementNodeName = element->nodeName();    String parentNodeName = element->parentNode() ? element->parentNode()->nodeName() : "null";    String firstChildNodeName = element->firstChild() ? element->firstChild()->nodeName() : "null";    for (unsigned int i = 0; i < depth; ++i)        text += "  ";    text += String::format("SVGElementInstance this=%p, (parentNode=%s, firstChild=%s, correspondingElement=%s (%p), shadowTreeElement=%p, id=%s)\n",                           targetInstance, parentNodeName.latin1().data(), firstChildNodeName.latin1().data(), elementNodeName.latin1().data(),                           element, targetInstance->shadowTreeElement(), elementId.latin1().data());    for (unsigned int i = 0; i < depth; ++i)        text += "  ";    HashSet<SVGElementInstance*> elementInstances = element->instancesForElement();    text += String::format("Corresponding element is associated with %i instance(s):\n", elementInstances.size());    HashSet<SVGElementInstance*>::iterator end = elementInstances.end();    for (HashSet<SVGElementInstance*>::iterator it = elementInstances.begin(); it != end; ++it) {        for (unsigned int i = 0; i < depth; ++i)            text += "  ";        text += String::format(" -> SVGElementInstance this=%p, (refCount: %i, shadowTreeElement in document? %i)\n",                               *it, (*it)->refCount(), (*it)->shadowTreeElement()->inDocument());    }    ++depth;    for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())        dumpInstanceTree(depth, text, instance);    --depth;}#endifstatic bool isDisallowedElement(Node* element){#if ENABLE(SVG_FOREIGN_OBJECT)    // <foreignObject> should never be contained in a <use> tree. Too dangerous side effects possible.    if (element->hasTagName(SVGNames::foreignObjectTag))        return true;#endif#if ENABLE(SVG_ANIMATION)    if (SVGSMILElement::isSMILElement(element))        return true;#endif    return false;}static bool subtreeContainsDisallowedElement(Node* start){    if (isDisallowedElement(start))        return true;    for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {        if (subtreeContainsDisallowedElement(cur))            return true;    }    return false;}void SVGUseElement::buildPendingResource(){    String id = SVGURIReference::getTarget(href());    Element* targetElement = document()->getElementById(id);    if (!targetElement) {        // TODO: We want to deregister as pending resource, if our href() changed!        // TODO: Move to svgAttributeChanged, once we're fixing use & the new dynamic update concept.        document()->accessSVGExtensions()->addPendingResource(id, this);        return;    }    // Do not build the shadow/instance tree for <use> elements living in a shadow tree.    // The will be expanded soon anyway - see expandUseElementsInShadowTree().    Node* parent = parentNode();    while (parent) {        if (parent->isShadowNode())

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -