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/loader/cache/DocumentResource.h" 35 #include "core/loader/cache/DocumentResourceReference.h" 36 #include "core/platform/graphics/filters/custom/CustomFilterOperation.h" 37 #include "core/platform/graphics/filters/custom/CustomFilterProgram.h" 38 #include "core/rendering/FilterEffectRenderer.h" 39 #include "core/rendering/RenderLayer.h" 40 #include "core/rendering/svg/RenderSVGResourceContainer.h" 41 #include "core/svg/SVGElement.h" 42 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" 43 #include "core/svg/graphics/filters/SVGFilter.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->getOperationType() != FilterOperation::REFERENCE) 120 continue; 121 ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation.get()); 122 DocumentResourceReference* documentReference = referenceFilterOperation->documentResourceReference(); 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->renderer() || !filter->renderer()->isSVGResourceFilter()) 134 continue; 135 filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(m_layer); 136 m_internalSVGReferences.append(filter); 137 } 138 } 139 } 140 141 void RenderLayerFilterInfo::removeReferenceFilterClients() 142 { 143 for (size_t i = 0; i < m_externalSVGReferences.size(); ++i) 144 m_externalSVGReferences.at(i)->removeClient(this); 145 m_externalSVGReferences.clear(); 146 for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) { 147 Element* filter = m_internalSVGReferences.at(i).get(); 148 if (!filter->renderer()) 149 continue; 150 filter->renderer()->toRenderSVGResourceContainer()->removeClientRenderLayer(m_layer); 151 } 152 m_internalSVGReferences.clear(); 153 } 154 155 void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*) 156 { 157 RenderObject* renderer = m_layer->renderer(); 158 toElement(renderer->node())->scheduleLayerUpdate(); 159 renderer->repaint(); 160 } 161 162 void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations) 163 { 164 if (!operations.size()) { 165 removeCustomFilterClients(); 166 return; 167 } 168 CustomFilterProgramList cachedCustomFilterPrograms; 169 for (size_t i = 0; i < operations.size(); ++i) { 170 const FilterOperation* filterOperation = operations.at(i); 171 if (filterOperation->getOperationType() != FilterOperation::CUSTOM) 172 continue; 173 const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation); 174 RefPtr<CustomFilterProgram> program = customFilterOperation->program(); 175 cachedCustomFilterPrograms.append(program); 176 program->addClient(this); 177 } 178 // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged. 179 removeCustomFilterClients(); 180 m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms); 181 } 182 183 void RenderLayerFilterInfo::removeCustomFilterClients() 184 { 185 for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i) 186 m_cachedCustomFilterPrograms.at(i)->removeClient(this); 187 m_cachedCustomFilterPrograms.clear(); 188 } 189 190 } // namespace WebCore 191 192