PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) { SVGFilterElement* filterElement = toSVGFilterElement(node()); FloatRect targetBoundingBox = filter->targetBoundingBox(); // Add effects to the builder RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter)); for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) { if (!node->isSVGElement()) continue; SVGElement* element = toSVGElement(node); if (!element->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); if (!effect) { builder->clearEffects(); return 0; } builder->appendEffectToEffectReferences(effect, effectElement->renderer()); effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), targetBoundingBox)); effect->setOperatingColorSpace( effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); builder->add(effectElement->result(), effect); } return builder.release(); }
PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) { SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); FloatRect targetBoundingBox = filter->targetBoundingBox(); // Add effects to the builder RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter); for (Node* node = filterElement->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); RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); if (!effect) { builder->clearEffects(); return 0; } builder->appendEffectToEffectReferences(effect, effectElement->renderer()); effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), targetBoundingBox)); builder->add(effectElement->result(), effect); } return builder.release(); }
PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(Filter* filter) { SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; // Add effects to the builder RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter); for (Node* node = filterElement->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); RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter); if (!effect) { builder->clearEffects(); return 0; } builder->appendEffectToEffectReferences(effect); effectElement->setStandardAttributes(primitiveBoundingBoxMode, effect.get()); builder->add(effectElement->result(), effect); } return builder.release(); }
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(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 }
void SVGFilterElement::buildFilter(const FloatRect& targetRect) const { bool filterBBoxMode = filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; bool primitiveBBoxMode = primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; FloatRect filterBBox; if (filterBBoxMode) filterBBox = FloatRect(x().valueAsPercentage(), y().valueAsPercentage(), width().valueAsPercentage(), height().valueAsPercentage()); else filterBBox = FloatRect(x().value(this), y().value(this), width().value(this), height().value(this)); FloatRect filterRect = filterBBox; if (filterBBoxMode) filterRect = FloatRect(targetRect.x() + filterRect.x() * targetRect.width(), targetRect.y() + filterRect.y() * targetRect.height(), filterRect.width() * targetRect.width(), filterRect.height() * targetRect.height()); m_filter->setFilterBoundingBox(filterRect); m_filter->setFilterRect(filterBBox); m_filter->setEffectBoundingBoxMode(primitiveBBoxMode); m_filter->setFilterBoundingBoxMode(filterBBoxMode); if (hasAttribute(SVGNames::filterResAttr)) { m_filter->setHasFilterResolution(true); m_filter->setFilterResolution(FloatSize(filterResX(), filterResY())); } // Add effects to the filter m_filter->builder()->clearEffects(); for (Node* n = firstChild(); n != 0; n = n->nextSibling()) { SVGElement* element = 0; if (n->isSVGElement()) { element = static_cast<SVGElement*>(n); if (element->isFilterEffect()) { SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); if (!effectElement->build(m_filter.get())) { m_filter->builder()->clearEffects(); break; } } } } }
PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, RenderObject* renderer, FilterEffect* previousEffect, const ReferenceFilterOperation* filterOperation) { if (!renderer) return nullptr; TreeScope* treeScope = &renderer->node()->treeScope(); if (DocumentResourceReference* documentResourceRef = documentResourceReference(filterOperation)) { DocumentResource* cachedSVGDocument = documentResourceRef->document(); // If we have an SVG document, this is an external reference. Otherwise // we look up the referenced node in the current document. if (cachedSVGDocument) treeScope = cachedSVGDocument->document(); } if (!treeScope) return nullptr; Element* filter = treeScope->getElementById(filterOperation->fragment()); if (!filter) { // Although we did not find the referenced filter, it might exist later // in the document. treeScope->document().accessSVGExtensions().addPendingResource(filterOperation->fragment(), toElement(renderer->node())); return nullptr; } if (!isSVGFilterElement(*filter)) return nullptr; SVGFilterElement& filterElement = toSVGFilterElement(*filter); // 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(parentFilter)); ColorSpace filterColorSpace = ColorSpaceDeviceRGB; bool useFilterColorSpace = getSVGElementColorSpace(&filterElement, filterColorSpace); for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) { if (!element->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); RefPtr<FilterEffect> effect = effectElement->build(builder.get(), parentFilter); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), parentFilter->sourceImageRect())); ColorSpace colorSpace = filterColorSpace; if (useFilterColorSpace || getSVGElementColorSpace(effectElement, colorSpace)) effect->setOperatingColorSpace(colorSpace); builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect); } return builder->lastEffect(); }
PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation) { if (!renderer) return 0; Document* document = renderer->document(); ASSERT(document); CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference(); CachedDocument* 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; } if (!filter->isSVGElement() || !filter->hasTagName(SVGNames::filterTag)) return 0; SVGFilterElement* filterElement = toSVGFilterElement(toSVGElement(filter)); 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 = filterElement->firstChild(); node; node = node->nextSibling()) { if (!node->isSVGElement()) continue; SVGElement* element = toSVGElement(node); if (!element->isFilterEffect()) continue; SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element); effect = effectElement->build(builder.get(), this); if (!effect) continue; effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), sourceImageRect())); builder->add(effectElement->result(), effect); m_effects.append(effect); } return effect; }