Beispiel #1
0
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);
        }
    }
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #5
0
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;
        }
    }
}