15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/cpu/arm/filters/FEBlendNEON.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/FEBlend.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/GraphicsContext.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/Filter.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/text/TextStream.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderTreeAsText.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "SkBitmapSource.h"
38e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "SkXfermodeImageFilter.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/SkiaImageFilterBuilder.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/skia/NativeImageSkia.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FEBlend::FEBlend(Filter* filter, BlendModeType mode)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : FilterEffect(filter)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_mode(mode)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new FEBlend(filter, mode));
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)BlendModeType FEBlend::blendMode() const
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_mode;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEBlend::setBlendMode(BlendModeType mode)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_mode == mode)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_mode = mode;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline unsigned char fastDivideBy255(uint16_t value)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is an approximate algorithm for division by 255, but it gives accurate results for 16bit values.
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint16_t quotient = value >> 8;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint16_t remainder = value - (quotient * 255) + 1;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return quotient + (remainder >> 8);
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendNormal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastDivideBy255((255 - alphaA) * colorB + colorA * 255);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendMultiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastDivideBy255((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA);
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendScreen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastDivideBy255((colorB + colorA) * 255 - colorA * colorB);
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendDarken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastDivideBy255(std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendLighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastDivideBy255(std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned char feBlendUnknown(unsigned char, unsigned char, unsigned char, unsigned char)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template<BlendType BlendFunction>
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void platformApply(unsigned char* sourcePixelA, unsigned char* sourcePixelB,
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          unsigned char* destinationPixel, unsigned pixelArrayLength)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned len = pixelArrayLength / 4;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned pixelOffset = 0; pixelOffset < len; pixelOffset++) {
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char alphaA = sourcePixelA[3];
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char alphaB = sourcePixelB[3];
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationPixel[0] = BlendFunction(sourcePixelA[0], sourcePixelB[0], alphaA, alphaB);
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationPixel[1] = BlendFunction(sourcePixelA[1], sourcePixelB[1], alphaA, alphaB);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationPixel[2] = BlendFunction(sourcePixelA[2], sourcePixelB[2], alphaA, alphaB);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationPixel[3] = 255 - fastDivideBy255((255 - alphaA) * (255 - alphaB));
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sourcePixelA += 4;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sourcePixelB += 4;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationPixel += 4;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEBlend::platformApplyGeneric(unsigned char* sourcePixelA, unsigned char* sourcePixelB,
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                   unsigned char* destinationPixel, unsigned pixelArrayLength)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (m_mode) {
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_NORMAL:
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendNormal>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_MULTIPLY:
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendMultiply>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_SCREEN:
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendScreen>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_DARKEN:
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendDarken>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_LIGHTEN:
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendLighten>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_UNKNOWN:
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApply<feBlendUnknown>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEBlend::applySoftware()
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* in = inputEffect(0);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* in2 = inputEffect(1);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!dstPixelArray)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned pixelArrayLength = srcPixelArrayA->length();
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(pixelArrayLength == srcPixelArrayB->length());
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE(ARM_NEON_INTRINSICS)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (pixelArrayLength >= 8)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else { // If there is just one pixel we expand it to two.
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(pixelArrayLength > 0);
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t sourceA[2] = {0, 0};
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t sourceBAndDest[2] = {0, 0};
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0];
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0];
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    platformApplyGeneric(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
190e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic SkXfermode::Mode toSkiaMode(BlendModeType mode)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    switch (mode) {
19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FEBLEND_MODE_NORMAL:
194e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kSrcOver_Mode;
19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FEBLEND_MODE_MULTIPLY:
196e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kMultiply_Mode;
19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FEBLEND_MODE_SCREEN:
198e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kScreen_Mode;
19953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FEBLEND_MODE_DARKEN:
200e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kDarken_Mode;
20153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FEBLEND_MODE_LIGHTEN:
202e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kLighten_Mode;
20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    default:
204e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return SkXfermode::kSrcOver_Mode;
20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
20653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
20753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool FEBlend::applySkia()
20953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
21053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // For now, only use the skia implementation for accelerated rendering.
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (filter()->renderingMode() != Accelerated)
21253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
21353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FilterEffect* in = inputEffect(0);
21553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FilterEffect* in2 = inputEffect(1);
21653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!in || !in2)
21853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
21953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
22153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!resultImage)
22253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
22353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
22453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<Image> foreground = in->asImageBuffer()->copyImage(DontCopyBackingStore);
22553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<Image> background = in2->asImageBuffer()->copyImage(DontCopyBackingStore);
22653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
22753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<NativeImageSkia> foregroundNativeImage = foreground->nativeImageForCurrentFrame();
22853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<NativeImageSkia> backgroundNativeImage = background->nativeImageForCurrentFrame();
22953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
23053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!foregroundNativeImage || !backgroundNativeImage)
23153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
23253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
23353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkBitmap foregroundBitmap = foregroundNativeImage->bitmap();
23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkBitmap backgroundBitmap = backgroundNativeImage->bitmap();
23553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
23653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkAutoTUnref<SkImageFilter> backgroundSource(new SkBitmapSource(backgroundBitmap));
237e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toSkiaMode(m_mode)));
238e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    SkAutoTUnref<SkImageFilter> blend(new SkXfermodeImageFilter(mode, backgroundSource));
23953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPaint paint;
24053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    paint.setImageFilter(blend);
24153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    resultImage->context()->drawBitmap(foregroundBitmap, 0, 0, &paint);
24253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return true;
24353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
24453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
245e6d4491e48613634a83c1957c72759da80987961Ben MurdochPassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* builder)
24653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
247e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace()));
248e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace()));
249e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(toSkiaMode(m_mode)));
250e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    return adoptRef(new SkXfermodeImageFilter(mode, background.get(), foreground.get()));
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_UNKNOWN:
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "UNKNOWN";
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_NORMAL:
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "NORMAL";
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_MULTIPLY:
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "MULTIPLY";
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_SCREEN:
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "SCREEN";
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_DARKEN:
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "DARKEN";
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FEBLEND_MODE_LIGHTEN:
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "LIGHTEN";
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "[feBlend";
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect::externalRepresentation(ts);
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " mode=\"" << m_mode << "\"]\n";
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inputEffect(0)->externalRepresentation(ts, indent + 1);
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inputEffect(1)->externalRepresentation(ts, indent + 1);
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
290