SVGElement::~SVGElement() { ASSERT(inDocument() || !hasRelativeLengths()); if (!hasSVGRareData()) ASSERT(!SVGElementRareData::rareDataMap().contains(this)); else { SVGElementRareData::SVGElementRareDataMap& rareDataMap = SVGElementRareData::rareDataMap(); SVGElementRareData::SVGElementRareDataMap::iterator it = rareDataMap.find(this); ASSERT_WITH_SECURITY_IMPLICATION(it != rareDataMap.end()); SVGElementRareData* rareData = it->value; rareData->destroyAnimatedSMILStyleProperties(); if (SVGCursorElement* cursorElement = rareData->cursorElement()) cursorElement->removeClient(this); if (CSSCursorImageValue* cursorImageValue = rareData->cursorImageValue()) cursorImageValue->removeReferencedElement(this); delete rareData; // The rare data cleanup may have caused other SVG nodes to be deleted, // modifying the rare data map. Do not rely on the existing iterator. ASSERT(rareDataMap.contains(this)); rareDataMap.remove(this); // Clear HasSVGRareData flag now so that we are in a consistent state when // calling rebuildAllElementReferencesForTarget() and // removeAllElementReferencesForTarget() below. clearHasSVGRareData(); } document().accessSVGExtensions().rebuildAllElementReferencesForTarget(this); document().accessSVGExtensions().removeAllElementReferencesForTarget(this); }
SVGElement::~SVGElement() { if (!hasSVGRareData()) ASSERT(!SVGElementRareData::rareDataMap().contains(this)); else { ASSERT(document()); SVGElementRareData::SVGElementRareDataMap& rareDataMap = SVGElementRareData::rareDataMap(); SVGElementRareData::SVGElementRareDataMap::iterator it = rareDataMap.find(this); ASSERT(it != rareDataMap.end()); SVGElementRareData* rareData = it->value; rareData->destroyAnimatedSMILStyleProperties(); if (SVGCursorElement* cursorElement = rareData->cursorElement()) cursorElement->removeClient(this); if (CSSCursorImageValue* cursorImageValue = rareData->cursorImageValue()) cursorImageValue->removeReferencedElement(this); delete rareData; // The rare data cleanup may have caused other SVG nodes to be deleted, // modifying the rare data map, so we must re-get the iterator here. it = rareDataMap.find(this); ASSERT(it != rareDataMap.end()); rareDataMap.remove(it); } ASSERT(document()); document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this); document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this); }
SVGElementRareData* SVGElement::ensureSVGRareData() { if (hasSVGRareData()) return svgRareData(); m_SVGRareData = adoptPtrWillBeNoop(new SVGElementRareData(this)); return m_SVGRareData.get(); }
void SVGElement::willRecalcStyle(StyleRecalcChange change) { if (!hasSVGRareData()) return; // If the style changes because of a regular property change (not induced by SMIL animations themselves) // reset the "computed style without SMIL style properties", so the base value change gets reflected. if (change > NoChange || needsStyleRecalc()) svgRareData()->setNeedsOverrideComputedStyleUpdate(); }
void SVGElement::removeInstanceMapping(SVGElementInstance* instance) { ASSERT(instance); ASSERT(hasSVGRareData()); HashSet<SVGElementInstance*>& instances = svgRareData()->elementInstances(); ASSERT(instances.contains(instance)); instances.remove(instance); }
void SVGElement::clearWebAnimatedAttributes() { if (!hasSVGRareData()) return; for (const QualifiedName* attribute : svgRareData()->webAnimatedAttributes()) { updateInstancesAnimatedAttribute(this, *attribute, [](SVGAnimatedPropertyBase& animatedProperty) { animatedProperty.animationEnded(); }); } svgRareData()->webAnimatedAttributes().clear(); }
SVGElementRareData* SVGElement::ensureSVGRareData() { if (hasSVGRareData()) return svgRareData(); ASSERT(!SVGElementRareData::rareDataMap().contains(this)); SVGElementRareData* data = new SVGElementRareData; SVGElementRareData::rareDataMap().set(this, data); setHasSVGRareData(); return data; }
void SVGElement::removeInstanceMapping(SVGElement* instance) { ASSERT(instance); ASSERT(instance->inUseShadowTree()); if (!hasSVGRareData()) return; WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement>>& instances = svgRareData()->elementInstances(); instances.remove(instance); }
void SVGElement::willRecalcStyle(StyleRecalcChange change) { // FIXME: This assumes that when shouldNotifyRendererWithIdenticalStyles() is true // the change came from a SMIL animation, but what if there were non-SMIL changes // since then? I think we should remove the shouldNotifyRendererWithIdenticalStyles // check. if (!hasSVGRareData() || shouldNotifyRendererWithIdenticalStyles()) return; // If the style changes because of a regular property change (not induced by SMIL animations themselves) // reset the "computed style without SMIL style properties", so the base value change gets reflected. if (change > NoChange || needsStyleRecalc()) svgRareData()->setNeedsOverrideComputedStyleUpdate(); }
AffineTransform SVGGraphicsElement::calculateAnimatedLocalTransform() const { AffineTransform matrix; const ComputedStyle* style = layoutObject() ? layoutObject()->style() : nullptr; // If CSS property was set, use that, otherwise fallback to attribute (if set). if (style && style->hasTransform()) { TransformationMatrix transform; float zoom = style->effectiveZoom(); // SVGTextElements need special handling for the text positioning code. if (isSVGTextElement(this)) { // Do not take into account SVG's zoom rules, transform-origin, or percentage values. style->applyTransform(transform, LayoutSize(0, 0), ComputedStyle::ExcludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); } else { // CSS transforms operate with pre-scaled lengths. To make this work with SVG // (which applies the zoom factor globally, at the root level) we // // * pre-scale the bounding box (to bring it into the same space as the other CSS values) // * invert the zoom factor (to effectively compute the CSS transform under a 1.0 zoom) // // Note: objectBoundingBox is an emptyRect for elements like pattern or clipPath. // See the "Object bounding box units" section of http://dev.w3.org/csswg/css3-transforms/ if (zoom != 1) { FloatRect scaledBBox = layoutObject()->objectBoundingBox(); scaledBBox.scale(zoom); transform.scale(1 / zoom); style->applyTransform(transform, scaledBBox, ComputedStyle::IncludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); transform.scale(zoom); } else { style->applyTransform(transform, layoutObject()->objectBoundingBox(), ComputedStyle::IncludeTransformOrigin, ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties); } } // Flatten any 3D transform. matrix = transform.toAffineTransform(); } else { m_transform->currentValue()->concatenate(matrix); } if (hasSVGRareData()) return *svgRareData()->animateMotionTransform() * matrix; return matrix; }
SVGElement::~SVGElement() { ASSERT(inDocument() || !hasRelativeLengths()); // The below teardown is all handled by weak pointer processing in oilpan. #if !ENABLE(OILPAN) if (hasSVGRareData()) { if (SVGCursorElement* cursorElement = svgRareData()->cursorElement()) cursorElement->removeReferencedElement(this); if (CSSCursorImageValue* cursorImageValue = svgRareData()->cursorImageValue()) cursorImageValue->removeReferencedElement(this); // Clear the rare data now so that we are in a consistent state when // calling rebuildAllElementReferencesForTarget() below. m_SVGRareData.clear(); } // With Oilpan, either removedFrom has been called or the document is dead // as well and there is no reason to clear out the references. document().accessSVGExtensions().rebuildAllElementReferencesForTarget(this); document().accessSVGExtensions().removeAllElementReferencesForTarget(this); #endif }
void SVGElement::setInstanceUpdatesBlocked(bool value) { if (hasSVGRareData()) svgRareData()->setInstanceUpdatesBlocked(value); }
bool SVGElement::instanceUpdatesBlocked() const { return hasSVGRareData() && svgRareData()->instanceUpdatesBlocked(); }
bool SVGGraphicsElement::hasAnimatedLocalTransform() const { const ComputedStyle* style = layoutObject() ? layoutObject()->style() : nullptr; // Each of these is used in SVGGraphicsElement::calculateAnimatedLocalTransform to create an animated local transform. return (style && style->hasTransform()) || !m_transform->currentValue()->isEmpty() || hasSVGRareData(); }
SVGElementRareData* SVGElement::svgRareData() const { ASSERT(hasSVGRareData()); return SVGElementRareData::rareDataFromMap(this); }
const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement>>& SVGElement::instancesForElement() const { if (!hasSVGRareData()) return emptyInstances(); return svgRareData()->elementInstances(); }
SVGElement* SVGElement::correspondingElement() const { ASSERT(!hasSVGRareData() || !svgRareData()->correspondingElement() || containingShadowRoot()); return hasSVGRareData() ? svgRareData()->correspondingElement() : 0; }
const HashSet<SVGElementInstance*>& SVGElement::instancesForElement() const { if (!hasSVGRareData()) { DEFINE_STATIC_LOCAL(HashSet<SVGElementInstance*>, emptyInstances, ()); return emptyInstances; }