void SVGAnimateTransformElement::applyResultsToTarget() { if (!hasValidTarget()) return; // We accumulate to the target element transform list so there is not much to do here. SVGElement* targetElement = this->targetElement(); if (!targetElement) return; if (RenderObject* renderer = targetElement->renderer()) { renderer->setNeedsTransformUpdate(); RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } // ...except in case where we have additional instances in <use> trees. const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); RefPtr<SVGTransformList> transformList = transformListFor(targetElement); const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); ASSERT(shadowTreeElement); if (shadowTreeElement->isStyledTransformable()) static_cast<SVGStyledTransformableElement*>(shadowTreeElement)->setTransformBaseValue(transformList.get()); else if (shadowTreeElement->hasTagName(SVGNames::textTag)) static_cast<SVGTextElement*>(shadowTreeElement)->setTransformBaseValue(transformList.get()); else if (shadowTreeElement->hasTagName(SVGNames::linearGradientTag) || shadowTreeElement->hasTagName(SVGNames::radialGradientTag)) static_cast<SVGGradientElement*>(shadowTreeElement)->setGradientTransformBaseValue(transformList.get()); if (RenderObject* renderer = shadowTreeElement->renderer()) { renderer->setNeedsTransformUpdate(); RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } } }
void SVGAnimateMotionElement::applyResultsToTarget() { // We accumulate to the target element transform list so there is not much to do here. SVGElement* targetElement = this->targetElement(); if (!targetElement) return; if (RenderObject* renderer = targetElement->renderer()) RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); AffineTransform* t = targetElement->supplementalTransform(); if (!t) return; // ...except in case where we have additional instances in <use> trees. 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(); ASSERT(shadowTreeElement); AffineTransform* transform = shadowTreeElement->supplementalTransform(); if (!transform) continue; transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f()); if (RenderObject* renderer = shadowTreeElement->renderer()) { renderer->setNeedsTransformUpdate(); RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } } }
void RenderSVGViewportContainer::calcViewport() { SVGSVGElement& svg = svgSVGElement(); FloatRect oldViewport = m_viewport; SVGLengthContext lengthContext(&svg); m_viewport = FloatRect(svg.x().value(lengthContext), svg.y().value(lengthContext), svg.width().value(lengthContext), svg.height().value(lengthContext)); SVGElement* correspondingElement = svg.correspondingElement(); if (correspondingElement && svg.isInShadowTree()) { const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement(); ASSERT(!instances.isEmpty()); SVGUseElement* useElement = 0; const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { const SVGElementInstance* instance = (*it); ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag)); if (instance->shadowTreeElement() == &svg) { ASSERT(correspondingElement == instance->correspondingElement()); useElement = instance->directUseElement(); if (!useElement) useElement = instance->correspondingUseElement(); break; } } ASSERT(useElement); bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag); // 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. SVGLengthContext lengthContext(&svg); if (useElement->hasAttribute(SVGNames::widthAttr)) m_viewport.setWidth(useElement->width().value(lengthContext)); else if (isSymbolElement && svg.hasAttribute(SVGNames::widthAttr)) { SVGLength containerWidth(LengthModeWidth, "100%"); m_viewport.setWidth(containerWidth.value(lengthContext)); } if (useElement->hasAttribute(SVGNames::heightAttr)) m_viewport.setHeight(useElement->height().value(lengthContext)); else if (isSymbolElement && svg.hasAttribute(SVGNames::heightAttr)) { SVGLength containerHeight(LengthModeHeight, "100%"); m_viewport.setHeight(containerHeight.value(lengthContext)); } } if (oldViewport != m_viewport) { setNeedsBoundariesUpdate(); setNeedsTransformUpdate(); } }
static void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance) { SVGElement* element = targetInstance->correspondingElement(); ASSERT(element); if (element->hasTagName(SVGNames::useTag)) { if (toSVGUseElement(element)->cachedDocumentIsStillLoading()) return; } SVGElement* shadowTreeElement = targetInstance->shadowTreeElement(); ASSERT(shadowTreeElement); SVGUseElement* directUseElement = targetInstance->directUseElement(); String directUseElementName = directUseElement ? directUseElement->nodeName() : "null"; String elementId = element->getIdAttribute(); String elementNodeName = element->nodeName(); String shadowTreeElementNodeName = shadowTreeElement->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 (%p), firstChild=%s (%p), correspondingElement=%s (%p), directUseElement=%s (%p), shadowTreeElement=%s (%p), id=%s)\n", targetInstance, parentNodeName.latin1().data(), element->parentNode(), firstChildNodeName.latin1().data(), element->firstChild(), elementNodeName.latin1().data(), element, directUseElementName.latin1().data(), directUseElement, shadowTreeElementNodeName.latin1().data(), shadowTreeElement, elementId.latin1().data()); for (unsigned int i = 0; i < depth; ++i) text += " "; const HashSet<SVGElementInstance*>& elementInstances = element->instancesForElement(); text += "Corresponding element is associated with " + String::number(elementInstances.size()) + " instance(s):\n"; const HashSet<SVGElementInstance*>::const_iterator end = elementInstances.end(); for (HashSet<SVGElementInstance*>::const_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; }
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 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. const HashSet<SVGElementInstance*>& instances = target->instancesForElement(); const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); for (HashSet<SVGElementInstance*>::const_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()->setNeedsStyleRecalc(); } }
void SVGAnimateTransformElement::applyResultsToTarget() { if (!hasValidTarget()) return; // We accumulate to the target element transform list so there is not much to do here. SVGElement* targetElement = this->targetElement(); if (targetElement->renderer()) targetElement->renderer()->setNeedsLayout(true); // ...except in case where we have additional instances in <use> trees. const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); RefPtr<SVGTransformList> transformList = transformListFor(targetElement); const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); ASSERT(shadowTreeElement); if (shadowTreeElement->isStyledTransformable()) static_cast<SVGStyledTransformableElement*>(shadowTreeElement)->setTransformBaseValue(transformList.get()); else if (shadowTreeElement->hasTagName(SVGNames::textTag)) static_cast<SVGTextElement*>(shadowTreeElement)->setTransformBaseValue(transformList.get()); if (shadowTreeElement->renderer()) shadowTreeElement->renderer()->setNeedsLayout(true); } }