Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(934)

Unified Diff: Source/core/platform/graphics/filters/FilterEffect.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/platform/graphics/filters/FilterEffect.cpp
diff --git a/Source/core/platform/graphics/filters/FilterEffect.cpp b/Source/core/platform/graphics/filters/FilterEffect.cpp
deleted file mode 100644
index 849796d3adc6c16d218150a6e5463016caaafc17..0000000000000000000000000000000000000000
--- a/Source/core/platform/graphics/filters/FilterEffect.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com>
- * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
- * Copyright (C) 2012 University of Szeged
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#include "core/platform/graphics/filters/FilterEffect.h"
-
-#include "core/platform/graphics/ImageBuffer.h"
-#include "core/platform/graphics/filters/Filter.h"
-
-#if HAVE(ARM_NEON_INTRINSICS)
-#include <arm_neon.h>
-#endif
-
-namespace WebCore {
-
-FilterEffect::FilterEffect(Filter* filter)
- : m_alphaImage(false)
- , m_filter(filter)
- , m_hasX(false)
- , m_hasY(false)
- , m_hasWidth(false)
- , m_hasHeight(false)
- , m_clipsToBounds(true)
- , m_operatingColorSpace(ColorSpaceLinearRGB)
- , m_resultColorSpace(ColorSpaceDeviceRGB)
-{
- ASSERT(m_filter);
-}
-
-FilterEffect::~FilterEffect()
-{
-}
-
-inline bool isFilterSizeValid(IntRect rect)
-{
- if (rect.width() < 0 || rect.width() > kMaxFilterSize
- || rect.height() < 0 || rect.height() > kMaxFilterSize)
- return false;
- return true;
-}
-
-void FilterEffect::determineAbsolutePaintRect()
-{
- m_absolutePaintRect = IntRect();
- unsigned size = m_inputEffects.size();
- for (unsigned i = 0; i < size; ++i)
- m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect());
-
- // Filters in SVG clip to primitive subregion, while CSS doesn't.
- if (m_clipsToBounds)
- m_absolutePaintRect.intersect(enclosingIntRect(m_maxEffectRect));
- else
- m_absolutePaintRect.unite(enclosingIntRect(m_maxEffectRect));
-
-}
-
-FloatRect FilterEffect::mapRectRecursive(const FloatRect& rect)
-{
- FloatRect result;
- if (m_inputEffects.size() > 0) {
- result = m_inputEffects.at(0)->mapRectRecursive(rect);
- for (unsigned i = 1; i < m_inputEffects.size(); ++i)
- result.unite(m_inputEffects.at(i)->mapRectRecursive(rect));
- } else
- result = rect;
- return mapRect(result);
-}
-
-FloatRect FilterEffect::getSourceRect(const FloatRect& destRect, const FloatRect& destClipRect)
-{
- FloatRect sourceRect = mapRect(destRect, false);
- FloatRect sourceClipRect = mapRect(destClipRect, false);
-
- FloatRect boundaries = effectBoundaries();
- if (hasX())
- sourceClipRect.setX(boundaries.x());
- if (hasY())
- sourceClipRect.setY(boundaries.y());
- if (hasWidth())
- sourceClipRect.setWidth(boundaries.width());
- if (hasHeight())
- sourceClipRect.setHeight(boundaries.height());
-
- FloatRect result;
- if (m_inputEffects.size() > 0) {
- result = m_inputEffects.at(0)->getSourceRect(sourceRect, sourceClipRect);
- for (unsigned i = 1; i < m_inputEffects.size(); ++i)
- result.unite(m_inputEffects.at(i)->getSourceRect(sourceRect, sourceClipRect));
- } else {
- result = sourceRect;
- result.intersect(sourceClipRect);
- }
- return result;
-}
-
-IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
-{
- ASSERT(hasResult());
- IntPoint location = m_absolutePaintRect.location();
- location.moveBy(-effectRect.location());
- return IntRect(location, m_absolutePaintRect.size());
-}
-
-IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
-{
- return IntRect(IntPoint(srcRect.x() - m_absolutePaintRect.x(),
- srcRect.y() - m_absolutePaintRect.y()), srcRect.size());
-}
-
-FilterEffect* FilterEffect::inputEffect(unsigned number) const
-{
- ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
- return m_inputEffects.at(number).get();
-}
-
-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();
- }
-
- if (applySkia())
- return;
-
- applySoftware();
-}
-
-void FilterEffect::forceValidPreMultipliedPixels()
-{
- // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
- if (!m_premultipliedImageResult)
- return;
-
- Uint8ClampedArray* imageArray = m_premultipliedImageResult.get();
- unsigned char* pixelData = imageArray->data();
- int pixelArrayLength = imageArray->length();
-
- // We must have four bytes per pixel, and complete pixels
- ASSERT(!(pixelArrayLength % 4));
-
-#if HAVE(ARM_NEON_INTRINSICS)
- if (pixelArrayLength >= 64) {
- unsigned char* lastPixel = pixelData + (pixelArrayLength & ~0x3f);
- do {
- // Increments pixelData by 64.
- uint8x16x4_t sixteenPixels = vld4q_u8(pixelData);
- sixteenPixels.val[0] = vminq_u8(sixteenPixels.val[0], sixteenPixels.val[3]);
- sixteenPixels.val[1] = vminq_u8(sixteenPixels.val[1], sixteenPixels.val[3]);
- sixteenPixels.val[2] = vminq_u8(sixteenPixels.val[2], sixteenPixels.val[3]);
- vst4q_u8(pixelData, sixteenPixels);
- pixelData += 64;
- } while (pixelData < lastPixel);
-
- pixelArrayLength &= 0x3f;
- if (!pixelArrayLength)
- return;
- }
-#endif
-
- int numPixels = pixelArrayLength / 4;
-
- // Iterate over each pixel, checking alpha and adjusting color components if necessary
- while (--numPixels >= 0) {
- // Alpha is the 4th byte in a pixel
- unsigned char a = *(pixelData + 3);
- // Clamp each component to alpha, and increment the pixel location
- for (int i = 0; i < 3; ++i) {
- if (*pixelData > a)
- *pixelData = a;
- ++pixelData;
- }
- // Increment for alpha
- ++pixelData;
- }
-}
-
-void FilterEffect::clearResult()
-{
- if (m_imageBufferResult)
- m_imageBufferResult.clear();
- if (m_unmultipliedImageResult)
- m_unmultipliedImageResult.clear();
- if (m_premultipliedImageResult)
- m_premultipliedImageResult.clear();
-}
-
-void FilterEffect::clearResultsRecursive()
-{
- // Clear all results, regardless that the current effect has
- // a result. Can be used if an effect is in an erroneous state.
- if (hasResult())
- clearResult();
-
- unsigned size = m_inputEffects.size();
- for (unsigned i = 0; i < size; ++i)
- m_inputEffects.at(i).get()->clearResultsRecursive();
-}
-
-ImageBuffer* FilterEffect::asImageBuffer()
-{
- if (!hasResult())
- return 0;
- if (m_imageBufferResult)
- return m_imageBufferResult.get();
- m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), 1, m_filter->renderingMode());
- IntRect destinationRect(IntPoint(), m_absolutePaintRect.size());
- if (m_premultipliedImageResult)
- m_imageBufferResult->putByteArray(Premultiplied, m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
- else
- m_imageBufferResult->putByteArray(Unmultiplied, m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
- return m_imageBufferResult.get();
-}
-
-PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect)
-{
- ASSERT(isFilterSizeValid(rect));
- RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
- copyUnmultipliedImage(imageData.get(), rect);
- return imageData.release();
-}
-
-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();
-}
-
-inline void FilterEffect::copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect& rect)
-{
- // Initialize the destination to transparent black, if not entirely covered by the source.
- if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_absolutePaintRect.width() || rect.maxY() > m_absolutePaintRect.height())
- memset(destination->data(), 0, destination->length());
-
- // Early return if the rect does not intersect with the source.
- if (rect.maxX() <= 0 || rect.maxY() <= 0 || rect.x() >= m_absolutePaintRect.width() || rect.y() >= m_absolutePaintRect.height())
- return;
-
- int xOrigin = rect.x();
- int xDest = 0;
- if (xOrigin < 0) {
- xDest = -xOrigin;
- xOrigin = 0;
- }
- int xEnd = rect.maxX();
- if (xEnd > m_absolutePaintRect.width())
- xEnd = m_absolutePaintRect.width();
-
- int yOrigin = rect.y();
- int yDest = 0;
- if (yOrigin < 0) {
- yDest = -yOrigin;
- yOrigin = 0;
- }
- int yEnd = rect.maxY();
- if (yEnd > m_absolutePaintRect.height())
- yEnd = m_absolutePaintRect.height();
-
- int size = (xEnd - xOrigin) * 4;
- int destinationScanline = rect.width() * 4;
- int sourceScanline = m_absolutePaintRect.width() * 4;
- unsigned char *destinationPixel = destination->data() + ((yDest * rect.width()) + xDest) * 4;
- unsigned char *sourcePixel = source->data() + ((yOrigin * m_absolutePaintRect.width()) + xOrigin) * 4;
-
- while (yOrigin < yEnd) {
- memcpy(destinationPixel, sourcePixel, size);
- destinationPixel += destinationScanline;
- sourcePixel += sourceScanline;
- ++yOrigin;
- }
-}
-
-void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* 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 = Uint8ClampedArray::createUninitialized(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);
-}
-
-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));
- m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
- unsigned char* sourceComponent = m_unmultipliedImageResult->data();
- unsigned char* destinationComponent = m_premultipliedImageResult->data();
- unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.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);
-}
-
-ImageBuffer* FilterEffect::createImageBufferResult()
-{
- // Only one result type is allowed.
- ASSERT(!hasResult());
- if (m_absolutePaintRect.isEmpty())
- return 0;
- m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), 1, m_filter->renderingMode());
- if (!m_imageBufferResult)
- return 0;
- ASSERT(m_imageBufferResult->context());
- return m_imageBufferResult.get();
-}
-
-Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult()
-{
- // Only one result type is allowed.
- ASSERT(!hasResult());
- ASSERT(isFilterSizeValid(m_absolutePaintRect));
-
- if (m_absolutePaintRect.isEmpty())
- return 0;
- m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
- return m_unmultipliedImageResult.get();
-}
-
-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();
-}
-
-void FilterEffect::transformResultColorSpace(ColorSpace dstColorSpace)
-{
- if (!hasResult() || dstColorSpace == m_resultColorSpace)
- return;
-
- // FIXME: We can avoid this potentially unnecessary ImageBuffer conversion by adding
- // color space transform support for the {pre,un}multiplied arrays.
- asImageBuffer()->transformColorSpace(m_resultColorSpace, dstColorSpace);
-
- m_resultColorSpace = dstColorSpace;
-
- if (m_unmultipliedImageResult)
- m_unmultipliedImageResult.clear();
- if (m_premultipliedImageResult)
- m_premultipliedImageResult.clear();
-}
-
-TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const
-{
- // FIXME: We should dump the subRegions of the filter primitives here later. This isn't
- // possible at the moment, because we need more detailed informations from the target object.
- return ts;
-}
-
-FloatRect FilterEffect::determineFilterPrimitiveSubregion(DetermineSubregionFlags flags)
-{
- ASSERT(filter());
-
- // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
- FloatRect subregion;
- if (unsigned numberOfInputEffects = inputEffects().size()) {
- subregion = inputEffect(0)->determineFilterPrimitiveSubregion(flags);
- for (unsigned i = 1; i < numberOfInputEffects; ++i)
- subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion(flags));
- } else
- subregion = filter()->filterRegion();
-
- // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
- if (filterEffectType() == FilterEffectTypeTile)
- subregion = filter()->filterRegion();
-
- if (flags & MapRectForward)
- subregion = mapRect(subregion);
-
- FloatRect boundaries = effectBoundaries();
- if (hasX())
- subregion.setX(boundaries.x());
- if (hasY())
- subregion.setY(boundaries.y());
- if (hasWidth())
- subregion.setWidth(boundaries.width());
- if (hasHeight())
- subregion.setHeight(boundaries.height());
-
- setFilterPrimitiveSubregion(subregion);
-
- FloatRect absoluteSubregion = filter()->absoluteTransform().mapRect(subregion);
- FloatSize filterResolution = filter()->filterResolution();
- absoluteSubregion.scale(filterResolution.width(), filterResolution.height());
-
- // Clip every filter effect to the filter region.
- if (flags & ClipToFilterRegion) {
- FloatRect absoluteScaledFilterRegion = filter()->absoluteFilterRegion();
- absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
- absoluteSubregion.intersect(absoluteScaledFilterRegion);
- }
-
- setMaxEffectRect(absoluteSubregion);
- return subregion;
-}
-
-PassRefPtr<SkImageFilter> FilterEffect::createImageFilter(SkiaImageFilterBuilder* builder)
-{
- return 0;
-}
-
-SkImageFilter::CropRect FilterEffect::getCropRect(const FloatSize& cropOffset) const
-{
- SkRect rect = SkRect::MakeEmpty();
- uint32_t flags = 0;
- FloatRect boundaries = effectBoundaries();
- FloatSize resolution = filter()->filterResolution();
- boundaries.scale(resolution.width(), resolution.height());
- boundaries.move(cropOffset);
- if (hasX()) {
- rect.fLeft = boundaries.x();
- flags |= SkImageFilter::CropRect::kHasLeft_CropEdge;
- }
- if (hasY()) {
- rect.fTop = boundaries.y();
- flags |= SkImageFilter::CropRect::kHasTop_CropEdge;
- }
- if (hasWidth()) {
- rect.fRight = rect.fLeft + boundaries.width();
- flags |= SkImageFilter::CropRect::kHasRight_CropEdge;
- }
- if (hasHeight()) {
- rect.fBottom = rect.fTop + boundaries.height();
- flags |= SkImageFilter::CropRect::kHasBottom_CropEdge;
- }
- return SkImageFilter::CropRect(rect, flags);
-}
-
-} // namespace WebCore
« no previous file with comments | « Source/core/platform/graphics/filters/FilterEffect.h ('k') | Source/core/platform/graphics/filters/FilterOperation.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698