Пример #1
0
void FEGaussianBlur::apply(Filter* filter)
{
    m_in->apply(filter);
    if (!m_in->resultImage())
        return;

    if (!getEffectContext())
        return;

    setIsAlphaImage(m_in->isAlphaImage());

    if (m_x == 0 || m_y == 0)
        return;

    unsigned sdx = static_cast<unsigned>(floor(m_x * 3 * sqrt(2 * M_PI) / 4.f + 0.5f));
    unsigned sdy = static_cast<unsigned>(floor(m_y * 3 * sqrt(2 * M_PI) / 4.f + 0.5f));

    IntRect effectDrawingRect = calculateDrawingIntRect(m_in->subRegion());
    RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect));
    CanvasPixelArray* srcPixelArray(srcImageData->data());

    IntRect imageRect(IntPoint(), resultImage()->size());
    RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
    CanvasPixelArray* tmpPixelArray(tmpImageData->data());

    int stride = 4 * imageRect.width();
    for (int i = 0; i < 3; ++i) {
        boxBlur(srcPixelArray, tmpPixelArray, sdx, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage());
        boxBlur(tmpPixelArray, srcPixelArray, sdy, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage());
    }

    resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint());
}
Пример #2
0
void FEGaussianBlur::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* srcPixelArray = createPremultipliedImageResult();
    if (!srcPixelArray)
        return;

    setIsAlphaImage(in->isAlphaImage());

    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyPremultipliedImage(srcPixelArray, effectDrawingRect);

    if (!m_stdX && !m_stdY)
        return;

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

    IntSize paintSize = absolutePaintRect().size();
    RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized(paintSize.width() * paintSize.height() * 4);
    Uint8ClampedArray* tmpPixelArray = tmpImageData.get();

    platformApply(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
}
Пример #3
0
void FEGaussianBlur::applySoftware()
{
    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    FilterEffect* in = inputEffect(0);

    IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());

    setIsAlphaImage(in->isAlphaImage());

    float stdX = filter()->applyHorizontalScale(m_stdX);
    float stdY = filter()->applyVerticalScale(m_stdY);

    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);

    SkPaint paint;
    GraphicsContext* dstContext = resultImage->context();
    paint.setImageFilter(SkBlurImageFilter::Create(stdX, stdY))->unref();

    SkRect bounds = SkRect::MakeWH(absolutePaintRect().width(), absolutePaintRect().height());
    dstContext->saveLayer(&bounds, &paint);
    paint.setColor(0xFFFFFFFF);
    dstContext->drawImage(image.get(), drawingRegion.location(), CompositeCopy);
    dstContext->restoreLayer();
}
Пример #4
0
void FEGaussianBlur::platformApplySkia()
{
    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    FilterEffect* in = inputEffect(0);

    IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());

    setIsAlphaImage(in->isAlphaImage());

    float stdX = filter()->applyHorizontalScale(m_stdX);
    float stdY = filter()->applyVerticalScale(m_stdY);
    
    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);

    SkPaint paint;
    GraphicsContext* dstContext = resultImage->context();
    SkCanvas* canvas = dstContext->platformContext()->canvas();
    paint.setImageFilter(new SkBlurImageFilter(stdX, stdY))->unref();
    canvas->saveLayer(0, &paint);
    paint.setColor(0xFFFFFFFF);
    dstContext->drawImage(image.get(), ColorSpaceDeviceRGB, drawingRegion.location(), CompositeCopy);
    canvas->restore();
    return;
}
Пример #5
0
void FEMorphology::applySoftware()
{
    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    FilterEffect* in = inputEffect(0);

    IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());

    setIsAlphaImage(in->isAlphaImage());

    float radiusX = filter()->applyHorizontalScale(m_radiusX);
    float radiusY = filter()->applyVerticalScale(m_radiusY);

    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);

    SkPaint paint;
    GraphicsContext* dstContext = resultImage->context();
    if (m_type == FEMORPHOLOGY_OPERATOR_DILATE)
        paint.setImageFilter(SkDilateImageFilter::Create(radiusX, radiusY))->unref();
    else if (m_type == FEMORPHOLOGY_OPERATOR_ERODE)
        paint.setImageFilter(SkErodeImageFilter::Create(radiusX, radiusY))->unref();

    SkRect bounds = SkRect::MakeWH(absolutePaintRect().width(), absolutePaintRect().height());
    dstContext->saveLayer(&bounds, &paint);
    dstContext->drawImage(image.get(), drawingRegion.location(), CompositeCopy);
    dstContext->restoreLayer();
}
Пример #6
0
void FEGaussianBlur::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* srcPixelArray = createPremultipliedImageResult();
    if (!srcPixelArray)
        return;

    setIsAlphaImage(in->isAlphaImage());

    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyPremultipliedImage(srcPixelArray, effectDrawingRect);

    if (!m_stdX && !m_stdY)
        return;

    IntSize kernelSize = calculateKernelSize(filter(), FloatPoint(m_stdX, m_stdY));
    kernelSize.scale(filter().filterScale());

    IntSize paintSize = absolutePaintRect().size();
    paintSize.scale(filter().filterScale());
    RefPtr<Uint8ClampedArray> tmpImageData = Uint8ClampedArray::createUninitialized((paintSize.area() * 4).unsafeGet());
    if (!tmpImageData) {
        WTFLogAlways("FEGaussianBlur::platformApplySoftware Unable to create buffer. Requested size was %d x %d\n", paintSize.width(), paintSize.height());
        return;
    }

    platformApply(srcPixelArray, tmpImageData.get(), kernelSize.width(), kernelSize.height(), paintSize);
}
Пример #7
0
bool FELighting::applySkia()
{
    // For now, only use the skia implementation for accelerated rendering.
    if (!filter()->isAccelerated())
        return false;

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

    FilterEffect* in = inputEffect(0);

    IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());

    setIsAlphaImage(in->isAlphaImage());

    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
    RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
    if (!nativeImage)
        return false;

    GraphicsContext* dstContext = resultImage->context();

    SkPaint paint;
    RefPtr<SkImageFilter> filter = createImageFilter(0);
    paint.setImageFilter(filter.get());
    dstContext->drawBitmap(nativeImage->bitmap(), drawingRegion.location().x(), drawingRegion.location().y(), &paint);
    return true;
}
Пример #8
0
void FEOffset::apply(Filter* filter)
{
    m_in->apply(filter);
    if (!m_in->resultImage())
        return;

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

    setIsAlphaImage(m_in->isAlphaImage());

    FloatRect sourceImageRect = filter->sourceImageRect();
    sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height());

    if (filter->effectBoundingBoxMode()) {
        m_dx *= sourceImageRect.width();
        m_dy *= sourceImageRect.height();
    }
    m_dx *= filter->filterResolution().width();
    m_dy *= filter->filterResolution().height();

    FloatRect dstRect = FloatRect(m_dx + m_in->scaledSubRegion().x() - scaledSubRegion().x(),
                                  m_dy + m_in->scaledSubRegion().y() - scaledSubRegion().y(),
                                  m_in->scaledSubRegion().width(),
                                  m_in->scaledSubRegion().height());

    filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, dstRect);
}
Пример #9
0
void FEColorMatrix::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

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

    resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));

    IntRect imageRect(IntPoint(), absolutePaintRect().size());
    RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);

    switch (m_type) {
    case FECOLORMATRIX_TYPE_UNKNOWN:
        break;
    case FECOLORMATRIX_TYPE_MATRIX:
        effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values);
        break;
    case FECOLORMATRIX_TYPE_SATURATE: 
        effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values);
        break;
    case FECOLORMATRIX_TYPE_HUEROTATE:
        effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values);
        break;
    case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
        effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values);
        setIsAlphaImage(true);
        break;
    }

    resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint());
}
Пример #10
0
void FEMorphology::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    setIsAlphaImage(in->isAlphaImage());
    if (m_radiusX <= 0 || m_radiusY <= 0) {
        dstPixelArray->zeroFill();
        return;
    }

    Filter& filter = this->filter();
    int radiusX = static_cast<int>(floorf(filter.applyHorizontalScale(m_radiusX)));
    int radiusY = static_cast<int>(floorf(filter.applyVerticalScale(m_radiusY)));

    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);

    PaintingData paintingData;
    paintingData.srcPixelArray = srcPixelArray.get();
    paintingData.dstPixelArray = dstPixelArray;
    paintingData.width = effectDrawingRect.width();
    paintingData.height = effectDrawingRect.height();
    paintingData.radiusX = std::min(effectDrawingRect.width() - 1, radiusX);
    paintingData.radiusY = std::min(effectDrawingRect.height() - 1, radiusY);

    platformApply(&paintingData);
}
Пример #11
0
void FECustomFilter::clearShaderResult()
{
    clearResult();
    Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult();
    if (!dstPixelArray)
        return;

    FilterEffect* in = inputEffect(0);
    setIsAlphaImage(in->isAlphaImage());
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyUnmultipliedImage(dstPixelArray, effectDrawingRect);
}
Пример #12
0
void SourceAlpha::platformApplySoftware()
{
    ImageBuffer* resultImage = createImageBufferResult();
    Filter* filter = this->filter();
    if (!resultImage || !filter->sourceImage())
        return;

    setIsAlphaImage(true);

    FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
    GraphicsContext* filterContext = resultImage->context();
    filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB);
    filterContext->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint(), CompositeDestinationIn);
}
Пример #13
0
void SourceAlpha::apply(Filter* filter)
{
    GraphicsContext* filterContext = getEffectContext();
    if (!filterContext)
        return;

    setIsAlphaImage(true);

    FloatRect imageRect(FloatPoint(), filter->sourceImage()->size());
    filterContext->save();
    filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
    filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
    filterContext->restore();
}
Пример #14
0
void SourceAlpha::apply()
{
    GraphicsContext* filterContext = effectContext();
    Filter* filter = this->filter();
    if (!filterContext || !filter->sourceImage())
        return;

    setIsAlphaImage(true);

    FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
    filterContext->save();
    filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
    filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB);
    filterContext->restore();
}
Пример #15
0
void FEOffset::applySoftware()
{
    FilterEffect* in = inputEffect(0);

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

    setIsAlphaImage(in->isAlphaImage());

    FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
    Filter* filter = this->filter();
    drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
    resultImage->context()->drawImageBuffer(in->asImageBuffer(), drawingRegion);
}
Пример #16
0
void FEOffset::apply()
{
    FilterEffect* in = inputEffect(0);
    in->apply();
    if (!in->resultImage())
        return;

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

    setIsAlphaImage(in->isAlphaImage());

    FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
    Filter* filter = this->filter();
    drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
    filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegion);
}
Пример #17
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()));
}
Пример #18
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
}
Пример #19
0
void SourceAlpha::applySoftware()
{
    ImageBuffer* resultImage = createImageBufferResult();
    Filter* filter = this->filter();
    if (!resultImage || !filter->sourceImage())
        return;

    setIsAlphaImage(true);

    FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
    GraphicsContext* filterContext = resultImage->context();
    filterContext->fillRect(imageRect, Color::black);

    IntRect srcRect = filter->sourceImageRect();
    if (ImageBuffer* sourceImageBuffer = filter->sourceImage()) {
        filterContext->drawImageBuffer(sourceImageBuffer,
            FloatRect(IntPoint(srcRect.location() - absolutePaintRect().location()), sourceImageBuffer->size()),
            0, CompositeDestinationIn);
    }
}
Пример #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();
    }

    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()));
}
Пример #21
0
void FELighting::applySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* srcPixelArray = createPremultipliedImageResult();
    if (!srcPixelArray)
        return;

    setIsAlphaImage(false);

    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyPremultipliedImage(srcPixelArray, effectDrawingRect);

    // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
    // standard has no test case for them, and other browsers (like Firefox) has strange
    // output for various kernelUnitLengths, and I am not sure they are reliable.
    // Anyway, feConvolveMatrix should also use the implementation

    IntSize absolutePaintSize = absolutePaintRect().size();
    drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height());
}
Пример #22
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()));
}
Пример #23
0
void FELighting::apply(Filter* filter)
{
    m_in->apply(filter);
    if (!m_in->resultImage())
        return;

    if (!getEffectContext())
        return;

    setIsAlphaImage(false);

    IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    RefPtr<ImageData> srcImageData(m_in->resultImage()->getUnmultipliedImageData(effectDrawingRect));
    CanvasPixelArray* srcPixelArray(srcImageData->data());

    // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
    // standard has no test case for them, and other browsers (like Firefox) has strange
    // output for various kernelUnitLengths, and I am not sure they are reliable.
    // Anyway, feConvolveMatrix should also use the implementation

    if (drawLighting(srcPixelArray, effectDrawingRect.width(), effectDrawingRect.height()))
        resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
}
Пример #24
0
void FEColorMatrix::apply()
{
    FilterEffect* in = inputEffect(0);
    in->apply();
    if (!in->resultImage())
        return;

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

    filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));

    IntRect imageRect(IntPoint(), resultImage()->size());
    RefPtr<ImageData> imageData = resultImage()->getUnmultipliedImageData(imageRect);
    ByteArray* pixelArray = imageData->data()->data();

    switch (m_type) {
        case FECOLORMATRIX_TYPE_UNKNOWN:
            break;
        case FECOLORMATRIX_TYPE_MATRIX:
            effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray, m_values);
            break;
        case FECOLORMATRIX_TYPE_SATURATE: 
            effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray, m_values);
            break;
        case FECOLORMATRIX_TYPE_HUEROTATE:
            effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray, m_values);
            break;
        case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
            effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray, m_values);
            setIsAlphaImage(true);
            break;
    }

    resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
Пример #25
0
void FEMorphology::apply(Filter* filter)
{
    m_in->apply(filter);
    if (!m_in->resultImage())
        return;
    
    if (!getEffectContext())
        return;

    setIsAlphaImage(m_in->isAlphaImage());

    int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width());
    int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height());
    if (radiusX <= 0 || radiusY <= 0)
        return;

    IntRect imageRect(IntPoint(), resultImage()->size());
    IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    RefPtr<CanvasPixelArray> srcPixelArray(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data());
    RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());

    int effectWidth = effectDrawingRect.width() * 4;
    
    // Limit the radius size to effect dimensions
    radiusX = min(effectDrawingRect.width() - 1, radiusX);
    radiusY = min(effectDrawingRect.height() - 1, radiusY);
    
    Vector<unsigned char> extrema;
    for (int y = 0; y < effectDrawingRect.height(); ++y) {
        int startY = max(0, y - radiusY);
        int endY = min(effectDrawingRect.height() - 1, y + radiusY);
        for (unsigned channel = 0; channel < 4; ++channel) {
            // Fill the kernel
            extrema.clear();
            for (int j = 0; j <= radiusX; ++j) {
                unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + 4 * j + channel);
                for (int i = startY; i <= endY; ++i) {
                    unsigned char pixel = srcPixelArray->get(i * effectWidth + 4 * j + channel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) ||
                        (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
                        columnExtrema = pixel;
                }
                extrema.append(columnExtrema);
            }
            
            // Kernel is filled, get extrema of next column 
            for (int x = 0; x < effectDrawingRect.width(); ++x) {
                unsigned endX = min(x + radiusX, effectDrawingRect.width() - 1);
                unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + endX * 4 + channel);
                for (int i = startY; i <= endY; ++i) {
                    unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + channel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) ||
                        (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
                        columnExtrema = pixel;
                }
                if (x - radiusX >= 0)
                    extrema.remove(0);
                if (x + radiusX <= effectDrawingRect.width())
                    extrema.append(columnExtrema);
                unsigned char entireExtrema = extrema[0];
                for (unsigned kernelIndex = 0; kernelIndex < extrema.size(); ++kernelIndex) {
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema) ||
                        (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema))
                        entireExtrema = extrema[kernelIndex];
                }
                imageData->data()->set(y * effectWidth + 4 * x + channel, entireExtrema);
            }
        }
    }
    resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}