Use #pragma once in WebCore
[WebKit-https.git] / Source / WebCore / svg / SVGFEImageElement.cpp
index 04ea14c..0b32710 100644 (file)
  */
 
 #include "config.h"
-
-#if ENABLE(SVG) && ENABLE(FILTERS)
 #include "SVGFEImageElement.h"
 
-#include "Attr.h"
 #include "CachedImage.h"
 #include "CachedResourceLoader.h"
-#include "ColorSpace.h"
+#include "CachedResourceRequest.h"
 #include "Document.h"
+#include "Image.h"
 #include "RenderObject.h"
 #include "RenderSVGResource.h"
-#include "SVGImageBufferTools.h"
 #include "SVGNames.h"
-#include "SVGPreserveAspectRatio.h"
+#include "SVGPreserveAspectRatioValue.h"
+#include "XLinkNames.h"
 
 namespace WebCore {
 
@@ -42,127 +40,163 @@ DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGFEImageElement, SVGNames::preserveAspectR
 DEFINE_ANIMATED_STRING(SVGFEImageElement, XLinkNames::hrefAttr, Href, href)
 DEFINE_ANIMATED_BOOLEAN(SVGFEImageElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
 
-inline SVGFEImageElement::SVGFEImageElement(const QualifiedName& tagName, Document* document)
+BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEImageElement)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(href)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
+    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
+END_REGISTER_ANIMATED_PROPERTIES
+
+inline SVGFEImageElement::SVGFEImageElement(const QualifiedName& tagName, Document& document)
     : SVGFilterPrimitiveStandardAttributes(tagName, document)
 {
+    ASSERT(hasTagName(SVGNames::feImageTag));
+    registerAnimatedPropertiesForSVGFEImageElement();
 }
 
-PassRefPtr<SVGFEImageElement> SVGFEImageElement::create(const QualifiedName& tagName, Document* document)
+Ref<SVGFEImageElement> SVGFEImageElement::create(const QualifiedName& tagName, Document& document)
 {
-    return adoptRef(new SVGFEImageElement(tagName, document));
+    return adoptRef(*new SVGFEImageElement(tagName, document));
 }
 
 SVGFEImageElement::~SVGFEImageElement()
 {
-    if (m_cachedImage)
-        m_cachedImage->removeClient(this);
+    clearResourceReferences();
 }
 
-void SVGFEImageElement::requestImageResource()
+bool SVGFEImageElement::hasSingleSecurityOrigin() const
+{
+    if (!m_cachedImage)
+        return true;
+    auto* image = m_cachedImage->image();
+    return !image || image->hasSingleSecurityOrigin();
+}
+
+void SVGFEImageElement::clearResourceReferences()
 {
     if (m_cachedImage) {
-        m_cachedImage->removeClient(this);
-        m_cachedImage = 0;
+        m_cachedImage->removeClient(*this);
+        m_cachedImage = nullptr;
     }
 
-    Element* hrefElement = document()->getElementById(SVGURIReference::getTarget(href()));
-    if (hrefElement && hrefElement->isSVGElement() && hrefElement->renderer())
-        return;
+    document().accessSVGExtensions().removeAllTargetReferencesForElement(this);
+}
+
+void SVGFEImageElement::requestImageResource()
+{
+    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+    options.contentSecurityPolicyImposition = isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
 
-    m_cachedImage = ownerDocument()->cachedResourceLoader()->requestImage(href());
+    CachedResourceRequest request(ResourceRequest(document().completeURL(href())), options);
+    request.setInitiator(this);
+    m_cachedImage = document().cachedResourceLoader().requestImage(WTFMove(request));
 
     if (m_cachedImage)
-        m_cachedImage->addClient(this);
+        m_cachedImage->addClient(*this);
 }
 
-void SVGFEImageElement::parseMappedAttribute(Attribute* attr)
+void SVGFEImageElement::buildPendingResource()
 {
-    const String& value = attr->value();
-    if (attr->name() == SVGNames::preserveAspectRatioAttr)
-        SVGPreserveAspectRatio::parsePreserveAspectRatio(this, value);
-    else {
-        if (SVGURIReference::parseMappedAttribute(attr)) {
+    clearResourceReferences();
+    if (!inDocument())
+        return;
+
+    String id;
+    Element* target = SVGURIReference::targetElementFromIRIString(href(), document(), &id);
+    if (!target) {
+        if (id.isEmpty())
             requestImageResource();
-            return;
+        else {
+            document().accessSVGExtensions().addPendingResource(id, this);
+            ASSERT(hasPendingResources());
         }
-        if (SVGLangSpace::parseMappedAttribute(attr))
-            return;
-        if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
-            return;
-
-        SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr);
+    } else if (target->isSVGElement()) {
+        // Register us with the target in the dependencies map. Any change of hrefElement
+        // that leads to relayout/repainting now informs us, so we can react to it.
+        document().accessSVGExtensions().addElementReferencingTarget(this, downcast<SVGElement>(target));
     }
+
+    invalidate();
 }
 
-void SVGFEImageElement::svgAttributeChanged(const QualifiedName& attrName)
+void SVGFEImageElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
-    SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
+    if (name == SVGNames::preserveAspectRatioAttr) {
+        SVGPreserveAspectRatioValue preserveAspectRatio;
+        preserveAspectRatio.parse(value);
+        setPreserveAspectRatioBaseValue(preserveAspectRatio);
+        return;
+    }
 
-    if (attrName == SVGNames::preserveAspectRatioAttr)
-        invalidate();
+    SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
+    SVGURIReference::parseAttribute(name, value);
+    SVGExternalResourcesRequired::parseAttribute(name, value);
 }
 
-void SVGFEImageElement::synchronizeProperty(const QualifiedName& attrName)
+void SVGFEImageElement::svgAttributeChanged(const QualifiedName& attrName)
 {
-    SVGFilterPrimitiveStandardAttributes::synchronizeProperty(attrName);
+    if (attrName == SVGNames::preserveAspectRatioAttr) {
+        InstanceInvalidationGuard guard(*this);
+        invalidate();
+        return;
+    }
 
-    if (attrName == anyQName()) {
-        synchronizePreserveAspectRatio();
-        synchronizeHref();
-        synchronizeExternalResourcesRequired();
+    if (SVGURIReference::isKnownAttribute(attrName)) {
+        InstanceInvalidationGuard guard(*this);
+        buildPendingResource();
         return;
     }
 
-    if (attrName == SVGNames::preserveAspectRatioAttr)
-        synchronizePreserveAspectRatio();
-    else if (SVGURIReference::isKnownAttribute(attrName))
-        synchronizeHref();
-    else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
-        synchronizeExternalResourcesRequired();
+    SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
+}
+
+Node::InsertionNotificationRequest SVGFEImageElement::insertedInto(ContainerNode& rootParent)
+{
+    SVGFilterPrimitiveStandardAttributes::insertedInto(rootParent);
+    return InsertionShouldCallFinishedInsertingSubtree;
+}
+
+void SVGFEImageElement::finishedInsertingSubtree()
+{
+    buildPendingResource();
+}
+
+void SVGFEImageElement::removedFrom(ContainerNode& rootParent)
+{
+    SVGFilterPrimitiveStandardAttributes::removedFrom(rootParent);
+    if (rootParent.inDocument())
+        clearResourceReferences();
 }
 
-void SVGFEImageElement::notifyFinished(CachedResource*)
+void SVGFEImageElement::notifyFinished(CachedResource&)
 {
     if (!inDocument())
         return;
 
     Element* parent = parentElement();
-    ASSERT(parent);
 
-    if (!parent->hasTagName(SVGNames::filterTag) || !parent->renderer())
+    if (!parent || !parent->hasTagName(SVGNames::filterTag))
+        return;
+
+    RenderElement* parentRenderer = parent->renderer();
+    if (!parentRenderer)
         return;
 
-    RenderSVGResource::markForLayoutAndParentResourceInvalidation(parent->renderer());
+    RenderSVGResource::markForLayoutAndParentResourceInvalidation(*parentRenderer);
 }
 
-PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter* filter)
+RefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter& filter)
 {
-    if (!m_cachedImage && !m_targetImage) {
-        Element* hrefElement = document()->getElementById(SVGURIReference::getTarget(href()));
-        if (!hrefElement || !hrefElement->isSVGElement())
-            return 0;
-
-        RenderObject* renderer = hrefElement->renderer();
-        if (!renderer)
-            return 0;
-
-        IntRect targetRect = enclosingIntRect(renderer->objectBoundingBox());
-        m_targetImage = ImageBuffer::create(targetRect.size(), ColorSpaceLinearRGB);
-
-        AffineTransform contentTransformation;
-        SVGImageBufferTools::renderSubtreeToImageBuffer(m_targetImage.get(), renderer, contentTransformation);
-    }
-
-    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio());
+    if (m_cachedImage)
+        return FEImage::createWithImage(filter, m_cachedImage->imageForRenderer(renderer()), preserveAspectRatio());
+    return FEImage::createWithIRIReference(filter, document(), href(), preserveAspectRatio());
 }
 
-void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
+void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
 {
     SVGFilterPrimitiveStandardAttributes::addSubresourceAttributeURLs(urls);
 
-    addSubresourceURL(urls, document()->completeURL(href()));
+    addSubresourceURL(urls, document().completeURL(href()));
 }
 
 }
-
-#endif // ENABLE(SVG)