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 #include "core/rendering/RenderLayerFilterInfo.h" 33 34 #include "core/fetch/DocumentResourceReference.h" 35 #include "core/rendering/FilterEffectRenderer.h" 36 #include "core/rendering/RenderLayer.h" 37 #include "core/rendering/svg/ReferenceFilterBuilder.h" 38 #include "core/rendering/svg/RenderSVGResourceContainer.h" 39 #include "core/svg/SVGFilterElement.h" 40 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" 41 #include "core/svg/graphics/filters/SVGFilter.h" 42 #include "platform/graphics/filters/custom/CustomFilterOperation.h" 43 #include "platform/graphics/filters/custom/CustomFilterProgram.h" 44 45 namespace WebCore { 46 47 RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0; 48 49 RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer) 50 { 51 if (!s_filterMap) 52 return 0; 53 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 54 return (iter != s_filterMap->end()) ? iter->value : 0; 55 } 56 57 RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer) 58 { 59 if (!s_filterMap) 60 s_filterMap = new RenderLayerFilterInfoMap(); 61 62 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 63 if (iter != s_filterMap->end()) { 64 ASSERT(layer->hasFilterInfo()); 65 return iter->value; 66 } 67 68 RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer); 69 s_filterMap->set(layer, filter); 70 layer->setHasFilterInfo(true); 71 return filter; 72 } 73 74 void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer) 75 { 76 if (!s_filterMap) 77 return; 78 RenderLayerFilterInfo* filter = s_filterMap->take(layer); 79 if (s_filterMap->isEmpty()) { 80 delete s_filterMap; 81 s_filterMap = 0; 82 } 83 if (!filter) { 84 ASSERT(!layer->hasFilterInfo()); 85 return; 86 } 87 layer->setHasFilterInfo(false); 88 delete filter; 89 } 90 91 RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer) 92 : m_layer(layer) 93 { 94 } 95 96 RenderLayerFilterInfo::~RenderLayerFilterInfo() 97 { 98 removeCustomFilterClients(); 99 removeReferenceFilterClients(); 100 } 101 102 void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer) 103 { 104 m_renderer = renderer; 105 } 106 107 void RenderLayerFilterInfo::notifyFinished(Resource*) 108 { 109 RenderObject* renderer = m_layer->renderer(); 110 toElement(renderer->node())->scheduleLayerUpdate(); 111 renderer->repaint(); 112 } 113 114 void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations) 115 { 116 removeReferenceFilterClients(); 117 for (size_t i = 0; i < operations.size(); ++i) { 118 RefPtr<FilterOperation> filterOperation = operations.operations().at(i); 119 if (filterOperation->type() != FilterOperation::REFERENCE) 120 continue; 121 ReferenceFilterOperation* referenceFilterOperation = toReferenceFilterOperation(filterOperation.get()); 122 DocumentResourceReference* documentReference = ReferenceFilterBuilder::documentResourceReference(referenceFilterOperation); 123 DocumentResource* cachedSVGDocument = documentReference ? documentReference->document() : 0; 124 125 if (cachedSVGDocument) { 126 // Reference is external; wait for notifyFinished(). 127 cachedSVGDocument->addClient(this); 128 m_externalSVGReferences.append(cachedSVGDocument); 129 } else { 130 // Reference is internal; add layer as a client so we can trigger 131 // filter repaint on SVG attribute change. 132 Element* filter = m_layer->renderer()->node()->document().getElementById(referenceFilterOperation->fragment()); 133 if (!filter || !filter->hasTagName(SVGNames::filterTag)) 134 continue; 135 if (filter->renderer()) 136 toRenderSVGResourceContainer(filter->renderer())->addClientRenderLayer(m_layer); 137 else 138 toSVGFilterElement(filter)->addClient(m_layer->renderer()->node()); 139 m_internalSVGReferences.append(filter); 140 } 141 } 142 } 143 144 void RenderLayerFilterInfo::removeReferenceFilterClients() 145 { 146 for (size_t i = 0; i < m_externalSVGReferences.size(); ++i) 147 m_externalSVGReferences.at(i)->removeClient(this); 148 m_externalSVGReferences.clear(); 149 for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) { 150 Element* filter = m_internalSVGReferences.at(i).get(); 151 if (filter->renderer()) 152 toRenderSVGResourceContainer(filter->renderer())->removeClientRenderLayer(m_layer); 153 else 154 toSVGFilterElement(filter)->removeClient(m_layer->renderer()->node()); 155 } 156 m_internalSVGReferences.clear(); 157 } 158 159 void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*) 160 { 161 RenderObject* renderer = m_layer->renderer(); 162 toElement(renderer->node())->scheduleLayerUpdate(); 163 renderer->repaint(); 164 } 165 166 void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations) 167 { 168 if (!operations.size()) { 169 removeCustomFilterClients(); 170 return; 171 } 172 CustomFilterProgramList cachedCustomFilterPrograms; 173 for (size_t i = 0; i < operations.size(); ++i) { 174 const FilterOperation* filterOperation = operations.at(i); 175 if (filterOperation->type() != FilterOperation::CUSTOM) 176 continue; 177 RefPtr<CustomFilterProgram> program = toCustomFilterOperation(filterOperation)->program(); 178 cachedCustomFilterPrograms.append(program); 179 program->addClient(this); 180 } 181 // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged. 182 removeCustomFilterClients(); 183 m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms); 184 } 185 186 void RenderLayerFilterInfo::removeCustomFilterClients() 187 { 188 for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i) 189 m_cachedCustomFilterPrograms.at(i)->removeClient(this); 190 m_cachedCustomFilterPrograms.clear(); 191 } 192 193 } // namespace WebCore 194 195