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