15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2012 University of Szeged 653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/FilterEffect.h" 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/ImageBuffer.h" 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/Filter.h" 30e6d4491e48613634a83c1957c72759da80987961Ben Murdoch#include "third_party/skia/include/core/SkImageFilter.h" 317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h" 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE(ARM_NEON_INTRINSICS) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <arm_neon.h> 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FilterEffect::FilterEffect(Filter* filter) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_alphaImage(false) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_filter(filter) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasX(false) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasY(false) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasWidth(false) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasHeight(false) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_clipsToBounds(true) 47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) , m_operatingColorSpace(ColorSpaceLinearRGB) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_resultColorSpace(ColorSpaceDeviceRGB) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_filter); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FilterEffect::~FilterEffect() 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool isFilterSizeValid(IntRect rect) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.width() < 0 || rect.width() > kMaxFilterSize 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || rect.height() < 0 || rect.height() > kMaxFilterSize) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::determineAbsolutePaintRect() 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_absolutePaintRect = IntRect(); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned size = m_inputEffects.size(); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < size; ++i) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect()); 7102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Filters in SVG clip to primitive subregion, while CSS doesn't. 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_clipsToBounds) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_absolutePaintRect.intersect(enclosingIntRect(m_maxEffectRect)); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_absolutePaintRect.unite(enclosingIntRect(m_maxEffectRect)); 7702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 80e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)FloatRect FilterEffect::mapRectRecursive(const FloatRect& rect) 81e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){ 82e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect result; 83e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (m_inputEffects.size() > 0) { 84e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result = m_inputEffects.at(0)->mapRectRecursive(rect); 85e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) for (unsigned i = 1; i < m_inputEffects.size(); ++i) 86e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result.unite(m_inputEffects.at(i)->mapRectRecursive(rect)); 87e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } else 88e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result = rect; 89e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) return mapRect(result); 90e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)} 91e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 92e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)FloatRect FilterEffect::getSourceRect(const FloatRect& destRect, const FloatRect& destClipRect) 93e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){ 94e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect sourceRect = mapRect(destRect, false); 95e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect sourceClipRect = mapRect(destClipRect, false); 96e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 97e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect boundaries = effectBoundaries(); 98e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasX()) 99e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) sourceClipRect.setX(boundaries.x()); 100e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasY()) 101e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) sourceClipRect.setY(boundaries.y()); 102e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasWidth()) 103e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) sourceClipRect.setWidth(boundaries.width()); 104e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasHeight()) 105e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) sourceClipRect.setHeight(boundaries.height()); 106e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 107e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect result; 108e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (m_inputEffects.size() > 0) { 109e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result = m_inputEffects.at(0)->getSourceRect(sourceRect, sourceClipRect); 110e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) for (unsigned i = 1; i < m_inputEffects.size(); ++i) 111e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result.unite(m_inputEffects.at(i)->getSourceRect(sourceRect, sourceClipRect)); 112e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } else { 113e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result = sourceRect; 114e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) result.intersect(sourceClipRect); 115e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } 116e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) return result; 117e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)} 118e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(hasResult()); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntPoint location = m_absolutePaintRect.location(); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) location.moveBy(-effectRect.location()); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntRect(location, m_absolutePaintRect.size()); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return IntRect(IntPoint(srcRect.x() - m_absolutePaintRect.x(), 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) srcRect.y() - m_absolutePaintRect.y()), srcRect.size()); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FilterEffect* FilterEffect::inputEffect(unsigned number) const 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size()); 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_inputEffects.at(number).get(); 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::apply() 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (hasResult()) 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned size = m_inputEffects.size(); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < size; ++i) { 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect* in = m_inputEffects.at(i).get(); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) in->apply(); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!in->hasResult()) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Convert input results to the current effect's color space. 151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) transformResultColorSpace(in, i); 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) determineAbsolutePaintRect(); 155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) setResultColorSpace(m_operatingColorSpace); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isFilterSizeValid(m_absolutePaintRect)) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (requiresValidPreMultipliedPixels()) { 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < size; ++i) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) inputEffect(i)->correctFilterResultIfNeeded(); 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 16402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (applySkia()) 166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 16853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) applySoftware(); 169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::forceValidPreMultipliedPixels() 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Must operate on pre-multiplied results; other formats cannot have invalid pixels. 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_premultipliedImageResult) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Uint8ClampedArray* imageArray = m_premultipliedImageResult.get(); 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* pixelData = imageArray->data(); 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int pixelArrayLength = imageArray->length(); 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We must have four bytes per pixel, and complete pixels 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!(pixelArrayLength % 4)); 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE(ARM_NEON_INTRINSICS) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pixelArrayLength >= 64) { 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* lastPixel = pixelData + (pixelArrayLength & ~0x3f); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Increments pixelData by 64. 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uint8x16x4_t sixteenPixels = vld4q_u8(pixelData); 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sixteenPixels.val[0] = vminq_u8(sixteenPixels.val[0], sixteenPixels.val[3]); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sixteenPixels.val[1] = vminq_u8(sixteenPixels.val[1], sixteenPixels.val[3]); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sixteenPixels.val[2] = vminq_u8(sixteenPixels.val[2], sixteenPixels.val[3]); 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) vst4q_u8(pixelData, sixteenPixels); 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixelData += 64; 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while (pixelData < lastPixel); 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixelArrayLength &= 0x3f; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!pixelArrayLength) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int numPixels = pixelArrayLength / 4; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Iterate over each pixel, checking alpha and adjusting color components if necessary 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (--numPixels >= 0) { 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Alpha is the 4th byte in a pixel 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char a = *(pixelData + 3); 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clamp each component to alpha, and increment the pixel location 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (*pixelData > a) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *pixelData = a; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++pixelData; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Increment for alpha 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++pixelData; 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::clearResult() 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_imageBufferResult) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_imageBufferResult.clear(); 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_unmultipliedImageResult) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_unmultipliedImageResult.clear(); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_premultipliedImageResult) 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_premultipliedImageResult.clear(); 228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void FilterEffect::clearResultsRecursive() 231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Clear all results, regardless that the current effect has 233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // a result. Can be used if an effect is in an erroneous state. 234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (hasResult()) 235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) clearResult(); 236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) unsigned size = m_inputEffects.size(); 238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for (unsigned i = 0; i < size; ++i) 239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_inputEffects.at(i).get()->clearResultsRecursive(); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ImageBuffer* FilterEffect::asImageBuffer() 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!hasResult()) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_imageBufferResult) 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_imageBufferResult.get(); 2485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), 1, m_filter->renderingMode()); 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect destinationRect(IntPoint(), m_absolutePaintRect.size()); 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_premultipliedImageResult) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_imageBufferResult->putByteArray(Premultiplied, m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_imageBufferResult->putByteArray(Unmultiplied, m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_imageBufferResult.get(); 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(rect)); 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copyUnmultipliedImage(imageData.get(), rect); 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return imageData.release(); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect& rect) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(rect)); 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copyPremultipliedImage(imageData.get(), rect); 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return imageData.release(); 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline void FilterEffect::copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect& rect) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Initialize the destination to transparent black, if not entirely covered by the source. 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_absolutePaintRect.width() || rect.maxY() > m_absolutePaintRect.height()) 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(destination->data(), 0, destination->length()); 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Early return if the rect does not intersect with the source. 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (rect.maxX() <= 0 || rect.maxY() <= 0 || rect.x() >= m_absolutePaintRect.width() || rect.y() >= m_absolutePaintRect.height()) 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int xOrigin = rect.x(); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int xDest = 0; 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (xOrigin < 0) { 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xDest = -xOrigin; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xOrigin = 0; 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int xEnd = rect.maxX(); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (xEnd > m_absolutePaintRect.width()) 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xEnd = m_absolutePaintRect.width(); 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int yOrigin = rect.y(); 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int yDest = 0; 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (yOrigin < 0) { 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) yDest = -yOrigin; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) yOrigin = 0; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int yEnd = rect.maxY(); 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (yEnd > m_absolutePaintRect.height()) 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) yEnd = m_absolutePaintRect.height(); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int size = (xEnd - xOrigin) * 4; 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int destinationScanline = rect.width() * 4; 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int sourceScanline = m_absolutePaintRect.width() * 4; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char *destinationPixel = destination->data() + ((yDest * rect.width()) + xDest) * 4; 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char *sourcePixel = source->data() + ((yOrigin * m_absolutePaintRect.width()) + xOrigin) * 4; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (yOrigin < yEnd) { 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destinationPixel, sourcePixel, size); 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationPixel += destinationScanline; 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sourcePixel += sourceScanline; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++yOrigin; 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* destination, const IntRect& rect) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(hasResult()); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_unmultipliedImageResult) { 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We prefer a conversion from the image buffer. 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_imageBufferResult) 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(m_absolutePaintRect)); 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* sourceComponent = m_premultipliedImageResult->data(); 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* destinationComponent = m_unmultipliedImageResult->data(); 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (sourceComponent < end) { 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int alpha = sourceComponent[3]; 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (alpha) { 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[0] = static_cast<int>(sourceComponent[0]) * 255 / alpha; 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[1] = static_cast<int>(sourceComponent[1]) * 255 / alpha; 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[2] = static_cast<int>(sourceComponent[2]) * 255 / alpha; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[0] = 0; 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[1] = 0; 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[2] = 0; 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[3] = alpha; 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sourceComponent += 4; 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent += 4; 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copyImageBytes(m_unmultipliedImageResult.get(), destination, rect); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect& rect) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(hasResult()); 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_premultipliedImageResult) { 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We prefer a conversion from the image buffer. 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_imageBufferResult) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(m_absolutePaintRect)); 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* sourceComponent = m_unmultipliedImageResult->data(); 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* destinationComponent = m_premultipliedImageResult->data(); 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (sourceComponent < end) { 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int alpha = sourceComponent[3]; 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255; 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[1] = static_cast<int>(sourceComponent[1]) * alpha / 255; 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[2] = static_cast<int>(sourceComponent[2]) * alpha / 255; 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent[3] = alpha; 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sourceComponent += 4; 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destinationComponent += 4; 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) copyImageBytes(m_premultipliedImageResult.get(), destination, rect); 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ImageBuffer* FilterEffect::createImageBufferResult() 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only one result type is allowed. 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!hasResult()); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_absolutePaintRect.isEmpty()) 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 3855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), 1, m_filter->renderingMode()); 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_imageBufferResult) 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_imageBufferResult->context()); 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_imageBufferResult.get(); 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult() 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only one result type is allowed. 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!hasResult()); 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(m_absolutePaintRect)); 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_absolutePaintRect.isEmpty()) 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_unmultipliedImageResult.get(); 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Uint8ClampedArray* FilterEffect::createPremultipliedImageResult() 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Only one result type is allowed. 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!hasResult()); 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isFilterSizeValid(m_absolutePaintRect)); 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_absolutePaintRect.isEmpty()) 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_premultipliedImageResult.get(); 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FilterEffect::transformResultColorSpace(ColorSpace dstColorSpace) 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!hasResult() || dstColorSpace == m_resultColorSpace) 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // FIXME: We can avoid this potentially unnecessary ImageBuffer conversion by adding 42253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // color space transform support for the {pre,un}multiplied arrays. 42353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) asImageBuffer()->transformColorSpace(m_resultColorSpace, dstColorSpace); 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_resultColorSpace = dstColorSpace; 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_unmultipliedImageResult) 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_unmultipliedImageResult.clear(); 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_premultipliedImageResult) 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_premultipliedImageResult.clear(); 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We should dump the subRegions of the filter primitives here later. This isn't 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // possible at the moment, because we need more detailed informations from the target object. 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ts; 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 440e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)FloatRect FilterEffect::determineFilterPrimitiveSubregion() 441e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){ 442e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) ASSERT(filter()); 443e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 444e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect. 445e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect subregion; 446e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (unsigned numberOfInputEffects = inputEffects().size()) { 447e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion = inputEffect(0)->determineFilterPrimitiveSubregion(); 448e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) for (unsigned i = 1; i < numberOfInputEffects; ++i) 449e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion()); 450e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) } else 451e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion = filter()->filterRegion(); 452e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 453e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>. 454e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (filterEffectType() == FilterEffectTypeTile) 455e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion = filter()->filterRegion(); 456e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 457e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion = mapRect(subregion); 458e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 459e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect boundaries = effectBoundaries(); 460e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasX()) 461e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion.setX(boundaries.x()); 462e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasY()) 463e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion.setY(boundaries.y()); 464e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasWidth()) 465e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion.setWidth(boundaries.width()); 466e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) if (hasHeight()) 467e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) subregion.setHeight(boundaries.height()); 468e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 469e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) setFilterPrimitiveSubregion(subregion); 470e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 471e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatRect absoluteSubregion = filter()->absoluteTransform().mapRect(subregion); 472e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) FloatSize filterResolution = filter()->filterResolution(); 473e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) absoluteSubregion.scale(filterResolution.width(), filterResolution.height()); 474e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 475e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) setMaxEffectRect(absoluteSubregion); 476e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) return subregion; 477e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)} 478e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles) 479e6d4491e48613634a83c1957c72759da80987961Ben MurdochPassRefPtr<SkImageFilter> FilterEffect::createImageFilter(SkiaImageFilterBuilder* builder) 480e6d4491e48613634a83c1957c72759da80987961Ben Murdoch{ 481e6d4491e48613634a83c1957c72759da80987961Ben Murdoch return 0; 482e6d4491e48613634a83c1957c72759da80987961Ben Murdoch} 483e6d4491e48613634a83c1957c72759da80987961Ben Murdoch 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 485