void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect& rect) { ASSERT(hasResult()); if (!m_premultipliedImageResult) { // We prefer a conversion from the image buffer. if (m_imageBufferResult) m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); else { ASSERT(isFilterSizeValid(m_absolutePaintRect)); IntSize inputSize(m_absolutePaintRect.size()); inputSize.scale(m_filter->filterScale()); m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4); unsigned char* sourceComponent = m_unmultipliedImageResult->data(); unsigned char* destinationComponent = m_premultipliedImageResult->data(); unsigned char* end = sourceComponent + (inputSize.width() * inputSize.height() * 4); while (sourceComponent < end) { int alpha = sourceComponent[3]; destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255; destinationComponent[1] = static_cast<int>(sourceComponent[1]) * alpha / 255; destinationComponent[2] = static_cast<int>(sourceComponent[2]) * alpha / 255; destinationComponent[3] = alpha; sourceComponent += 4; destinationComponent += 4; } } } copyImageBytes(m_premultipliedImageResult.get(), destination, rect); }
void FilterEffect::apply() { if (hasResult()) return; unsigned size = m_inputEffects.size(); for (unsigned i = 0; i < size; ++i) { FilterEffect* in = m_inputEffects.at(i).get(); in->apply(); if (!in->hasResult()) return; // Convert input results to the current effect's color space. transformResultColorSpace(in, i); } determineAbsolutePaintRect(); setResultColorSpace(m_operatingColorSpace); if (!isFilterSizeValid(m_absolutePaintRect)) return; if (requiresValidPreMultipliedPixels()) { for (unsigned i = 0; i < size; ++i) inputEffect(i)->correctFilterResultIfNeeded(); } // Add platform specific apply functions here and return earlier. #if ENABLE(OPENCL) if (platformApplyOpenCL()) return; #endif platformApplySoftware(); }
void FilterEffect::applyRecursive() { if (hasResult()) return; unsigned size = m_inputEffects.size(); for (unsigned i = 0; i < size; ++i) { FilterEffect* in = m_inputEffects.at(i).get(); in->applyRecursive(); if (!in->hasResult()) return; // Convert input results to the current effect's color space. transformResultColorSpace(in, i); } setResultColorSpace(m_operatingColorSpace); if (!isFilterSizeValid(m_absolutePaintRect)) return; if (!mayProduceInvalidPreMultipliedPixels()) { for (unsigned i = 0; i < size; ++i) inputEffect(i)->correctFilterResultIfNeeded(); } applySoftware(); }
PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect& rect) { ASSERT(isFilterSizeValid(rect)); RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); copyPremultipliedImage(imageData.get(), rect); return imageData.release(); }
void FilterEffect::copyUnmultipliedImage(ByteArray* destination, const IntRect& rect) { ASSERT(hasResult()); if (!m_unmultipliedImageResult) { // We prefer a conversion from the image buffer. if (m_imageBufferResult) m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); else { ASSERT(isFilterSizeValid(m_absolutePaintRect)); m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); unsigned char* sourceComponent = m_premultipliedImageResult->data(); unsigned char* destinationComponent = m_unmultipliedImageResult->data(); unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); while (sourceComponent < end) { int alpha = sourceComponent[3]; if (alpha) { destinationComponent[0] = static_cast<int>(sourceComponent[0]) * 255 / alpha; destinationComponent[1] = static_cast<int>(sourceComponent[1]) * 255 / alpha; destinationComponent[2] = static_cast<int>(sourceComponent[2]) * 255 / alpha; } else { destinationComponent[0] = 0; destinationComponent[1] = 0; destinationComponent[2] = 0; } destinationComponent[3] = alpha; sourceComponent += 4; destinationComponent += 4; } } } copyImageBytes(m_unmultipliedImageResult.get(), destination, rect); }
PassRefPtr<ByteArray> FilterEffect::asUnmultipliedImage(const IntRect& rect) { ASSERT(isFilterSizeValid(rect)); RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4); copyUnmultipliedImage(imageData.get(), rect); return imageData.release(); }
GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* oldContext) { ASSERT(m_renderLayer); FilterEffectRenderer* filter = m_renderLayer->filterRenderer(); filter->allocateBackingStoreIfNeeded(); // Paint into the context that represents the SourceGraphic of the filter. GraphicsContext* sourceGraphicsContext = filter->inputContext(); if (!sourceGraphicsContext || !isFilterSizeValid(filter->absoluteFilterRegion())) { // Disable the filters and continue. m_haveFilterEffect = false; return oldContext; } m_savedGraphicsContext = oldContext; // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer. sourceGraphicsContext->save(); // FIXME: can we just use sourceImageRect for everything, and get rid of // m_repaintRect? FloatPoint offset = filter->sourceImageRect().location(); sourceGraphicsContext->translate(-offset.x(), -offset.y()); sourceGraphicsContext->clearRect(m_repaintRect); sourceGraphicsContext->clip(m_repaintRect); return sourceGraphicsContext; }
PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect) { ASSERT(isFilterSizeValid(rect)); IntSize scaledSize(rect.size()); scaledSize.scale(m_filter->filterScale()); RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4); copyUnmultipliedImage(imageData.get(), rect); return imageData.release(); }
bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect) { if (!filterRect.isZero() && isFilterSizeValid(filterRect)) { FloatRect currentSourceRect = sourceImageRect(); if (filterRect != currentSourceRect) { setSourceImageRect(filterRect); return true; } } return false; }
Uint8ClampedArray* FilterEffect::createPremultipliedImageResult() { // Only one result type is allowed. ASSERT(!hasResult()); ASSERT(isFilterSizeValid(m_absolutePaintRect)); if (m_absolutePaintRect.isEmpty()) return 0; m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); return m_premultipliedImageResult.get(); }
ImageBuffer* FilterEffect::createImageBufferResult() { // Only one result type is allowed. ASSERT(!hasResult()); ASSERT(isFilterSizeValid(m_absolutePaintRect)); OwnPtr<ImageBufferSurface> surface; surface = adoptPtr(new UnacceleratedImageBufferSurface(m_absolutePaintRect.size())); m_imageBufferResult = ImageBuffer::create(surface.release()); return m_imageBufferResult.get(); }
ByteArray* FilterEffect::createUnmultipliedImageResult() { // Only one result type is allowed. ASSERT(!hasResult()); ASSERT(isFilterSizeValid(m_absolutePaintRect)); determineAbsolutePaintRect(); if (m_absolutePaintRect.isEmpty()) return 0; m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); return m_unmultipliedImageResult.get(); }
Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult() { // Only one result type is allowed. ASSERT(!hasResult()); ASSERT(isFilterSizeValid(m_absolutePaintRect)); if (m_absolutePaintRect.isEmpty()) return 0; IntSize resultSize(m_absolutePaintRect.size()); resultSize.scale(m_filter->filterScale()); m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4); return m_unmultipliedImageResult.get(); }
bool FilterEffectRendererHelper::beginFilterEffect() { ASSERT(m_renderLayer); FilterEffectRenderer* filter = m_renderLayer->filterRenderer(); filter->allocateBackingStoreIfNeeded(); // Paint into the context that represents the SourceGraphic of the filter. GraphicsContext* sourceGraphicsContext = filter->inputContext(); if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) { // Disable the filters and continue. m_haveFilterEffect = false; return false; } // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer. sourceGraphicsContext->save(); sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y()); sourceGraphicsContext->clearRect(m_repaintRect); sourceGraphicsContext->clip(m_repaintRect); m_startedFilterEffect = true; return true; }