void FEDropShadow::determineAbsolutePaintRect()
{
    Filter* filter = this->filter();
    ASSERT(filter);

    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
    FloatRect absoluteOffsetPaintRect(absolutePaintRect);
    absoluteOffsetPaintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
    absolutePaintRect.unite(absoluteOffsetPaintRect);
    
    unsigned kernelSizeX = 0;
    unsigned kernelSizeY = 0;
    FEGaussianBlur::calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
    
    // We take the half kernel size and multiply it with three, because we run box blur three times.
    absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f);
    absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f);

    if (clipsToBounds())
        absolutePaintRect.intersect(maxEffectRect());
    else
        absolutePaintRect.unite(maxEffectRect());

    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
}
Exemplo n.º 2
0
void FEOffset::determineAbsolutePaintRect()
{
    FloatRect paintRect = inputEffect(0)->absolutePaintRect();
    Filter& filter = this->filter();
    paintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy));
    if (clipsToBounds())
        paintRect.intersect(maxEffectRect());
    else
        paintRect.unite(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
Exemplo n.º 3
0
void FEMorphology::determineAbsolutePaintRect()
{
    FloatRect paintRect = inputEffect(0)->absolutePaintRect();
    Filter& filter = this->filter();
    paintRect.inflateX(filter.applyHorizontalScale(m_radiusX));
    paintRect.inflateY(filter.applyVerticalScale(m_radiusY));
    if (clipsToBounds())
        paintRect.intersect(maxEffectRect());
    else
        paintRect.unite(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
Exemplo n.º 4
0
void FEDropShadow::determineAbsolutePaintRect()
{
    Filter* filter = this->filter();
    ASSERT(filter);

    FloatRect absolutePaintRect = mapRect(inputEffect(0)->absolutePaintRect());

    if (clipsToBounds())
        absolutePaintRect.intersect(maxEffectRect());
    else
        absolutePaintRect.unite(maxEffectRect());

    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
}
Exemplo n.º 5
0
void FilterEffect::apply()
{
    // Recursively determine paint rects first, so that we don't redraw images
    // if a smaller section is requested first.
    determineAbsolutePaintRect(maxEffectRect());
    applyRecursive();
}
Exemplo n.º 6
0
FloatRect FilterEffect::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
    FloatRect requestedRect = originalRequestedRect;
    // Filters in SVG clip to primitive subregion, while CSS doesn't.
    if (m_clipsToBounds)
        requestedRect.intersect(maxEffectRect());

    // We may be called multiple times if result is used more than once. Return
    // quickly if if nothing new is required.
    if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
        return requestedRect;

    FloatRect inputRect = mapPaintRect(requestedRect, false);
    FloatRect inputUnion;
    unsigned size = m_inputEffects.size();

    for (unsigned i = 0; i < size; ++i)
        inputUnion.unite(m_inputEffects.at(i)->determineAbsolutePaintRect(inputRect));
    inputUnion = mapPaintRect(inputUnion, true);

    if (affectsTransparentPixels() || !size) {
        inputUnion = requestedRect;
    } else {
        // Rect may have inflated. Re-intersect with request.
        inputUnion.intersect(requestedRect);
    }

    addAbsolutePaintRect(inputUnion);
    return inputUnion;
}
Exemplo n.º 7
0
void FEImage::determineAbsolutePaintRect()
{
    FloatRect paintRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion());
    FloatRect srcRect;
    if (m_image) {
        srcRect.setSize(m_image->size());
        m_preserveAspectRatio.transformRect(paintRect, srcRect);
    } else if (RenderElement* renderer = referencedRenderer())
        srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());

    if (clipsToBounds())
        paintRect.intersect(maxEffectRect());
    else
        paintRect.unite(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
Exemplo n.º 8
0
void FEGaussianBlur::determineAbsolutePaintRect()
{
    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
    if (clipsToBounds())
        absolutePaintRect.intersect(maxEffectRect());
    else
        absolutePaintRect.unite(maxEffectRect());

    unsigned kernelSizeX = 0;
    unsigned kernelSizeY = 0;
    calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);

    // We take the half kernel size and multiply it with three, because we run box blur three times.
    absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f);
    absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f);
    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
}
Exemplo n.º 9
0
void FEOffset::determineAbsolutePaintRect()
{
    FloatRect paintRect = inputEffect(0)->absolutePaintRect();
    Filter* filter = this->filter();
    paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
    paintRect.intersect(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
Exemplo n.º 10
0
void FEImage::determineAbsolutePaintRect()
{
    ASSERT(m_image);
    FloatRect srcRect(FloatPoint(), m_image->size());
    FloatRect paintRect(m_absoluteSubregion);
    m_preserveAspectRatio.transformRect(paintRect, srcRect);
    paintRect.intersect(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
Exemplo n.º 11
0
FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
    FloatRect requestedRect = originalRequestedRect;
    if (clipsToBounds())
        requestedRect.intersect(maxEffectRect());

    // We may be called multiple times if result is used more than once. Return
    // quickly if nothing new is required.
    if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
        return requestedRect;

    // No mapPaintRect required for FEComposite.
    FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect);
    FloatRect affectedRect;
    switch (m_type) {
    case FECOMPOSITE_OPERATOR_IN:
        // 'in' has output only in the intersection of both inputs.
        affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect));
        break;
    case FECOMPOSITE_OPERATOR_ATOP:
        // 'atop' has output only in the extents of the second input.
        // Make sure first input knows where it needs to produce output.
        inputEffect(0)->determineAbsolutePaintRect(input1Rect);
        affectedRect = input1Rect;
        break;
    case FECOMPOSITE_OPERATOR_ARITHMETIC:
        if (k4() > 0) {
            // Make sure first input knows where it needs to produce output.
            inputEffect(0)->determineAbsolutePaintRect(requestedRect);
            // Arithmetic with non-zero k4 may influnce the complete filter primitive
            // region. So we can't optimize the paint region here.
            affectedRect = requestedRect;
            break;
        }
        if (k2() <= 0) {
            // Input 0 does not appear where input 1 is not present.
            FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect);
            if (k3() > 0) {
                affectedRect = input1Rect;
            } else {
                // Just k1 is positive. Use intersection.
                affectedRect = intersection(input1Rect, input0Rect);
            }
            break;
        }
        // else fall through to use union
    default:
        // Take the union of both input effects.
        affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect));
        break;
    }

    affectedRect.intersect(requestedRect);
    addAbsolutePaintRect(affectedRect);
    return affectedRect;
}
Exemplo n.º 12
0
FloatRect FEGaussianBlur::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
    FloatRect requestedRect = originalRequestedRect;
    if (clipsToBounds())
        requestedRect.intersect(maxEffectRect());

    FilterEffect* input = inputEffect(0);
    FloatRect inputRect = input->determineAbsolutePaintRect(mapRect(requestedRect, false));
    FloatRect outputRect = mapRect(inputRect, true);
    outputRect.intersect(requestedRect);
    addAbsolutePaintRect(outputRect);

    // Blur needs space for both input and output pixels in the paint area.
    // Input is also clipped to subregion.
    if (clipsToBounds())
        inputRect.intersect(maxEffectRect());
    addAbsolutePaintRect(inputRect);
    return outputRect;
}
Exemplo n.º 13
0
void FEGaussianBlur::determineAbsolutePaintRect()
{
    IntSize kernelSize = calculateKernelSize(filter(), FloatPoint(m_stdX, m_stdY));

    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
    // Edge modes other than 'none' do not inflate the affected paint rect.
    if (m_edgeMode != EDGEMODE_NONE) {
        setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
        return;
    }

    // We take the half kernel size and multiply it with three, because we run box blur three times.
    absolutePaintRect.inflateX(3 * kernelSize.width() * 0.5f);
    absolutePaintRect.inflateY(3 * kernelSize.height() * 0.5f);

    if (clipsToBounds())
        absolutePaintRect.intersect(maxEffectRect());
    else
        absolutePaintRect.unite(maxEffectRect());

    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
}
Exemplo n.º 14
0
void FEDropShadow::determineAbsolutePaintRect()
{
    Filter& filter = this->filter();

    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
    FloatRect absoluteOffsetPaintRect(absolutePaintRect);
    absoluteOffsetPaintRect.move(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy));
    absolutePaintRect.unite(absoluteOffsetPaintRect);

    IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY));

    // We take the half kernel size and multiply it with three, because we run box blur three times.
    absolutePaintRect.inflateX(3 * kernelSize.width() * 0.5f);
    absolutePaintRect.inflateY(3 * kernelSize.height() * 0.5f);

    if (clipsToBounds())
        absolutePaintRect.intersect(maxEffectRect());
    else
        absolutePaintRect.unite(maxEffectRect());

    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
}
Exemplo n.º 15
0
FloatRect FEDisplacementMap::determineAbsolutePaintRect(const FloatRect& requestedRect)
{
    FloatRect rect = requestedRect;
    if (clipsToBounds())
        rect.intersect(maxEffectRect());

    if (absolutePaintRect().contains(enclosingIntRect(rect)))
        return rect;

    rect = mapPaintRect(rect, false);
    rect = inputEffect(0)->determineAbsolutePaintRect(rect);
    rect = mapPaintRect(rect, true);
    rect.intersect(requestedRect);

    addAbsolutePaintRect(rect);
    return rect;
}
Exemplo n.º 16
0
void FETile::platformApplySoftware()
{
// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
    FilterEffect* in = inputEffect(0);

    ImageBuffer* resultImage = createImageBufferResult();
    ImageBuffer* inBuffer = in->asImageBuffer();
    if (!resultImage || !inBuffer)
        return;

    setIsAlphaImage(in->isAlphaImage());

    // Source input needs more attention. It has the size of the filterRegion but gives the
    // size of the cutted sourceImage back. This is part of the specification and optimization.
    FloatRect tileRect = in->maxEffectRect();
    FloatPoint inMaxEffectLocation = tileRect.location();
    FloatPoint maxEffectLocation = maxEffectRect().location();
    if (in->filterEffectType() == FilterEffectTypeSourceInput) {
        Filter& filter = this->filter();
        tileRect = filter.filterRegion();
        tileRect.scale(filter.filterResolution().width(), filter.filterResolution().height());
    }

    auto tileImage = SVGRenderingContext::createImageBuffer(tileRect, tileRect, ColorSpaceSRGB, filter().renderingMode());
    if (!tileImage)
        return;

    GraphicsContext& tileImageContext = tileImage->context();
    tileImageContext.translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
    tileImageContext.drawImageBuffer(*inBuffer, in->absolutePaintRect().location());

    auto tileImageCopy = ImageBuffer::sinkIntoImage(WTFMove(tileImage));
    if (!tileImageCopy)
        return;

    auto pattern = Pattern::create(WTFMove(tileImageCopy), true, true);

    AffineTransform patternTransform;
    patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
    pattern.get().setPatternSpaceTransform(patternTransform);
    GraphicsContext& filterContext = resultImage->context();
    filterContext.setFillPattern(WTFMove(pattern));
    filterContext.fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
}
Exemplo n.º 17
0
void FETile::apply()
{
// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
#if ENABLE(SVG)
    FilterEffect* in = inputEffect(0);
    in->apply();
    if (!in->resultImage())
        return;

    GraphicsContext* filterContext = effectContext();
    if (!filterContext)
        return;

    setIsAlphaImage(in->isAlphaImage());

    // Source input needs more attention. It has the size of the filterRegion but gives the
    // size of the cutted sourceImage back. This is part of the specification and optimization.
    FloatRect tileRect = in->maxEffectRect();
    FloatPoint inMaxEffectLocation = tileRect.location();
    FloatPoint maxEffectLocation = maxEffectRect().location();
    if (in->filterEffectType() == FilterEffectTypeSourceInput) {
        Filter* filter = this->filter();
        tileRect = filter->filterRegion();
        tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
    }

    OwnPtr<ImageBuffer> tileImage;
    if (!SVGImageBufferTools::createImageBuffer(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB))
        return;

    GraphicsContext* tileImageContext = tileImage->context();
    tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
    tileImageContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());

    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);

    AffineTransform patternTransform;
    patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
    pattern->setPatternSpaceTransform(patternTransform);
    filterContext->setFillPattern(pattern);
    filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
#endif
}
Exemplo n.º 18
0
void FEComposite::determineAbsolutePaintRect()
{
    switch (m_type) {
    case FECOMPOSITE_OPERATOR_IN:
    case FECOMPOSITE_OPERATOR_ATOP:
        // For In and Atop the first effect just influences the result of
        // the second effect. So just use the absolute paint rect of the second effect here.
        setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
        return;
    case FECOMPOSITE_OPERATOR_ARITHMETIC:
        // Arithmetic may influnce the compele filter primitive region. So we can't
        // optimize the paint region here.
        setAbsolutePaintRect(enclosingIntRect(maxEffectRect()));
        return;
    default:
        // Take the union of both input effects.
        FilterEffect::determineAbsolutePaintRect();
        return;
    }
}
Exemplo n.º 19
0
void FETile::applySoftware()
{
    FilterEffect* in = inputEffect(0);

    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    setIsAlphaImage(in->isAlphaImage());

    // Source input needs more attention. It has the size of the filterRegion but gives the
    // size of the cutted sourceImage back. This is part of the specification and optimization.
    FloatRect tileRect = in->maxEffectRect();
    FloatPoint inMaxEffectLocation = tileRect.location();
    FloatPoint maxEffectLocation = maxEffectRect().location();
    if (in->filterEffectType() == FilterEffectTypeSourceInput) {
        Filter* filter = this->filter();
        tileRect = filter->absoluteFilterRegion();
    }

    OwnPtr<ImageBufferSurface> surface;
    IntSize intTileSize = roundedIntSize(tileRect.size());
    surface = adoptPtr(new UnacceleratedImageBufferSurface(intTileSize));
    OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(surface.release());
    if (!tileImage)
        return;

    GraphicsContext* tileImageContext = tileImage->context();
    tileImageContext->scale(FloatSize(intTileSize.width() / tileRect.width(), intTileSize.height() / tileRect.height()));
    tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
    tileImageContext->drawImageBuffer(in->asImageBuffer(), in->absolutePaintRect().location());

    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(CopyBackingStore), true, true);

    AffineTransform patternTransform;
    patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
    pattern->setPatternSpaceTransform(patternTransform);
    GraphicsContext* filterContext = resultImage->context();
    filterContext->setFillPattern(pattern);
    filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
}
Exemplo n.º 20
0
void FETile::applySoftware()
{
    FilterEffect* in = inputEffect(0);

    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    setIsAlphaImage(in->isAlphaImage());

    // Source input needs more attention. It has the size of the filterRegion but gives the
    // size of the cutted sourceImage back. This is part of the specification and optimization.
    FloatRect tileRect = in->maxEffectRect();
    FloatPoint inMaxEffectLocation = tileRect.location();
    FloatPoint maxEffectLocation = maxEffectRect().location();
    if (in->filterEffectType() == FilterEffectTypeSourceInput) {
        Filter* filter = this->filter();
        tileRect = filter->absoluteFilterRegion();
        tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
    }

    OwnPtr<ImageBuffer> tileImage;
    if (!SVGRenderingContext::createImageBufferForPattern(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter()->renderingMode()))
        return;

    GraphicsContext* tileImageContext = tileImage->context();
    tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
    tileImageContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());

    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(CopyBackingStore), true, true);

    AffineTransform patternTransform;
    patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
    pattern->setPatternSpaceTransform(patternTransform);
    GraphicsContext* filterContext = resultImage->context();
    filterContext->setFillPattern(pattern);
    filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
}
Exemplo n.º 21
0
FloatRect FEImage::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return FloatRect();

    FloatRect requestedRect = originalRequestedRect;
    if (clipsToBounds())
        requestedRect.intersect(maxEffectRect());

    FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
    FloatRect srcRect;
    if (renderer) {
        srcRect = getRendererRepaintRect(renderer);
        SVGElement* contextNode = toSVGElement(renderer->node());

        if (contextNode->hasRelativeLengths()) {
            // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709).
            SVGLengthContext lengthContext(contextNode);
            FloatSize viewportSize;
            if (lengthContext.determineViewport(viewportSize)) {
                srcRect = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect).mapRect(srcRect);
            }
        } else {
            srcRect = filter()->mapLocalRectToAbsoluteRect(srcRect);
            srcRect.move(destRect.x(), destRect.y());
        }
        destRect.intersect(srcRect);
    } else {
        srcRect = FloatRect(FloatPoint(), m_image->size());
        m_preserveAspectRatio->transformRect(destRect, srcRect);
    }

    destRect.intersect(requestedRect);
    addAbsolutePaintRect(destRect);
    return destRect;
}
Exemplo n.º 22
0
FloatRect FETile::mapPaintRect(const FloatRect& rect, bool forward)
{
    return forward ? maxEffectRect() : inputEffect(0)->maxEffectRect();
}