void RenderLayer::FilterInfo::updateReferenceFilterClients(const FilterOperations& operations) { removeReferenceFilterClients(); for (size_t i = 0, size = operations.size(); i < size; ++i) { FilterOperation* filterOperation = operations.operations()[i].get(); if (filterOperation->getOperationType() != FilterOperation::REFERENCE) continue; ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation); CachedSVGDocumentReference* documentReference = referenceFilterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : 0; if (cachedSVGDocument) { // Reference is external; wait for notifyFinished(). cachedSVGDocument->addClient(this); m_externalSVGReferences.append(cachedSVGDocument); } else { // Reference is internal; add layer as a client so we can trigger // filter repaint on SVG attribute change. Element* filter = m_layer.renderer().node()->document().getElementById(referenceFilterOperation->fragment()); if (!filter || !filter->renderer() || !filter->renderer()->isSVGResourceFilter()) continue; filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(&m_layer); m_internalSVGReferences.append(filter); } } }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { #if ENABLE(SVG) if (!renderer) return 0; Document* document = &renderer->document(); CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0; // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) document = cachedSVGDocument->document(); if (!document) return 0; Element* filter = document->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later // in the document document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), toElement(renderer->node())); return 0; } RefPtr<FilterEffect> effect; // FIXME: Figure out what to do with SourceAlpha. Right now, we're // using the alpha of the original input layer, which is obviously // wrong. We should probably be extracting the alpha from the // previousEffect, but this requires some more processing. // This may need a spec clarification. RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(this)); for (SVGElement* svgElement = Traversal<SVGElement>::firstChild(filter); svgElement; svgElement = Traversal<SVGElement>::nextSibling(svgElement)) { if (!svgElement->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(svgElement); effect = effectElement->build(builder.get(), this); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); builder->add(effectElement->result(), effect); m_effects.append(effect); } return effect; #else UNUSED_PARAM(renderer); UNUSED_PARAM(previousEffect); UNUSED_PARAM(filterOperation); return 0; #endif }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderElement* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { #if ENABLE(SVG) if (!renderer) return 0; Document* document = &renderer->document(); CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0; // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) document = cachedSVGDocument->document(); if (!document) return 0; Element* filter = document->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later // in the document document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), renderer->element()); return 0; } RefPtr<FilterEffect> effect; // FIXME: Figure out what to do with SourceAlpha. Right now, we're // using the alpha of the original input layer, which is obviously // wrong. We should probably be extracting the alpha from the // previousEffect, but this requires some more processing. // This may need a spec clarification. auto builder = std::make_unique<SVGFilterBuilder>(previousEffect, SourceAlpha::create(this)); auto attributesChildren = childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filter); for (auto it = attributesChildren.begin(), end = attributesChildren.end(); it != end; ++it) { SVGFilterPrimitiveStandardAttributes* effectElement = &*it; effect = effectElement->build(builder.get(), this); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); builder->add(effectElement->result(), effect); m_effects.append(effect); } return effect; #else UNUSED_PARAM(renderer); UNUSED_PARAM(previousEffect); UNUSED_PARAM(filterOperation); return 0; #endif }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(Document* document, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { #if ENABLE(SVG) CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0; // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) document = cachedSVGDocument->document(); if (!document) return 0; Element* filter = document->getElementById(filterOperation->fragment()); if (!filter) return 0; RefPtr<FilterEffect> effect; // FIXME: Figure out what to do with SourceAlpha. Right now, we're // using the alpha of the original input layer, which is obviously // wrong. We should probably be extracting the alpha from the // previousEffect, but this requires some more processing. // This may need a spec clarification. RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(this)); for (Node* node = filter->firstChild(); node; node = node->nextSibling()) { if (!node->isSVGElement()) continue; SVGElement* element = static_cast<SVGElement*>(node); if (!element->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); effect = effectElement->build(builder.get(), this); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); builder->add(effectElement->result(), effect); m_effects.append(effect); } return effect; #else UNUSED_PARAM(document); UNUSED_PARAM(previousEffect); UNUSED_PARAM(filterOperation); return 0; #endif }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderElement* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { if (!renderer) return 0; Document* document = &renderer->document(); CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0; // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) document = cachedSVGDocument->document(); if (!document) return 0; Element* filter = document->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later in the document. // FIXME: This skips anonymous RenderObjects. <https://webkit.org/b/131085> if (Element* element = renderer->element()) document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), element); return 0; } RefPtr<FilterEffect> effect; // FIXME: Figure out what to do with SourceAlpha. Right now, we're // using the alpha of the original input layer, which is obviously // wrong. We should probably be extracting the alpha from the // previousEffect, but this requires some more processing. // This may need a spec clarification. auto builder = std::make_unique<SVGFilterBuilder>(previousEffect, SourceAlpha::create(this)); for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filter)) { effect = effectElement.build(builder.get(), this); if (!effect) continue; effectElement.setStandardAttributes(effect.get()); builder->add(effectElement.result(), effect); m_effects.append(effect); } return effect; }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderElement* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { if (!renderer) return nullptr; Document* document = &renderer->document(); CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0; // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) document = cachedSVGDocument->document(); if (!document) return nullptr; Element* filter = document->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later in the document. // FIXME: This skips anonymous RenderObjects. <https://webkit.org/b/131085> if (Element* element = renderer->element()) document->accessSVGExtensions().addPendingResource(filterOperation->fragment(), element); return nullptr; } RefPtr<FilterEffect> effect; auto builder = std::make_unique<SVGFilterBuilder>(previousEffect); for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filter)) { effect = effectElement.build(builder.get(), *this); if (!effect) continue; effectElement.setStandardAttributes(effect.get()); builder->add(effectElement.result(), effect); m_effects.append(effect); } return effect; }
void MaskImageOperation::notifyFinished(CachedResource* resource) { // The only one notifying us should be the SVG document we hold. CachedSVGDocument* cachedSVGDocument = ensureCachedSVGDocumentReference()->document(); if ((CachedResource*)cachedSVGDocument != resource || !resource) { ASSERT_NOT_REACHED(); return; } // Check if we find a valid masking element in this SVG document. SVGDocument* svgDocument = cachedSVGDocument->document(); bool validMaskFound = false; if (svgDocument && svgDocument->rootElement()) { // Are we looking for a specific element in the SVG document? if (fragment().length()) { if (Element* maskingElement = svgDocument->rootElement()->getElementById(fragment())) { if (is<SVGMaskElement>(maskingElement)) validMaskFound = true; } } } // If no valid mask was found, this is not a valid SVG document or it specified an invalid fragment identifier. // Fallback to the normal way of loading the document in an Image object. if (!validMaskFound) { // Get the resource loader, acquire the resource buffer and load it into an image. ASSERT(cachedSVGDocument->loader()); if (SubresourceLoader* loader = cachedSVGDocument->loader()) { if (SharedBuffer* dataBuffer = loader->resourceData()) { m_styleImage = StyleCachedImage::create(new CachedImage(cachedSVGDocument->resourceRequest(), cachedSVGDocument->sessionID())); if (m_renderLayerImageClient) m_styleImage->cachedImage()->addClient(m_renderLayerImageClient); for (auto itClient : m_rendererImageClients) m_styleImage->addClient(itClient.key); m_styleImage->cachedImage()->setResponse(cachedSVGDocument->response()); m_styleImage->cachedImage()->finishLoading(dataBuffer); // Let the cached resource loader of the document which requested this mask keep a handle to this // cached image to ensure it only gets deleted when it should. if (m_cachedResourceLoader.get()) m_cachedResourceLoader->addCachedResource(*m_styleImage->cachedImage()); } // Destroy the current SVG document as its no longer needed m_cachedSVGDocumentReference = nullptr; } } }