void FEComponentTransfer::applySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return; unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; getValues(rValues, gValues, bValues, aValues); IntRect destRect = drawingRegionOfInputImage(in->absolutePaintRect()); SkPaint paint; paint.setColorFilter(SkTableColorFilter::CreateARGB(aValues, rValues, gValues, bValues))->unref(); paint.setXfermodeMode(SkXfermode::kSrc_Mode); resultImage->context()->drawBitmap(nativeImage->bitmap(), destRect.x(), destRect.y(), &paint); if (affectsTransparentPixels()) { IntRect fullRect = IntRect(IntPoint(), absolutePaintRect().size()); resultImage->context()->clipOut(destRect); resultImage->context()->fillRect(fullRect, Color(rValues[0], gValues[0], bValues[0], aValues[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(); }
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(); }
void FEDropShadow::applySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter* filter = this->filter(); FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY)); FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); GraphicsContext* resultContext = resultImage->context(); ASSERT(resultContext); Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity)); SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(blurRadius.width(), blurRadius.height())); SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrcIn_Mode)); SkPaint paint; paint.setImageFilter(blurFilter.get()); paint.setColorFilter(colorFilter.get()); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return; resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x() + offset.width(), drawingRegion.y() + offset.height(), &paint); resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y()); }
bool FEBlend::platformApplySkia() { // For now, only use the skia implementation for accelerated rendering. if (filter()->renderingMode() != Accelerated) return false; FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); if (!in || !in2) return false; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return false; RefPtr<Image> foreground = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<Image> background = in2->asImageBuffer()->copyImage(DontCopyBackingStore); SkBitmap foregroundBitmap = foreground->nativeImageForCurrentFrame()->bitmap(); SkBitmap backgroundBitmap = background->nativeImageForCurrentFrame()->bitmap(); SkAutoTUnref<SkImageFilter> backgroundSource(new SkBitmapSource(backgroundBitmap)); SkBlendImageFilter::Mode mode = toSkiaMode(m_mode); SkAutoTUnref<SkImageFilter> blend(new SkBlendImageFilter(mode, backgroundSource)); SkPaint paint; paint.setImageFilter(blend); SkCanvas* canvas = resultImage->context()->platformContext()->canvas(); canvas->drawBitmap(foregroundBitmap, 0, 0, &paint); return true; }
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; }
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()); }
void FEColorMatrix::applySoftware() { ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; FilterEffect* in = inputEffect(0); IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data())); RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return; SkPaint paint; paint.setColorFilter(filter); paint.setXfermodeMode(SkXfermode::kSrc_Mode); resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y(), &paint); if (affectsTransparentPixels()) { IntRect fullRect = IntRect(IntPoint(), absolutePaintRect().size()); resultImage->context()->clipOut(drawingRegion); resultImage->context()->fillRect(fullRect, Color(m_values[4], m_values[9], m_values[14], m_values[19])); } return; }
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; }
void SourceGraphic::platformApplySoftware() { ImageBuffer* resultImage = createImageBufferResult(); Filter* filter = this->filter(); if (!resultImage || !filter->sourceImage()) return; resultImage->context()->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint()); }
void FEFlood::platformApplySoftware() { ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity()); resultImage->context()->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, ColorSpaceDeviceRGB); }
void FEFlood::applySoftware() { ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Color color = floodColor().combineWithAlpha(floodOpacity()); resultImage->context()->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color); FilterEffect::setResultColorSpace(ColorSpaceDeviceRGB); }
void FEComposite::platformApplySoftware() { FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) { ByteArray* dstPixelArray = createPremultipliedImageResult(); if (!dstPixelArray) return; IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect); IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect); arithmetic(srcPixelArray.get(), dstPixelArray, m_k1, m_k2, m_k3, m_k4); return; } ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; GraphicsContext* filterContext = resultImage->context(); FloatRect srcRect = FloatRect(0, 0, -1, -1); switch (m_type) { case FECOMPOSITE_OPERATOR_OVER: filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); break; case FECOMPOSITE_OPERATOR_IN: { GraphicsContextStateSaver stateSaver(*filterContext); filterContext->clipToImageBuffer(in2->asImageBuffer(), drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); break; } case FECOMPOSITE_OPERATOR_OUT: filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut); break; case FECOMPOSITE_OPERATOR_ATOP: filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop); break; case FECOMPOSITE_OPERATOR_XOR: filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR); break; default: break; } }
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); }
void FEImage::platformApplySoftware() { RenderObject* renderer = referencedRenderer(); if (!m_image && !renderer) return; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; SVGFilter* svgFilter = static_cast<SVGFilter*>(filter()); FloatRect destRect = svgFilter->absoluteTransform().mapRect(filterPrimitiveSubregion()); FloatRect srcRect; if (renderer) srcRect = svgFilter->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates()); else { srcRect = FloatRect(FloatPoint(), m_image->size()); m_preserveAspectRatio.transformRect(destRect, srcRect); } IntPoint paintLocation = absolutePaintRect().location(); destRect.move(-paintLocation.x(), -paintLocation.y()); // FEImage results are always in ColorSpaceDeviceRGB setResultColorSpace(ColorSpaceDeviceRGB); if (renderer) { const AffineTransform& absoluteTransform = svgFilter->absoluteTransform(); resultImage->context()->concatCTM(absoluteTransform); SVGElement* contextNode = static_cast<SVGElement*>(renderer->node()); if (contextNode->isStyled() && static_cast<SVGStyledElement*>(contextNode)->hasRelativeLengths()) { SVGLengthContext lengthContext(contextNode); float width = 0; float height = 0; // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport. // Build up a transformation that maps from the viewport space to the filter primitive subregion. if (lengthContext.determineViewport(width, height)) resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(0, 0, width, height), destRect)); } AffineTransform contentTransformation; SVGRenderingContext::renderSubtreeToImageBuffer(resultImage, renderer, contentTransformation); return; } resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect); }
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); }
void FEMerge::platformApplySoftware() { unsigned size = numberOfEffectInputs(); ASSERT(size > 0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; GraphicsContext* filterContext = resultImage->context(); for (unsigned i = 0; i < size; ++i) { FilterEffect* in = inputEffect(i); filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); } }
void FEImage::platformApplySoftware() { if (!m_image.get()) return; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; FloatRect srcRect(FloatPoint(), m_image->size()); FloatRect destRect(m_absoluteSubregion); m_preserveAspectRatio.transformRect(destRect, srcRect); IntPoint paintLocation = absolutePaintRect().location(); destRect.move(-paintLocation.x(), -paintLocation.y()); resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect); }
void FEBlend::platformApplySoftware() { FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; GraphicsContext& filterContext = resultImage->context(); ImageBuffer* imageBuffer = in->asImageBuffer(); ImageBuffer* imageBuffer2 = in2->asImageBuffer(); ASSERT(imageBuffer); ASSERT(imageBuffer2); filterContext.drawImageBuffer(imageBuffer2, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext.drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), IntRect(IntPoint(), imageBuffer->logicalSize()), ImagePaintingOptions(CompositeSourceOver, m_mode)); }
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())); }
void FEImage::applySoftware() { RenderObject* renderer = referencedRenderer(); if (!m_image && !renderer) return; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; IntPoint paintLocation = absolutePaintRect().location(); resultImage->context()->translate(-paintLocation.x(), -paintLocation.y()); // FEImage results are always in ColorSpaceDeviceRGB setResultColorSpace(ColorSpaceDeviceRGB); FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion()); FloatRect srcRect; if (!renderer) { srcRect = FloatRect(FloatPoint(), m_image->size()); m_preserveAspectRatio->transformRect(destRect, srcRect); resultImage->context()->drawImage(m_image.get(), destRect, srcRect); return; } 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 we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport. // Build up a transformation that maps from the viewport space to the filter primitive subregion. if (lengthContext.determineViewport(viewportSize)) resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect)); } else { resultImage->context()->translate(destRect.x(), destRect.y()); resultImage->context()->concatCTM(filter()->absoluteTransform()); } AffineTransform contentTransformation; SVGRenderingContext::renderSubtree(resultImage->context(), renderer, contentTransformation); }
void FEDropShadow::platformApplySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter& filter = this->filter(); FloatSize blurRadius(2 * filter.applyHorizontalScale(m_stdX), 2 * filter.applyVerticalScale(m_stdY)); blurRadius.scale(filter.filterScale()); FloatSize offset(filter.applyHorizontalScale(m_dx), filter.applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); FloatRect drawingRegionWithOffset(drawingRegion); drawingRegionWithOffset.move(offset); ImageBuffer* sourceImage = in->asImageBuffer(); if (!sourceImage) return; GraphicsContext& resultContext = resultImage->context(); resultContext.setAlpha(m_shadowOpacity); resultContext.drawImageBuffer(*sourceImage, drawingRegionWithOffset); resultContext.setAlpha(1); ShadowBlur contextShadow(blurRadius, offset, m_shadowColor); // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData. IntRect shadowArea(IntPoint(), resultImage->internalSize()); RefPtr<Uint8ClampedArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea, ImageBuffer::BackingStoreCoordinateSystem); contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); resultImage->putByteArray(Premultiplied, srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint(), ImageBuffer::BackingStoreCoordinateSystem); resultContext.setCompositeOperation(CompositeSourceIn); resultContext.fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor); resultContext.setCompositeOperation(CompositeDestinationOver); resultImage->context().drawImageBuffer(*sourceImage, drawingRegion); }
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); } }
bool FEDisplacementMap::applySkia() { // For now, only use the skia implementation for accelerated rendering. if (!filter()->isAccelerated()) return false; FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); if (!in || !in2) return false; ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return false; RefPtr<Image> color = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<Image> displ = in2->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> colorNativeImage = color->nativeImageForCurrentFrame(); RefPtr<NativeImageSkia> displNativeImage = displ->nativeImageForCurrentFrame(); if (!colorNativeImage || !displNativeImage) return false; SkBitmap colorBitmap = colorNativeImage->bitmap(); SkBitmap displBitmap = displNativeImage->bitmap(); SkAutoTUnref<SkImageFilter> colorSource(new SkBitmapSource(colorBitmap)); SkAutoTUnref<SkImageFilter> displSource(new SkBitmapSource(displBitmap)); SkDisplacementMapEffect::ChannelSelectorType typeX = toSkiaMode(m_xChannelSelector); SkDisplacementMapEffect::ChannelSelectorType typeY = toSkiaMode(m_yChannelSelector); // FIXME : Only applyHorizontalScale is used and applyVerticalScale is ignored // This can be fixed by adding a 2nd scale parameter to SkDisplacementMapEffect SkAutoTUnref<SkImageFilter> displEffect(new SkDisplacementMapEffect( typeX, typeY, SkFloatToScalar(filter()->applyHorizontalScale(m_scale)), displSource, colorSource)); SkPaint paint; paint.setImageFilter(displEffect); resultImage->context()->drawBitmap(colorBitmap, 0, 0, &paint); return true; }
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())); }
void FEDropShadow::platformApplySoftware() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; Filter* filter = this->filter(); FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY)); FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); FloatRect drawingRegionWithOffset(drawingRegion); drawingRegionWithOffset.move(offset); ImageBuffer* sourceImage = in->asImageBuffer(); ASSERT(sourceImage); GraphicsContext* resultContext = resultImage->context(); ASSERT(resultContext); resultContext->setAlpha(m_shadowOpacity); resultContext->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegionWithOffset); resultContext->setAlpha(1); ShadowBlur contextShadow(blurRadius, offset, m_shadowColor, ColorSpaceDeviceRGB); // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData. IntRect shadowArea(IntPoint(), resultImage->size()); RefPtr<ByteArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea); contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); resultImage->putPremultipliedImageData(srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint()); resultContext->setCompositeOperation(CompositeSourceIn); resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB); resultContext->setCompositeOperation(CompositeDestinationOver); resultImage->context()->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegion); }
bool FEComponentTransfer::platformApplySkia() { FilterEffect* in = inputEffect(0); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return false; RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return false; unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; getValues(rValues, gValues, bValues, aValues); SkPaint paint; paint.setColorFilter(SkTableColorFilter::CreateARGB(aValues, rValues, gValues, bValues))->unref(); paint.setXfermodeMode(SkXfermode::kSrc_Mode); resultImage->context()->platformContext()->drawBitmap(nativeImage->bitmap(), 0, 0, &paint); return true; }
bool FEColorMatrix::applySkia() { ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return false; FilterEffect* in = inputEffect(0); SkRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data())); RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore); RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame(); if (!nativeImage) return false; SkPaint paint; paint.setColorFilter(filter); paint.setXfermodeMode(SkXfermode::kSrc_Mode); resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.fLeft, drawingRegion.fTop, &paint); return true; }
void FEBlend::applySoftware() { #if HAVE(ARM_NEON_INTRINSICS) if (applySoftwareNEON()) return; #endif FilterEffect* in = inputEffect(0); FilterEffect* in2 = inputEffect(1); ImageBuffer* resultImage = createImageBufferResult(); if (!resultImage) return; GraphicsContext* filterContext = resultImage->context(); ImageBuffer* imageBuffer = in->asImageBuffer(); ImageBuffer* imageBuffer2 = in2->asImageBuffer(); ASSERT(imageBuffer); ASSERT(imageBuffer2); filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect())); filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeSourceOver, m_mode); }
void FETile::platformApplySoftware() { // 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); 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->filterRegion(); tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); } OwnPtr<ImageBuffer> tileImage; if (!SVGImageBufferTools::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())); #endif }