Make CachedSVGDocumentReference independent of FilterOperation
[WebKit-https.git] / Source / WebCore / rendering / RenderLayerFilterInfo.cpp
1 /*
2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials
14  *    provided with the distribution.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include "config.h"
31
32 #if ENABLE(CSS_FILTERS)
33 #include "RenderLayerFilterInfo.h"
34
35 #include "FilterEffectRenderer.h"
36 #include "RenderLayer.h"
37
38 #if ENABLE(SVG)
39 #include "CachedSVGDocument.h"
40 #include "CachedSVGDocumentReference.h"
41 #include "SVGElement.h"
42 #include "SVGFilter.h"
43 #include "SVGFilterPrimitiveStandardAttributes.h"
44 #endif
45
46 #if ENABLE(CSS_SHADERS)
47 #include "CustomFilterOperation.h"
48 #include "CustomFilterProgram.h"
49 #endif
50
51 namespace WebCore {
52
53 RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0;
54
55 RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer)
56 {
57     if (!s_filterMap)
58         return 0;
59     RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
60     return (iter != s_filterMap->end()) ? iter->value : 0;
61 }
62
63 RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer)
64 {
65     if (!s_filterMap)
66         s_filterMap = new RenderLayerFilterInfoMap();
67     
68     RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
69     if (iter != s_filterMap->end()) {
70         ASSERT(layer->hasFilterInfo());
71         return iter->value;
72     }
73     
74     RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer);
75     s_filterMap->set(layer, filter);
76     layer->setHasFilterInfo(true);
77     return filter;
78 }
79
80 void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer)
81 {
82     if (!s_filterMap)
83         return;
84     RenderLayerFilterInfo* filter = s_filterMap->take(layer);
85     if (s_filterMap->isEmpty()) {
86         delete s_filterMap;
87         s_filterMap = 0;
88     }
89     if (!filter) {
90         ASSERT(!layer->hasFilterInfo());
91         return;
92     }
93     layer->setHasFilterInfo(false);
94     delete filter;
95 }
96
97 RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
98     : m_layer(layer)
99 {
100 }
101
102 RenderLayerFilterInfo::~RenderLayerFilterInfo()
103 {
104 #if ENABLE(CSS_SHADERS)
105     removeCustomFilterClients();
106 #endif
107 #if ENABLE(SVG)
108     removeReferenceFilterClients();
109 #endif
110 }
111
112 void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer)
113
114     m_renderer = renderer; 
115 }
116
117 #if ENABLE(SVG)
118 void RenderLayerFilterInfo::notifyFinished(CachedResource*)
119 {
120     RenderObject* renderer = m_layer->renderer();
121     renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
122     renderer->repaint();
123 }
124
125 void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
126 {
127     removeReferenceFilterClients();
128     for (size_t i = 0; i < operations.size(); ++i) {
129         RefPtr<FilterOperation> filterOperation = operations.operations().at(i);
130         if (filterOperation->getOperationType() != FilterOperation::REFERENCE)
131             continue;
132         ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation.get());
133         CachedSVGDocumentReference* documentReference = referenceFilterOperation->cachedSVGDocumentReference();
134         CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : 0;
135
136         if (cachedSVGDocument) {
137             // Reference is external; wait for notifyFinished().
138             cachedSVGDocument->addClient(this);
139             m_externalSVGReferences.append(cachedSVGDocument);
140         } else {
141             // Reference is internal; add layer as a client so we can trigger
142             // filter repaint on SVG attribute change.
143             Element* filter = m_layer->renderer()->node()->document()->getElementById(referenceFilterOperation->fragment());
144             if (!filter || !filter->renderer() || !filter->renderer()->isSVGResourceFilter())
145                 continue;
146             filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(m_layer);
147             m_internalSVGReferences.append(filter);
148         }
149     }
150 }
151
152 void RenderLayerFilterInfo::removeReferenceFilterClients()
153 {
154     for (size_t i = 0; i < m_externalSVGReferences.size(); ++i)
155         m_externalSVGReferences.at(i)->removeClient(this);
156     m_externalSVGReferences.clear();
157     for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) {
158         Element* filter = m_internalSVGReferences.at(i).get();
159         if (!filter->renderer())
160             continue;
161         filter->renderer()->toRenderSVGResourceContainer()->removeClientRenderLayer(m_layer);
162     }
163     m_internalSVGReferences.clear();
164 }
165 #endif
166
167 #if ENABLE(CSS_SHADERS)
168 void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
169 {
170     RenderObject* renderer = m_layer->renderer();
171     renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
172     renderer->repaint();
173 }
174
175 void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations)
176 {
177     if (!operations.size()) {
178         removeCustomFilterClients();
179         return;
180     }
181     CustomFilterProgramList cachedCustomFilterPrograms;
182     for (size_t i = 0; i < operations.size(); ++i) {
183         const FilterOperation* filterOperation = operations.at(i);
184         if (filterOperation->getOperationType() != FilterOperation::CUSTOM)
185             continue;
186         const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation);
187         RefPtr<CustomFilterProgram> program = customFilterOperation->program();
188         cachedCustomFilterPrograms.append(program);
189         program->addClient(this);
190     }
191     // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged.
192     removeCustomFilterClients();
193     m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
194 }
195
196 void RenderLayerFilterInfo::removeCustomFilterClients()
197 {
198     for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i)
199         m_cachedCustomFilterPrograms.at(i)->removeClient(this);
200     m_cachedCustomFilterPrograms.clear();
201 }
202 #endif
203
204 } // namespace WebCore
205
206 #endif // ENABLE(CSS_FILTERS)