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

📄 svguseelement.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            return;        parent = parent->parentNode();    }     SVGElement* target = 0;    if (targetElement && targetElement->isSVGElement())        target = static_cast<SVGElement*>(targetElement);    if (m_targetElementInstance) {        m_targetElementInstance->forgetWrapper();        m_targetElementInstance = 0;    }    // Do not allow self-referencing.    // 'target' may be null, if it's a non SVG namespaced element.    if (!target || target == this) {        m_shadowTreeRootElement = 0;        return;    }    // Why a seperated instance/shadow tree? SVG demands it:    // The instance tree is accesable from JavaScript, and has to    // expose a 1:1 copy of the referenced tree, whereas internally we need    // to alter the tree for correct "use-on-symbol", "use-on-svg" support.       // Build instance tree. Create root SVGElementInstance object for the first sub-tree node.    //    // Spec: If the 'use' element references a simple graphics element such as a 'rect', then there is only a    // single SVGElementInstance object, and the correspondingElement attribute on this SVGElementInstance object    // is the SVGRectElement that corresponds to the referenced 'rect' element.    m_targetElementInstance = new SVGElementInstance(this, target);    // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children    bool foundProblem = false;    buildInstanceTree(target, m_targetElementInstance.get(), foundProblem);    // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!    // Non-appearing <use> content is easier to debug, then half-appearing content.    if (foundProblem) {        m_targetElementInstance = 0;        m_shadowTreeRootElement = 0;        return;    }    // Assure instance tree building was successfull    ASSERT(m_targetElementInstance);    ASSERT(m_targetElementInstance->correspondingUseElement() == this);    // Setup shadow tree root node    m_shadowTreeRootElement = new SVGGElement(SVGNames::gTag, document());    m_shadowTreeRootElement->setInDocument();    m_shadowTreeRootElement->setShadowParentNode(this);    // Spec: An additional transformation translate(x,y) is appended to the end    // (i.e., right-side) of the transform attribute on the generated 'g', where x    // and y represent the values of the x and y attributes on the 'use' element.     if (x().value(this) != 0.0 || y().value(this) != 0.0) {        String transformString = String::format("translate(%f, %f)", x().value(this), y().value(this));        m_shadowTreeRootElement->setAttribute(SVGNames::transformAttr, transformString);    }    // Build shadow tree from instance tree    // This also handles the special cases: <use> on <symbol>, <use> on <svg>.    buildShadowTree(target, m_targetElementInstance.get());#if ENABLE(SVG) && ENABLE(SVG_USE)    // Expand all <use> elements in the shadow tree.    // Expand means: replace the actual <use> element by what it references.    expandUseElementsInShadowTree(m_shadowTreeRootElement.get());    // Expand all <symbol> elements in the shadow tree.    // Expand means: replace the actual <symbol> element by the <svg> element.    expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());#endif    // Now that the shadow tree is completly expanded, we can associate    // shadow tree elements <-> instances in the instance tree.    associateInstancesWithShadowTreeElements(m_shadowTreeRootElement->firstChild(), m_targetElementInstance.get());    // Eventually dump instance tree#ifdef DUMP_INSTANCE_TREE    String text;    unsigned int depth = 0;    dumpInstanceTree(depth, text, m_targetElementInstance.get());    fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());#endif    // Eventually dump shadow tree#ifdef DUMP_SHADOW_TREE    ExceptionCode ec = 0;    PassRefPtr<XMLSerializer> serializer = XMLSerializer::create();    String markup = serializer->serializeToString(m_shadowTreeRootElement.get(), ec);    ASSERT(ec == 0);    fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());#endif    // Transfer event listeners assigned to the referenced element to our shadow tree elements.    transferEventListenersToShadowTree(m_targetElementInstance.get());    // The DOM side is setup properly. Now we have to attach the root shadow    // tree element manually - using attach() won't work for "shadow nodes".    attachShadowTree();}RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*){    return new (arena) RenderSVGTransformableContainer(this);}void SVGUseElement::attach(){    SVGStyledTransformableElement::attach();    // If we're a pending resource, this doesn't have any effect.    attachShadowTree();}void SVGUseElement::detach(){    SVGStyledTransformableElement::detach();    if (m_shadowTreeRootElement)        m_shadowTreeRootElement->detach();}static bool isDirectReference(Node* n){    return n->hasTagName(SVGNames::pathTag) ||           n->hasTagName(SVGNames::rectTag) ||           n->hasTagName(SVGNames::circleTag) ||           n->hasTagName(SVGNames::ellipseTag) ||           n->hasTagName(SVGNames::polygonTag) ||           n->hasTagName(SVGNames::polylineTag) ||           n->hasTagName(SVGNames::textTag);}Path SVGUseElement::toClipPath() const{    if (!m_shadowTreeRootElement)        const_cast<SVGUseElement*>(this)->buildPendingResource();    Node* n = m_shadowTreeRootElement->firstChild();    if (n->isSVGElement() && static_cast<SVGElement*>(n)->isStyledTransformable()) {        if (!isDirectReference(n))            // Spec: Indirect references are an error (14.3.5)            document()->accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");        else            return static_cast<SVGStyledTransformableElement*>(n)->toClipPath();    }    return Path();}void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem){    ASSERT(target);    ASSERT(targetInstance);    // A general description from the SVG spec, describing what buildInstanceTree() actually does.    //    // Spec: If the 'use' element references a 'g' which contains two 'rect' elements, then the instance tree    // contains three SVGElementInstance objects, a root SVGElementInstance object whose correspondingElement    // is the SVGGElement object for the 'g', and then two child SVGElementInstance objects, each of which has    // its correspondingElement that is an SVGRectElement object.    for (Node* node = target->firstChild(); node; node = node->nextSibling()) {        SVGElement* element = 0;        if (node->isSVGElement())            element = static_cast<SVGElement*>(node);        // Skip any non-svg nodes or any disallowed element.        if (!element || isDisallowedElement(element))            continue;        // Create SVGElementInstance object, for both container/non-container nodes.        SVGElementInstance* instancePtr = new SVGElementInstance(this, element);        targetInstance->appendChild(instancePtr);        // Enter recursion, appending new instance tree nodes to the "instance" object.        if (element->hasChildNodes())            buildInstanceTree(element, instancePtr, foundProblem);        // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced        // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.        if (element->hasTagName(SVGNames::useTag))            handleDeepUseReferencing(static_cast<SVGUseElement*>(element), instancePtr, foundProblem);    }    // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced    // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.    if (target->hasTagName(SVGNames::useTag))        handleDeepUseReferencing(static_cast<SVGUseElement*>(target), targetInstance, foundProblem);}void SVGUseElement::handleDeepUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, bool& foundProblem){    String id = SVGURIReference::getTarget(use->href());    Element* targetElement = document()->getElementById(id);     SVGElement* target = 0;    if (targetElement && targetElement->isSVGElement())        target = static_cast<SVGElement*>(targetElement);    if (!target)        return;    // Cycle detection first!    foundProblem = (target == this);    // Shortcut for self-references    if (foundProblem)        return;    SVGElementInstance* instance = targetInstance->parentNode();    while (instance) {        SVGElement* element = instance->correspondingElement();        if (element->getIDAttribute() == id) {            foundProblem = true;            return;        }            instance = instance->parentNode();    }    // Create an instance object, even if we're dealing with a cycle    SVGElementInstance* newInstance = new SVGElementInstance(this, target);    targetInstance->appendChild(newInstance);    // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children    buildInstanceTree(target, newInstance, foundProblem);}void SVGUseElement::alterShadowTreeForSVGTag(SVGElement* target){    String widthString = String::number(width().value(this));    String heightString = String::number(height().value(this));    if (hasAttribute(SVGNames::widthAttr))        target->setAttribute(SVGNames::widthAttr, widthString);    if (hasAttribute(SVGNames::heightAttr))        target->setAttribute(SVGNames::heightAttr, heightString);}void SVGUseElement::removeDisallowedElementsFromSubtree(Node* subtree){    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);    }}void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance){    // For instance <use> on <foreignObject> (direct case).    if (isDisallowedElement(target))        return;    RefPtr<Node> newChild = targetInstance->correspondingElement()->cloneNode(true);    // We don't walk the target tree element-by-element, and clone each element,    // but instead use cloneNode(deep=true). This is an optimization for the common    // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).    // Though if there are disallowed elements in the subtree, we have to remove them.    // For instance: <use> on <g> containing <foreignObject> (indirect case).    if (subtreeContainsDisallowedElement(newChild.get()))        removeDisallowedElementsFromSubtree(newChild.get());    SVGElement* newChildPtr = 0;    if (newChild->isSVGElement())        newChildPtr = static_cast<SVGElement*>(newChild.get());    ASSERT(newChildPtr);    ExceptionCode ec = 0;    m_shadowTreeRootElement->appendChild(newChild.release(), ec);    ASSERT(ec == 0);    // Handle use referencing <svg> special case    if (target->hasTagName(SVGNames::svgTag))        alterShadowTreeForSVGTag(newChildPtr);

⌨️ 快捷键说明

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