ba16580fce6379063b0e41bea1399ac0dedadc8e
[WebKit-https.git] / Source / WebCore / rendering / RenderLayerFilterInfo.cpp
1 /*
2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
3  * Copyright (C) 2013 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above
10  *    copyright notice, this list of conditions and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above
13  *    copyright notice, this list of conditions and the following
14  *    disclaimer in the documentation and/or other materials
15  *    provided with the distribution.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "RenderLayerFilterInfo.h"
33
34 #include "CachedSVGDocument.h"
35 #include "CachedSVGDocumentReference.h"
36 #include "FilterEffectRenderer.h"
37 #include "RenderSVGResourceFilter.h"
38 #include <wtf/NeverDestroyed.h>
39
40 namespace WebCore {
41
42 HashMap<const RenderLayer*, std::unique_ptr<RenderLayer::FilterInfo>>& RenderLayer::FilterInfo::map()
43 {
44     static NeverDestroyed<HashMap<const RenderLayer*, std::unique_ptr<FilterInfo>>> map;
45     return map;
46 }
47
48 RenderLayer::FilterInfo* RenderLayer::FilterInfo::getIfExists(const RenderLayer& layer)
49 {
50     ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
51
52     return layer.m_hasFilterInfo ? map().get(&layer) : nullptr;
53 }
54
55 RenderLayer::FilterInfo& RenderLayer::FilterInfo::get(RenderLayer& layer)
56 {
57     ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
58
59     auto& info = map().add(&layer, nullptr).iterator->value;
60     if (!info) {
61         info = std::make_unique<FilterInfo>(layer);
62         layer.m_hasFilterInfo = true;
63     }
64     return *info;
65 }
66
67 void RenderLayer::FilterInfo::remove(RenderLayer& layer)
68 {
69     ASSERT(layer.m_hasFilterInfo == map().contains(&layer));
70     if (!layer.m_hasFilterInfo)
71         return;
72
73     map().remove(&layer);
74     layer.m_hasFilterInfo = false;
75 }
76
77 RenderLayer::FilterInfo::FilterInfo(RenderLayer& layer)
78     : m_layer(layer)
79 {
80 }
81
82 RenderLayer::FilterInfo::~FilterInfo()
83 {
84     removeReferenceFilterClients();
85 }
86
87 void RenderLayer::FilterInfo::setFilter(RefPtr<CSSFilter>&& filter)
88 {
89     m_filter = filter;
90 }
91
92 void RenderLayer::FilterInfo::notifyFinished(CachedResource&)
93 {
94     m_layer.filterNeedsRepaint();
95 }
96
97 void RenderLayer::FilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
98 {
99     removeReferenceFilterClients();
100     for (auto& operation : operations.operations()) {
101         if (!is<ReferenceFilterOperation>(*operation))
102             continue;
103         auto& referenceOperation = downcast<ReferenceFilterOperation>(*operation);
104         auto* documentReference = referenceOperation.cachedSVGDocumentReference();
105         if (auto* cachedSVGDocument = documentReference ? documentReference->document() : nullptr) {
106             // Reference is external; wait for notifyFinished().
107             cachedSVGDocument->addClient(*this);
108             m_externalSVGReferences.append(cachedSVGDocument);
109         } else {
110             // Reference is internal; add layer as a client so we can trigger filter repaint on SVG attribute change.
111             auto* filterElement = m_layer.renderer().document().getElementById(referenceOperation.fragment());
112             if (!filterElement)
113                 continue;
114             auto* renderer = filterElement->renderer();
115             if (!is<RenderSVGResourceFilter>(renderer))
116                 continue;
117             downcast<RenderSVGResourceFilter>(*renderer).addClientRenderLayer(&m_layer);
118             m_internalSVGReferences.append(filterElement);
119         }
120     }
121 }
122
123 void RenderLayer::FilterInfo::removeReferenceFilterClients()
124 {
125     for (auto& resourceHandle : m_externalSVGReferences)
126         resourceHandle->removeClient(*this);
127
128     m_externalSVGReferences.clear();
129
130     for (auto& filterElement : m_internalSVGReferences) {
131         if (auto* renderer = filterElement->renderer())
132             downcast<RenderSVGResourceContainer>(*renderer).removeClientRenderLayer(&m_layer);
133     }
134     m_internalSVGReferences.clear();
135 }
136
137 } // namespace WebCore