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<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();
}
Example #3
0
JSValue jsSVGFilterElementClassName(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(asObject(slot.slotBase()))->impl());
    RefPtr<SVGAnimatedString> obj = imp->classNameAnimated();
    return toJS(exec, obj.get(), imp);
}
Example #4
0
JSValue jsSVGFilterElementExternalResourcesRequired(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(asObject(slot.slotBase()))->impl());
    RefPtr<SVGAnimatedBoolean> obj = imp->externalResourcesRequiredAnimated();
    return toJS(exec, obj.get(), imp);
}
JSValue* JSSVGFilterElementPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
{
    if (!thisObj->inherits(&JSSVGFilterElement::info))
      return throwError(exec, TypeError);

    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(thisObj)->impl());

    switch (id) {
    case JSSVGFilterElement::SetFilterResFuncNum: {
        bool filterResXOk;
        unsigned filterResX = args[0]->toInt32(exec, filterResXOk);
        if (!filterResXOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }
        bool filterResYOk;
        unsigned filterResY = args[1]->toInt32(exec, filterResYOk);
        if (!filterResYOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }

        imp->setFilterRes(filterResX, filterResY);
        return jsUndefined();
    }
    }
    return 0;
}
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();
}
Example #7
0
JSValue jsSVGFilterElementXmlspace(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    JSValue result = jsString(exec, imp->xmlspace());
    return result;
}
Example #8
0
JSValue jsSVGFilterElementStyle(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->style()));
    return result;
}
Example #9
0
JSValue jsSVGFilterElementPrimitiveUnits(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    RefPtr<SVGAnimatedEnumeration> obj = imp->primitiveUnitsAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());
    return result;
}
Example #10
0
JSValue jsSVGFilterElementExternalResourcesRequired(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    RefPtr<SVGAnimatedBoolean> obj = imp->externalResourcesRequiredAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());
    return result;
}
Example #11
0
JSValue jsSVGFilterElementClassName(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    RefPtr<SVGAnimatedString> obj = imp->classNameAnimated();
    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());
    return result;
}
GraphicsContext* SVGFilterPainter::prepareEffect(const LayoutObject& object, SVGFilterRecordingContext& recordingContext)
{
    ASSERT(recordingContext.paintingContext());

    m_filter.clearInvalidationMask();

    if (FilterData* filterData = m_filter.getFilterDataForLayoutObject(&object)) {
        // If the filterData already exists we do not need to record the content
        // to be filtered. This can occur if the content was previously recorded
        // or we are in a cycle.
        if (filterData->m_state == FilterData::PaintingFilter)
            filterData->m_state = FilterData::PaintingFilterCycleDetected;

        if (filterData->m_state == FilterData::RecordingContent)
            filterData->m_state = FilterData::RecordingContentCycleDetected;

        return nullptr;
    }

    OwnPtrWillBeRawPtr<FilterData> filterData = FilterData::create();
    FloatRect referenceBox = object.objectBoundingBox();

    SVGFilterElement* filterElement = toSVGFilterElement(m_filter.element());
    FloatRect filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), referenceBox);
    if (filterRegion.isEmpty())
        return nullptr;

    // Create the SVGFilter object.
    bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    Filter::UnitScaling unitScaling = primitiveBoundingBoxMode ? Filter::BoundingBox : Filter::UserSpace;
    filterData->filter = Filter::create(referenceBox, filterRegion, 1, unitScaling);
    filterData->nodeMap = SVGFilterGraphNodeMap::create();

    IntRect sourceRegion = enclosingIntRect(intersection(filterRegion, object.strokeBoundingBox()));
    filterData->filter->sourceGraphic()->setSourceRect(sourceRegion);

    // Create all relevant filter primitives.
    SVGFilterBuilder builder(filterData->filter->sourceGraphic(), filterData->nodeMap.get());
    builder.buildGraph(filterData->filter.get(), *filterElement, referenceBox);

    FilterEffect* lastEffect = builder.lastEffect();
    if (!lastEffect)
        return nullptr;

    lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
    filterData->filter->setLastEffect(lastEffect);

    FilterData* data = filterData.get();
    // TODO(pdr): Can this be moved out of painter?
    m_filter.setFilterDataForLayoutObject(const_cast<LayoutObject*>(&object), filterData.release());
    return recordingContext.beginContent(data);
}
Example #13
0
JSValue JSC_HOST_CALL jsSVGFilterElementPrototypeFunctionGetPresentationAttribute(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.isObject(&JSSVGFilterElement::s_info))
        return throwError(exec, TypeError);
    JSSVGFilterElement* castedThisObj = static_cast<JSSVGFilterElement*>(asObject(thisValue));
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThisObj->impl());
    const UString& name = args.at(0).toString(exec);


    JSC::JSValue result = toJS(exec, WTF::getPtr(imp->getPresentationAttribute(name)));
    return result;
}
Example #14
0
JSValue JSC_HOST_CALL jsSVGFilterElementPrototypeFunctionSetFilterRes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
    UNUSED_PARAM(args);
    if (!thisValue.isObject(&JSSVGFilterElement::s_info))
        return throwError(exec, TypeError);
    JSSVGFilterElement* castedThisObj = static_cast<JSSVGFilterElement*>(asObject(thisValue));
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThisObj->impl());
    unsigned filterResX = args.at(0).toInt32(exec);
    unsigned filterResY = args.at(1).toInt32(exec);

    imp->setFilterRes(filterResX, filterResY);
    return jsUndefined();
}
Example #15
0
EncodedJSValue JSC_HOST_CALL jsSVGFilterElementPrototypeFunctionGetPresentationAttribute(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    if (!thisValue.inherits(&JSSVGFilterElement::s_info))
        return throwVMTypeError(exec);
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(thisValue));
    ASSERT_GC_OBJECT_INHERITS(castedThis, &JSSVGFilterElement::s_info);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    const String& name(ustringToString(exec->argument(0).toString(exec)));
    if (exec->hadException())
        return JSValue::encode(jsUndefined());


    JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->getPresentationAttribute(name)));
    return JSValue::encode(result);
}
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    clearInvalidationMask();

    if (m_filter.contains(object)) {
        FilterData* filterData = m_filter.get(object);
        if (filterData->state == FilterData::PaintingSource)
            filterData->state = FilterData::CycleDetected;
        return false; // Already built, or we're in a cycle. Regardless, just do nothing more now.
    }

    OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
    FloatRect targetBoundingBox = object->objectBoundingBox();

    SVGFilterElement* filterElement = toSVGFilterElement(element());
    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox);
    if (filterData->boundaries.isEmpty())
        return false;

    filterData->drawingRegion = object->strokeBoundingBox();
    filterData->drawingRegion.intersect(filterData->boundaries);
    IntRect intDrawingRegion = enclosingIntRect(filterData->drawingRegion);

    // Create the SVGFilter object.
    bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    filterData->filter = SVGFilter::create(intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);

    // Create all relevant filter primitives.
    filterData->builder = buildPrimitives(filterData->filter.get());
    if (!filterData->builder)
        return false;

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect)
        return false;

    lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);

    FilterData* data = filterData.get();
    m_filter.set(object, filterData.release());
    beginDeferredFilter(context, data);
    return true;
}
Example #17
0
void JSSVGFilterElement::putValueProperty(ExecState* exec, int token, JSValue* value, int /*attr*/)
{
    switch (token) {
    case XmllangAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        imp->setXmllang(value->toString(exec));
        break;
    }
    case XmlspaceAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        imp->setXmlspace(value->toString(exec));
        break;
    }
    }
}
Example #18
0
EncodedJSValue JSC_HOST_CALL jsSVGFilterElementPrototypeFunctionSetFilterRes(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    if (!thisValue.inherits(&JSSVGFilterElement::s_info))
        return throwVMTypeError(exec);
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(asObject(thisValue));
    ASSERT_GC_OBJECT_INHERITS(castedThis, &JSSVGFilterElement::s_info);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    unsigned filterResX(exec->argument(0).toUInt32(exec));
    if (exec->hadException())
        return JSValue::encode(jsUndefined());
    unsigned filterResY(exec->argument(1).toUInt32(exec));
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    imp->setFilterRes(filterResX, filterResY);
    return JSValue::encode(jsUndefined());
}
Example #19
0
void setJSSVGFilterElementXmlspace(ExecState* exec, JSObject* thisObject, JSValue value)
{
    JSSVGFilterElement* castedThis = static_cast<JSSVGFilterElement*>(thisObject);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(castedThis->impl());
    imp->setXmlspace(ustringToString(value.toString(exec)));
}
Example #20
0
JSValue jsSVGFilterElementStyle(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(asObject(slot.slotBase()))->impl());
    return toJS(exec, WTF::getPtr(imp->style()));
}
Example #21
0
void setJSSVGFilterElementXmlspace(ExecState* exec, JSObject* thisObject, JSValue value)
{
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(thisObject)->impl());
    imp->setXmlspace(value.toString(exec));
}
Example #22
0
void PSVGFEElement::CalculatePrimitiveSubRegion(PSVGFilterElement* pFilterElement, PSVGElement* pReferencingElement, /*in,out*/gm::RectF& subRegion)
{
	ISVGFilterPrimitiveStandardAttributes* pStdAttributes = dynamic_cast<ISVGFilterPrimitiveStandardAttributes*>(m_pNode);
	ASSERT(pStdAttributes != NULL);

	SVGFilterElement* psvgFilterElement = static_cast<SVGFilterElement*>(pFilterElement->m_pNode);

	ISVGLength* xLength = pStdAttributes->get_x()->get_animVal();
	ISVGLength* yLength = pStdAttributes->get_y()->get_animVal();
	ISVGLength* widthLength = pStdAttributes->get_width()->get_animVal();
	ISVGLength* heightLength = pStdAttributes->get_height()->get_animVal();

//	RectD filterRegion = pReferencingElement->m_filterRect;

//	RectD subRegion;

	if (psvgFilterElement->primitiveUnits_attr().m_animated->m_animVal->m_value == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
	{
		gm::RectD rect = pReferencingElement->m_bounds;

		if (pStdAttributes->get_xAttr()->get_specified())
		{
			if (xLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.X = rect.X + (xLength->get_valueInSpecifiedUnits() * rect.Width/100);
			else
				subRegion.X = rect.X + (xLength->get_value() * rect.Width);
		}
		//else
		//	subRegion.X = filterRegion.X;

		if (pStdAttributes->get_yAttr()->get_specified())
		{
			if (yLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Y = rect.Y + (yLength->get_valueInSpecifiedUnits() * rect.Height/100);
			else
				subRegion.Y = rect.Y + (yLength->get_value() * rect.Height);
		}
		//else
		//	subRegion.Y = filterRegion.Y;

		if (pStdAttributes->get_widthAttr()->get_specified())
		{
			if (widthLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Width = (widthLength->get_valueInSpecifiedUnits() * rect.Width/100);
			else
				subRegion.Width = (widthLength->get_value() * rect.Width);
		}
		//else
		//	subRegion.Width = filterRegion.Width;

		if (pStdAttributes->get_heightAttr()->get_specified())
		{
			if (heightLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Height = (heightLength->get_valueInSpecifiedUnits() * rect.Height/100);
			else
				subRegion.Height = (heightLength->get_value() * rect.Height);
		}
		//else
		//	subRegion.Height = filterRegion.Height;
	}
	else
	{
		gm::RectD rect = pReferencingElement->GetViewportElement()->GetViewBox();

		if (pStdAttributes->get_xAttr()->get_specified())
		{
			if (xLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.X = rect.X + (xLength->get_valueInSpecifiedUnits() * rect.Width/100);
			else
				subRegion.X = xLength->get_value();
		}
		//else
		//	subRegion.X = filterRegion.X;

		if (pStdAttributes->get_yAttr()->get_specified())
		{
			if (yLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Y = rect.Y + (yLength->get_valueInSpecifiedUnits() * rect.Height/100);
			else
				subRegion.Y = yLength->get_value();
		}
		//else
		//	subRegion.Y = filterRegion.Y;

		if (pStdAttributes->get_widthAttr()->get_specified())
		{
			if (widthLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Width = (widthLength->get_valueInSpecifiedUnits() * rect.Width/100);
			else
				subRegion.Width = widthLength->get_value();
		}
		//else
		//	subRegion.Width = filterRegion.Width;

		if (pStdAttributes->get_heightAttr()->get_specified())
		{
			if (heightLength->get_unitType() == SVG_LENGTHTYPE_PERCENTAGE)
				subRegion.Height = (heightLength->get_valueInSpecifiedUnits() * rect.Height/100);
			else
				subRegion.Height = heightLength->get_value();
		}
		//else
		//	subRegion.Height = filterRegion.Height;
	}

//	return subRegion;
}
Example #23
0
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
#ifndef NDEBUG
    ASSERT(resourceMode == ApplyToDefaultMode);
#else
    UNUSED_PARAM(resourceMode);
#endif

    // Returning false here, to avoid drawings onto the context. We just want to
    // draw the stored filter output, not the unfiltered object as well.
    if (m_filter.contains(object)) {
        FilterData* filterData = m_filter.get(object);
        if (filterData->builded)
            return false;

        delete m_filter.take(object); // Oops, have to rebuild, go through normal code path
    }

    OwnPtr<FilterData> filterData(new FilterData);
    filterData->builder = buildPrimitives();
    if (!filterData->builder)
        return false;

    FloatRect paintRect = object->strokeBoundingBox();

    // Calculate the scale factor for the use of filterRes.
    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
    filterData->boundaries = filterElement->filterBoundingBox(object->objectBoundingBox());
    if (filterData->boundaries.isEmpty())
        return false;

    FloatSize scale(1.0f, 1.0f);
    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
        scale.setWidth(filterElement->filterResX() / filterData->boundaries.width());
        scale.setHeight(filterElement->filterResY() / filterData->boundaries.height());
    }

    if (scale.isEmpty())
        return false;

    // clip sourceImage to filterRegion
    FloatRect clippedSourceRect = paintRect;
    clippedSourceRect.intersect(filterData->boundaries);

    // scale filter size to filterRes
    FloatRect tempSourceRect = clippedSourceRect;

    // scale to big sourceImage size to kMaxFilterSize
    tempSourceRect.scale(scale.width(), scale.height());
    fitsInMaximumImageSize(tempSourceRect.size(), scale);

    // prepare Filters
    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    filterData->filter = SVGFilter::create(paintRect, filterData->boundaries, primitiveBoundingBoxMode);
    filterData->filter->setFilterResolution(scale);

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect)
        return false;
    
    lastEffect->calculateEffectRect(filterData->filter.get());
    // At least one FilterEffect has a too big image size,
    // recalculate the effect sizes with new scale factors.
    if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) {
        filterData->filter->setFilterResolution(scale);
        lastEffect->calculateEffectRect(filterData->filter.get());
    }

    clippedSourceRect.scale(scale.width(), scale.height());

    // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic.
    // The size of the SourceGraphic is clipped to the size of the filterRegion.
    IntRect bufferRect = enclosingIntRect(clippedSourceRect);
    OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB));
    
    if (!sourceGraphic.get())
        return false;

    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
    sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y());
    sourceGraphicContext->scale(scale);
    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size()));
    filterData->sourceGraphicBuffer = sourceGraphic.release();
    filterData->savedContext = context;

    context = sourceGraphicContext;

    ASSERT(!m_filter.contains(object));
    m_filter.set(object, filterData.leakPtr());

    return true;
}
Example #24
0
JSValue jsSVGFilterElementXmlspace(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    UNUSED_PARAM(exec);
    SVGFilterElement* imp = static_cast<SVGFilterElement*>(static_cast<JSSVGFilterElement*>(asObject(slot.slotBase()))->impl());
    return jsString(exec, imp->xmlspace());
}
bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    // Returning false here, to avoid drawings onto the context. We just want to
    // draw the stored filter output, not the unfiltered object as well.
    if (m_filter.contains(object)) {
        FilterData* filterData = m_filter.get(object);
        if (filterData->builded)
            return false;

        delete m_filter.take(object); // Oops, have to rebuild, go through normal code path
    }

    OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
    FloatRect targetBoundingBox = object->objectBoundingBox();

    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits(), targetBoundingBox);
    if (filterData->boundaries.isEmpty())
        return false;

    // Determine absolute transformation matrix for filter. 
    AffineTransform absoluteTransform;
    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
    if (!absoluteTransform.isInvertible())
        return false;

    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);

    // Determine absolute boundaries of the filter and the drawing region.
    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
    FloatRect drawingRegion = object->strokeBoundingBox();
    drawingRegion.intersect(filterData->boundaries);
    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion);

    // Create the SVGFilter object.
    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);

    // Create all relevant filter primitives.
    filterData->builder = buildPrimitives(filterData->filter.get());
    if (!filterData->builder)
        return false;

    // Calculate the scale factor for the use of filterRes.
    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
    FloatSize scale(1, 1);
    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
        scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width());
        scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height());
    }

    if (scale.isEmpty())
        return false;

    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
    FloatRect tempSourceRect = absoluteDrawingRegion;
    tempSourceRect.scale(scale.width(), scale.height());
    fitsInMaximumImageSize(tempSourceRect.size(), scale);

    // Set the scale level in SVGFilter.
    filterData->filter->setFilterResolution(scale);

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    if (!lastEffect)
        return false;

    RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
    FloatRect subRegion = lastEffect->maxEffectRect();
    // At least one FilterEffect has a too big image size,
    // recalculate the effect sizes with new scale factors.
    if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
        filterData->filter->setFilterResolution(scale);
        RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
    }

    // If the drawingRegion is empty, we have something like <g filter=".."/>.
    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
    if (drawingRegion.isEmpty()) {
        ASSERT(!m_filter.contains(object));
        filterData->savedContext = context;
        m_filter.set(object, filterData.leakPtr());
        return false;
    }

    // Change the coordinate transformation applied to the filtered element to reflect the resolution of the filter.
    AffineTransform effectiveTransform;
    effectiveTransform.scale(scale.width(), scale.height());
    effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);

    OwnPtr<ImageBuffer> sourceGraphic;
    RenderingMode renderingMode = object->document()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
    if (!SVGImageBufferTools::createImageBuffer(drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
        ASSERT(!m_filter.contains(object));
        filterData->savedContext = context;
        m_filter.set(object, filterData.leakPtr());
        return false;
    }
    
    // Set the rendering mode from the page's settings.
    filterData->filter->setRenderingMode(renderingMode);

    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
    ASSERT(sourceGraphicContext);
  
    filterData->sourceGraphicBuffer = sourceGraphic.release();
    filterData->savedContext = context;

    context = sourceGraphicContext;

    ASSERT(!m_filter.contains(object));
    m_filter.set(object, filterData.leakPtr());

    return true;
}
Example #26
0
JSValue* JSSVGFilterElement::getValueProperty(ExecState* exec, int token) const
{
    switch (token) {
    case FilterUnitsAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedEnumeration> obj = imp->filterUnitsAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedEnumeration>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedEnumeration>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedEnumeration>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case PrimitiveUnitsAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedEnumeration> obj = imp->primitiveUnitsAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedEnumeration>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedEnumeration>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedEnumeration>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case XAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedLength> obj = imp->xAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedLength>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedLength>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedLength>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case YAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedLength> obj = imp->yAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedLength>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedLength>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedLength>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case WidthAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedLength> obj = imp->widthAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedLength>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedLength>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedLength>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case HeightAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedLength> obj = imp->heightAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedLength>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedLength>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedLength>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case FilterResXAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedInteger> obj = imp->filterResXAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedInteger>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedInteger>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedInteger>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case FilterResYAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedInteger> obj = imp->filterResYAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedInteger>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedInteger>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedInteger>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case HrefAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedString> obj = imp->hrefAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedString>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedString>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedString>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case XmllangAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        return jsString(imp->xmllang());
    }
    case XmlspaceAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        return jsString(imp->xmlspace());
    }
    case ExternalResourcesRequiredAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedBoolean> obj = imp->externalResourcesRequiredAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedBoolean>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedBoolean>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedBoolean>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case ClassNameAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        ASSERT(exec && exec->dynamicInterpreter());

        RefPtr<SVGAnimatedString> obj = imp->classNameAnimated();
        Frame* activeFrame = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->frame();
        if (activeFrame) {
            SVGDocumentExtensions* extensions = (activeFrame->document() ? activeFrame->document()->accessSVGExtensions() : 0);
            if (extensions) {
                if (extensions->hasGenericContext<SVGAnimatedString>(obj.get()))
                    ASSERT(extensions->genericContext<SVGAnimatedString>(obj.get()) == imp);
                else
                    extensions->setGenericContext<SVGAnimatedString>(obj.get(), imp);
            }
        }

        return toJS(exec, obj.get());
    }
    case StyleAttrNum: {
        SVGFilterElement* imp = static_cast<SVGFilterElement*>(impl());

        return toJS(exec, WTF::getPtr(imp->style()));
    }
    }
    return 0;
}
Example #27
0
PassRefPtr<FilterEffect> ReferenceFilterBuilder::build(Filter* parentFilter, RenderObject* renderer, FilterEffect* previousEffect, const ReferenceFilterOperation* filterOperation)
{
    if (!renderer)
        return 0;

    Document* document = &renderer->document();

    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)
            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));

    // 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 (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(), parentFilter);
        if (!effect)
            continue;

        effectElement->setStandardAttributes(effect.get());
        effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnitsCurrentValue(), parentFilter->sourceImageRect()));
        ColorSpace colorSpace = filterColorSpace;
        if (useFilterColorSpace || getSVGElementColorSpace(effectElement, colorSpace))
            effect->setOperatingColorSpace(colorSpace);
        builder->add(effectElement->resultCurrentValue(), effect);
    }
    return builder->lastEffect();
}