void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*)
{
    ASSERT(object);
    ASSERT(context);
#ifndef NDEBUG
    ASSERT(resourceMode == ApplyToDefaultMode);
#else
    UNUSED_PARAM(resourceMode);
#endif

    if (!m_filter.contains(object))
        return;

    FilterData* filterData = m_filter.get(object);
    if (!filterData->builded) {
        if (!filterData->savedContext) {
            removeClientFromCache(object);
            return;
        }

        context = filterData->savedContext;
        filterData->savedContext = 0;
#if !PLATFORM(CG)
        if (filterData->sourceGraphicBuffer)
            filterData->sourceGraphicBuffer->transformColorSpace(ColorSpaceDeviceRGB, ColorSpaceLinearRGB);
#endif
    }

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    
    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
        // This is the real filtering of the object. It just needs to be called on the
        // initial filtering process. We just take the stored filter result on a
        // second drawing.
        if (!filterData->builded) {
            filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());
            lastEffect->apply();
#if !PLATFORM(CG)
            ImageBuffer* resultImage = lastEffect->asImageBuffer();
            if (resultImage)
                resultImage->transformColorSpace(ColorSpaceLinearRGB, ColorSpaceDeviceRGB);
#endif
            filterData->builded = true;
        }

        ImageBuffer* resultImage = lastEffect->asImageBuffer();
        if (resultImage) {
            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());

            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
            context->clip(lastEffect->maxEffectRect());
            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect());
            context->scale(filterData->filter->filterResolution());

            context->concatCTM(filterData->shearFreeAbsoluteTransform);
        }
    }
    filterData->sourceGraphicBuffer.clear();
}
示例#2
0
void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode)
{
    ASSERT(object);
    ASSERT(context);
#ifndef NDEBUG
    ASSERT(resourceMode == ApplyToDefaultMode);
#else
    UNUSED_PARAM(resourceMode);
#endif

    if (!m_filter.contains(object))
        return;

    FilterData* filterData = m_filter.get(object);
    if (!filterData->builded) {
        if (!filterData->savedContext) {
            removeClientFromCache(object);
            return;
        }

        context = filterData->savedContext;
        filterData->savedContext = 0;
#if !PLATFORM(CG)
        filterData->sourceGraphicBuffer->transformColorSpace(DeviceRGB, LinearRGB);
#endif
    }

    FilterEffect* lastEffect = filterData->builder->lastEffect();
    
    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->subRegion().isEmpty()) {
        // This is the real filtering of the object. It just needs to be called on the
        // initial filtering process. We just take the stored filter result on a
        // second drawing.
        if (!filterData->builded) {
            filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());
            lastEffect->apply(filterData->filter.get());
#if !PLATFORM(CG)
            ImageBuffer* resultImage = lastEffect->resultImage();
            if (resultImage)
                resultImage->transformColorSpace(LinearRGB, DeviceRGB);
#endif
            filterData->builded = true;
        }

        ImageBuffer* resultImage = lastEffect->resultImage();
        if (resultImage)
            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->subRegion());
    }

    filterData->sourceGraphicBuffer.clear();
}
void RenderSVGResourceFilter::postApplyResource(RenderElement& renderer, GraphicsContext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*)
{
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    FilterData* filterData = m_filter.get(&renderer);
    if (!filterData)
        return;

    switch (filterData->state) {
    case FilterData::MarkedForRemoval:
        m_filter.remove(&renderer);
        return;

    case FilterData::CycleDetected:
    case FilterData::Applying:
        // We have a cycle if we are already applying the data.
        // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
        // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
        // will continue correctly.
        filterData->state = FilterData::PaintingSource;
        return;

    case FilterData::PaintingSource:
        if (!filterData->savedContext) {
            removeClientFromCache(renderer);
            return;
        }

        context = filterData->savedContext;
        filterData->savedContext = 0;
        break;

    case FilterData::Built:
    { } // Empty
    }

    FilterEffect* lastEffect = filterData->builder->lastEffect();

    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
        // This is the real filtering of the object. It just needs to be called on the
        // initial filtering process. We just take the stored filter result on a
        // second drawing.
        if (filterData->state != FilterData::Built)
            filterData->filter->setSourceImage(WTF::move(filterData->sourceGraphicBuffer));

        // Always true if filterData is just built (filterData->state == FilterData::Built).
        if (!lastEffect->hasResult()) {
            filterData->state = FilterData::Applying;
            lastEffect->applyAll();
            lastEffect->correctFilterResultIfNeeded();
            lastEffect->transformResultColorSpace(ColorSpaceDeviceRGB);
        }
        filterData->state = FilterData::Built;

        ImageBuffer* resultImage = lastEffect->asImageBuffer();
        if (resultImage) {
            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());

            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
            context->drawImageBuffer(resultImage, renderer.style().colorSpace(), lastEffect->absolutePaintRect());
            context->scale(filterData->filter->filterResolution());

            context->concatCTM(filterData->shearFreeAbsoluteTransform);
        }
    }
    filterData->sourceGraphicBuffer.reset();
}
示例#4
0
void RenderSVGResourceContainer::removeClient(RenderObject* client)
{
    ASSERT(client);
    removeClientFromCache(client, false);
    m_clients.remove(client);
}
示例#5
0
void LayoutSVGResourceContainer::removeClient(LayoutObject* client)
{
    ASSERT(client);
    removeClientFromCache(client, false);
    m_clients.remove(client);
}
void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*)
{
    ASSERT(object);
    ASSERT(context);
    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);

    FilterData* filterData = m_filter.get(object);
    if (!filterData)
        return;

    if (filterData->markedForRemoval) {
        delete m_filter.take(object);
        return;
    }

    // We have a cycle if we are already applying the data.
    // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
    if (filterData->isApplying)
        return;

    if (!filterData->isBuilt) {
        if (!filterData->savedContext) {
            removeClientFromCache(object);
            return;
        }

        context = filterData->savedContext;
        filterData->savedContext = 0;
    }

    ApplyingFilterEffectGuard isApplyingGuard(filterData);

    FilterEffect* lastEffect = filterData->builder->lastEffect();

    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
        // This is the real filtering of the object. It just needs to be called on the
        // initial filtering process. We just take the stored filter result on a
        // second drawing.
        if (!filterData->isBuilt)
            filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());

        // Always true if filterData is just built (filterData->isBuilt is false).
        if (!lastEffect->hasResult()) {
            lastEffect->apply();
            lastEffect->correctFilterResultIfNeeded();
#if !USE(CG)
            ImageBuffer* resultImage = lastEffect->asImageBuffer();
            if (resultImage)
                resultImage->transformColorSpace(lastEffect->colorSpace(), ColorSpaceDeviceRGB);
#endif
        }
        filterData->isBuilt = true;

        ImageBuffer* resultImage = lastEffect->asImageBuffer();
        if (resultImage) {
            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());

            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect());
            context->scale(filterData->filter->filterResolution());

            context->concatCTM(filterData->shearFreeAbsoluteTransform);
        }
    }
    filterData->sourceGraphicBuffer.clear();
}