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

📄 svguseelement.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}#if ENABLE(SVG) && ENABLE(SVG_USE)void SVGUseElement::expandUseElementsInShadowTree(Node* element){    // Why expand the <use> elements in the shadow tree here, and not just    // do this directly in buildShadowTree, if we encounter a <use> element?    //    // Short answer: Because we may miss to expand some elements. Ie. if a <symbol>    // contains <use> tags, we'd miss them. So once we're done with settin' up the    // actual shadow tree (after the special case modification for svg/symbol) we have    // to walk it completely and expand all <use> elements.    if (element->hasTagName(SVGNames::useTag)) {        SVGUseElement* use = static_cast<SVGUseElement*>(element);        String id = SVGURIReference::getTarget(use->href());        Element* targetElement = document()->getElementById(id);         SVGElement* target = 0;        if (targetElement && targetElement->isSVGElement())            target = static_cast<SVGElement*>(targetElement);        // Don't ASSERT(target) here, it may be "pending", too.        if (target) {            // Setup sub-shadow tree root node            RefPtr<SVGElement> cloneParent = new SVGGElement(SVGNames::gTag, document());            // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the            // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.            transferUseAttributesToReplacedElement(use, cloneParent.get());            // 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 (use->x().value(this) != 0.0 || use->y().value(this) != 0.0) {                if (!cloneParent->hasAttribute(SVGNames::transformAttr)) {                    String transformString = String::format("translate(%f, %f)", use->x().value(this), use->y().value(this));                    cloneParent->setAttribute(SVGNames::transformAttr, transformString);                } else {                    String transformString = String::format(" translate(%f, %f)", use->x().value(this), use->y().value(this));                    const AtomicString& transformAttribute = cloneParent->getAttribute(SVGNames::transformAttr);                    cloneParent->setAttribute(SVGNames::transformAttr, transformAttribute + transformString);                 }            }            ExceptionCode ec = 0;             // For instance <use> on <foreignObject> (direct case).            if (isDisallowedElement(target)) {                // We still have to setup the <use> replacment (<g>). Otherwhise                // associateInstancesWithShadowTreeElements() makes wrong assumptions.                // Replace <use> with referenced content.                ASSERT(use->parentNode());                 use->parentNode()->replaceChild(cloneParent.release(), use, ec);                ASSERT(ec == 0);                return;            }            RefPtr<Node> newChild = target->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);            cloneParent->appendChild(newChild.release(), ec);            ASSERT(ec == 0);            // Replace <use> with referenced content.            ASSERT(use->parentNode());             use->parentNode()->replaceChild(cloneParent.release(), use, ec);            ASSERT(ec == 0);            // Handle use referencing <svg> special case            if (target->hasTagName(SVGNames::svgTag))                alterShadowTreeForSVGTag(newChildPtr);            // Immediately stop here, and restart expanding.            expandUseElementsInShadowTree(m_shadowTreeRootElement.get());            return;        }    }    for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())        expandUseElementsInShadowTree(child.get());}void SVGUseElement::expandSymbolElementsInShadowTree(Node* element){    if (element->hasTagName(SVGNames::symbolTag)) {        // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,        // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will        // always have explicit values for attributes width and height. If attributes width and/or        // height are provided on the 'use' element, then these attributes will be transferred to        // the generated 'svg'. If attributes width and/or height are not specified, the generated        // 'svg' element will use values of 100% for these attributes.        RefPtr<SVGSVGElement> svgElement = new SVGSVGElement(SVGNames::svgTag, document());        // Transfer all attributes from <symbol> to the new <svg> element        svgElement->attributes()->setAttributes(*element->attributes());        // Explicitly re-set width/height values        String widthString = String::number(width().value(this));        String heightString = String::number(height().value(this));         svgElement->setAttribute(SVGNames::widthAttr, hasAttribute(SVGNames::widthAttr) ? widthString : "100%");        svgElement->setAttribute(SVGNames::heightAttr, hasAttribute(SVGNames::heightAttr) ? heightString : "100%");        ExceptionCode ec = 0;        // Only clone symbol children, and add them to the new <svg> element            for (Node* child = element->firstChild(); child; child = child->nextSibling()) {            RefPtr<Node> newChild = child->cloneNode(true);            svgElement->appendChild(newChild.release(), ec);            ASSERT(ec == 0);        }            // 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(svgElement.get()))            removeDisallowedElementsFromSubtree(svgElement.get());        // Replace <symbol> with <svg>.        ASSERT(element->parentNode());         element->parentNode()->replaceChild(svgElement.release(), element, ec);        ASSERT(ec == 0);        // Immediately stop here, and restart expanding.        expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());        return;    }    for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())        expandSymbolElementsInShadowTree(child.get());}#endif    void SVGUseElement::attachShadowTree(){    if (!m_shadowTreeRootElement || m_shadowTreeRootElement->attached() || !document()->shouldCreateRenderers() || !attached() || !renderer())        return;    // Inspired by RenderTextControl::createSubtreeIfNeeded().     if (renderer()->canHaveChildren() && childShouldCreateRenderer(m_shadowTreeRootElement.get())) {        RefPtr<RenderStyle> style = m_shadowTreeRootElement->styleForRenderer();        if (m_shadowTreeRootElement->rendererIsNeeded(style.get())) {            m_shadowTreeRootElement->setRenderer(m_shadowTreeRootElement->createRenderer(document()->renderArena(), style.get()));            if (RenderObject* shadowRenderer = m_shadowTreeRootElement->renderer()) {                shadowRenderer->setStyle(style.release());                renderer()->addChild(shadowRenderer, m_shadowTreeRootElement->nextRenderer());                m_shadowTreeRootElement->setAttached();            }        }        // This will take care of attaching all shadow tree child nodes.        for (Node* child = m_shadowTreeRootElement->firstChild(); child; child = child->nextSibling())            child->attach();    }} void SVGUseElement::transferEventListenersToShadowTree(SVGElementInstance* target){    if (!target)        return;    SVGElement* originalElement = target->correspondingElement();    ASSERT(originalElement);    if (SVGElement* shadowTreeElement = target->shadowTreeElement()) {        const RegisteredEventListenerVector& listeners = originalElement->eventListeners();        size_t size = listeners.size();        for (size_t i = 0; i < size; ++i) {            const RegisteredEventListener& r = *listeners[i];            EventListener* listener = r.listener();            ASSERT(listener);            // Event listeners created from markup have already been transfered to the shadow tree during cloning!            if (listener->wasCreatedFromMarkup())                continue;            shadowTreeElement->addEventListener(r.eventType(), listener, r.useCapture());        }    }    for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())        transferEventListenersToShadowTree(instance);}void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance){    if (!target || !targetInstance)        return;    SVGElement* originalElement = targetInstance->correspondingElement();    if (originalElement->hasTagName(SVGNames::useTag)) {#if ENABLE(SVG) && ENABLE(SVG_USE)        // <use> gets replaced by <g>        ASSERT(target->nodeName() == SVGNames::gTag);#else         ASSERT(target->nodeName() == SVGNames::gTag || target->nodeName() == SVGNames::useTag);#endif    } else if (originalElement->hasTagName(SVGNames::symbolTag)) {        // <symbol> gets replaced by <svg>#if ENABLE(SVG) && ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT)        ASSERT(target->nodeName() == SVGNames::svgTag);#endif    } else        ASSERT(target->nodeName() == originalElement->nodeName());    SVGElement* element = 0;    if (target->isSVGElement())        element = static_cast<SVGElement*>(target);    ASSERT(!targetInstance->shadowTreeElement());    targetInstance->setShadowTreeElement(element);    Node* node = target->firstChild();    for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {        // Skip any non-svg elements in shadow tree        while (node && !node->isSVGElement())           node = node->nextSibling();        associateInstancesWithShadowTreeElements(node, instance);        node = node->nextSibling();    }}SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const{    return instanceForShadowTreeElement(element, m_targetElementInstance.get());}SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const{    ASSERT(element);    ASSERT(instance);    ASSERT(instance->shadowTreeElement());    if (element == instance->shadowTreeElement())        return instance;    for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {        SVGElementInstance* search = instanceForShadowTreeElement(element, current);        if (search)            return search;    }    return 0;}void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const{    ASSERT(from);    ASSERT(to);    to->attributes()->setAttributes(*from->attributes());    ExceptionCode ec = 0;    to->removeAttribute(SVGNames::xAttr, ec);    ASSERT(ec == 0);    to->removeAttribute(SVGNames::yAttr, ec);    ASSERT(ec == 0);    to->removeAttribute(SVGNames::widthAttr, ec);    ASSERT(ec == 0);    to->removeAttribute(SVGNames::heightAttr, ec);    ASSERT(ec == 0);    to->removeAttribute(XLinkNames::hrefAttr, ec);    ASSERT(ec == 0);}}#endif // ENABLE(SVG)

⌨️ 快捷键说明

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