static void updateContainerSize(SVGUseElement* useElement, SVGElementInstance* targetInstance) { // Depth-first used to write the method in early exit style, no particular other reason. for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling()) updateContainerSize(useElement, instance); SVGElement* correspondingElement = targetInstance->correspondingElement(); ASSERT(correspondingElement); bool isSymbolTag = correspondingElement->hasTagName(SVGNames::symbolTag); if (!correspondingElement->hasTagName(SVGNames::svgTag) && !isSymbolTag) return; SVGElement* shadowTreeElement = targetInstance->shadowTreeElement(); ASSERT(shadowTreeElement); ASSERT(shadowTreeElement->hasTagName(SVGNames::svgTag)); // Spec (<use> on <symbol>): 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. // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these // values will override the corresponding attributes on the 'svg' in the generated tree. if (useElement->hasAttribute(SVGNames::widthAttr)) shadowTreeElement->setAttribute(SVGNames::widthAttr, useElement->getAttribute(SVGNames::widthAttr)); else if (isSymbolTag && shadowTreeElement->hasAttribute(SVGNames::widthAttr)) shadowTreeElement->setAttribute(SVGNames::widthAttr, "100%"); if (useElement->hasAttribute(SVGNames::heightAttr)) shadowTreeElement->setAttribute(SVGNames::heightAttr, useElement->getAttribute(SVGNames::heightAttr)); else if (isSymbolTag && shadowTreeElement->hasAttribute(SVGNames::heightAttr)) shadowTreeElement->setAttribute(SVGNames::heightAttr, "100%"); }
void SVGAnimationElement::setTargetAttributeAnimatedValue(const String &value) { if (!hasValidTarget()) { return; } SVGElement *target = targetElement(); String attributeName = this->attributeName(); if (!target || attributeName.isEmpty() || value.isNull()) { return; } // We don't want the instance tree to get rebuild. Instances are updated in the loop below. if (target->isStyled()) { static_cast<SVGStyledElement *>(target)->setInstanceUpdatesBlocked(true); } ExceptionCode ec; bool isCSS = targetAttributeIsCSS(); if (isCSS) { // FIXME: This should set the override style, not the inline style. // Sadly override styles are not yet implemented. target->style()->setProperty(attributeName, value, "", ec); } else { // FIXME: This should set the 'presentation' value, not the actual // attribute value. Whatever that means in practice. target->setAttribute(attributeName, value, ec); } if (target->isStyled()) { static_cast<SVGStyledElement *>(target)->setInstanceUpdatesBlocked(false); } // If the target element is used in an <use> instance tree, update that as well. HashSet<SVGElementInstance *> *instances = document()->accessSVGExtensions()->instancesForElement(target); if (!instances) { return; } HashSet<SVGElementInstance *>::iterator end = instances->end(); for (HashSet<SVGElementInstance *>::iterator it = instances->begin(); it != end; ++it) { SVGElement *shadowTreeElement = (*it)->shadowTreeElement(); ASSERT(shadowTreeElement); if (isCSS) { shadowTreeElement->style()->setProperty(attributeName, value, "", ec); } else { shadowTreeElement->setAttribute(attributeName, value, ec); } (*it)->correspondingUseElement()->setChanged(); } }
void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value) { if (!hasValidAttributeType()) return; SVGElement* targetElement = this->targetElement(); QualifiedName attributeName = this->attributeName(); if (!targetElement || attributeName == anyQName() || value.isNull()) return; // We don't want the instance tree to get rebuild. Instances are updated in the loop below. if (targetElement->isStyled()) static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(true); bool attributeIsCSSProperty = isTargetAttributeCSSProperty(targetElement, attributeName); // Stop animation, if attributeType is set to CSS by the user, but the attribute itself is not a CSS property. if (!attributeIsCSSProperty && attributeType() == AttributeTypeCSS) return; ExceptionCode ec; if (attributeIsCSSProperty) { // FIXME: This should set the override style, not the inline style. // Sadly override styles are not yet implemented. targetElement->style()->setProperty(attributeName.localName(), value, "", ec); } else { // FIXME: This should set the 'presentation' value, not the actual // attribute value. Whatever that means in practice. targetElement->setAttribute(attributeName, value, ec); } if (targetElement->isStyled()) static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(false); // If the target element is used in an <use> instance tree, update that as well. const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); if (!shadowTreeElement) continue; if (attributeIsCSSProperty) shadowTreeElement->style()->setProperty(attributeName.localName(), value, "", ec); else shadowTreeElement->setAttribute(attributeName, value, ec); (*it)->correspondingUseElement()->setNeedsStyleRecalc(); } }
void SVGUseElement::transferSizeAttributesToTargetClone(SVGElement& shadowElement) const { // FIXME: The check for valueInSpecifiedUnits being non-zero below is a workaround for the fact // that we currently have no good way to tell whether a particular animatable attribute is a value // indicating it was unspecified, or specified but could not be parsed. Would be nice to fix that some day. if (is<SVGSymbolElement>(shadowElement)) { // Spec (<use> on <symbol>): 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. shadowElement.setAttribute(SVGNames::widthAttr, (widthIsValid() && width().valueInSpecifiedUnits()) ? AtomicString(width().valueAsString()) : "100%"); shadowElement.setAttribute(SVGNames::heightAttr, (heightIsValid() && height().valueInSpecifiedUnits()) ? AtomicString(height().valueAsString()) : "100%"); } else if (is<SVGSVGElement>(shadowElement)) { // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these // values will override the corresponding attributes on the 'svg' in the generated tree. shadowElement.setAttribute(SVGNames::widthAttr, (widthIsValid() && width().valueInSpecifiedUnits()) ? AtomicString(width().valueAsString()) : shadowElement.correspondingElement()->getAttribute(SVGNames::widthAttr)); shadowElement.setAttribute(SVGNames::heightAttr, (heightIsValid() && height().valueInSpecifiedUnits()) ? AtomicString(height().valueAsString()) : shadowElement.correspondingElement()->getAttribute(SVGNames::heightAttr)); } }
static void transferUseWidthAndHeightIfNeeded( const SVGUseElement& use, SVGElement& shadowElement, const SVGElement& originalElement) { DEFINE_STATIC_LOCAL(const AtomicString, hundredPercentString, ("100%")); // Use |originalElement| for checking the element type, because we will // have replaced a <symbol> with an <svg> in the instance tree. if (isSVGSymbolElement(originalElement)) { // Spec (<use> on <symbol>): 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. shadowElement.setAttribute( SVGNames::widthAttr, use.width()->isSpecified() ? AtomicString(use.width()->currentValue()->valueAsString()) : hundredPercentString); shadowElement.setAttribute( SVGNames::heightAttr, use.height()->isSpecified() ? AtomicString(use.height()->currentValue()->valueAsString()) : hundredPercentString); } else if (isSVGSVGElement(originalElement)) { // Spec (<use> on <svg>): If attributes width and/or height are // provided on the 'use' element, then these values will override the // corresponding attributes on the 'svg' in the generated tree. shadowElement.setAttribute( SVGNames::widthAttr, use.width()->isSpecified() ? AtomicString(use.width()->currentValue()->valueAsString()) : originalElement.getAttribute(SVGNames::widthAttr)); shadowElement.setAttribute( SVGNames::heightAttr, use.height()->isSpecified() ? AtomicString(use.height()->currentValue()->valueAsString()) : originalElement.getAttribute(SVGNames::heightAttr)); } }