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 43 namespace blink { 44 45 RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0; 46 47 RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer) 48 { 49 if (!s_filterMap) 50 return 0; 51 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 52 return (iter != s_filterMap->end()) ? iter->value : 0; 53 } 54 55 RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer) 56 { 57 if (!s_filterMap) 58 s_filterMap = new RenderLayerFilterInfoMap(); 59 60 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 61 if (iter != s_filterMap->end()) { 62 ASSERT(layer->hasFilterInfo()); 63 return iter->value; 64 } 65 66 RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer); 67 s_filterMap->set(layer, filter); 68 layer->setHasFilterInfo(true); 69 return filter; 70 } 71 72 void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer) 73 { 74 if (!s_filterMap) 75 return; 76 RenderLayerFilterInfo* filter = s_filterMap->take(layer); 77 if (s_filterMap->isEmpty()) { 78 delete s_filterMap; 79 s_filterMap = 0; 80 } 81 if (!filter) { 82 ASSERT(!layer->hasFilterInfo()); 83 return; 84 } 85 layer->setHasFilterInfo(false); 86 delete filter; 87 } 88 89 RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer) 90 : m_layer(layer) 91 { 92 } 93 94 RenderLayerFilterInfo::~RenderLayerFilterInfo() 95 { 96 removeReferenceFilterClients(); 97 } 98 99 void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer) 100 { 101 m_renderer = renderer; 102 } 103 104 void RenderLayerFilterInfo::notifyFinished(Resource*) 105 { 106 RenderObject* renderer = m_layer->renderer(); 107 // FIXME: This caller of scheduleSVGFilterLayerUpdateHack() is not correct. It's using the layer update 108 // system to trigger a RenderLayer to go through the filter updating logic, but that might not 109 // even happen if this element is style sharing and RenderObject::setStyle() returns early. 110 // Filters need to find a better way to hook into the system. 111 toElement(renderer->node())->scheduleSVGFilterLayerUpdateHack(); 112 renderer->setShouldDoFullPaintInvalidation(true); 113 } 114 115 void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations) 116 { 117 removeReferenceFilterClients(); 118 for (size_t i = 0; i < operations.size(); ++i) { 119 RefPtr<FilterOperation> filterOperation = operations.operations().at(i); 120 if (filterOperation->type() != FilterOperation::REFERENCE) 121 continue; 122 ReferenceFilterOperation* referenceFilterOperation = toReferenceFilterOperation(filterOperation.get()); 123 DocumentResourceReference* documentReference = ReferenceFilterBuilder::documentResourceReference(referenceFilterOperation); 124 DocumentResource* cachedSVGDocument = documentReference ? documentReference->document() : 0; 125 126 if (cachedSVGDocument) { 127 // Reference is external; wait for notifyFinished(). 128 cachedSVGDocument->addClient(this); 129 m_externalSVGReferences.append(cachedSVGDocument); 130 } else { 131 // Reference is internal; add layer as a client so we can trigger 132 // filter paint invalidation on SVG attribute change. 133 Element* filter = m_layer->renderer()->node()->document().getElementById(referenceFilterOperation->fragment()); 134 if (!isSVGFilterElement(filter)) 135 continue; 136 if (filter->renderer()) 137 toRenderSVGResourceContainer(filter->renderer())->addClientRenderLayer(m_layer); 138 else 139 toSVGFilterElement(filter)->addClient(m_layer->renderer()->node()); 140 m_internalSVGReferences.append(filter); 141 } 142 } 143 } 144 145 void RenderLayerFilterInfo::removeReferenceFilterClients() 146 { 147 for (size_t i = 0; i < m_externalSVGReferences.size(); ++i) 148 m_externalSVGReferences.at(i)->removeClient(this); 149 m_externalSVGReferences.clear(); 150 for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) { 151 Element* filter = m_internalSVGReferences.at(i).get(); 152 if (filter->renderer()) 153 toRenderSVGResourceContainer(filter->renderer())->removeClientRenderLayer(m_layer); 154 else 155 toSVGFilterElement(filter)->removeClient(m_layer->renderer()->node()); 156 } 157 m_internalSVGReferences.clear(); 158 } 159 160 } // namespace blink 161 162