Example #1
0
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);
}
Example #2
0
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();
}
Example #5
0
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();
}
Example #7
0
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);
}
Example #9
0
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;
}
Example #11
0
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();
}
Example #15
0
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;
}
Example #18
0
const HashSet<SVGElementInstance*>& SVGElement::instancesForElement() const
{
    if (!hasSVGRareData()) {
        DEFINE_STATIC_LOCAL(HashSet<SVGElementInstance*>, emptyInstances, ());
        return emptyInstances;
    }