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) Research In Motion Limited 2010. All rights reserved.
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)
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FEComposite.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "SkArithmeticMode.h"
30521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "SkXfermodeImageFilter.h"
31521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/cpu/arm/filters/FECompositeArithmeticNEON.h"
34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextStream.h"
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "third_party/skia/include/core/SkDevice.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h"
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FEComposite::FEComposite(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : FilterEffect(filter)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_type(type)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_k1(k1)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_k2(k2)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_k3(k3)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_k4(k4)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<FEComposite> FEComposite::create(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new FEComposite(filter, type, k1, k2, k3, k4));
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CompositeOperationType FEComposite::operation() const
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_type;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEComposite::setOperation(CompositeOperationType type)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_type == type)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_type = type;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEComposite::k1() const
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_k1;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEComposite::setK1(float k1)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_k1 == k1)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_k1 = k1;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEComposite::k2() const
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_k2;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEComposite::setK2(float k2)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_k2 == k2)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_k2 = k2;
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEComposite::k3() const
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_k3;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEComposite::setK3(float k3)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_k3 == k3)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_k3 = k3;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEComposite::k4() const
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_k4;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEComposite::setK4(float k4)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_k4 == k4)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_k4 = k4;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEComposite::correctFilterResultIfNeeded()
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_type != FECOMPOSITE_OPERATOR_ARITHMETIC)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    forceValidPreMultipliedPixels();
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <int b1, int b4>
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void computeArithmeticPixels(unsigned char* source, unsigned char* destination, int pixelArrayLength,
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                    float k1, float k2, float k3, float k4)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledK1;
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledK4;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (b1)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scaledK1 = k1 / 255.0f;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (b4)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scaledK4 = k4 * 255.0f;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (--pixelArrayLength >= 0) {
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char i1 = *source;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char i2 = *destination;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float result = k2 * i1 + k3 * i2;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (b1)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result += scaledK1 * i1 * i2;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (b4)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result += scaledK4;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (result <= 0)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *destination = 0;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (result >= 255)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *destination = 255;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *destination = result;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++source;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++destination;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// computeArithmeticPixelsUnclamped is a faster version of computeArithmeticPixels for the common case where clamping
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// is not necessary. This enables aggresive compiler optimizations such as auto-vectorization.
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template <int b1, int b4>
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void computeArithmeticPixelsUnclamped(unsigned char* source, unsigned char* destination, int pixelArrayLength, float k1, float k2, float k3, float k4)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledK1;
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledK4;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (b1)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scaledK1 = k1 / 255.0f;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (b4)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scaledK4 = k4 * 255.0f;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (--pixelArrayLength >= 0) {
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char i1 = *source;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned char i2 = *destination;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float result = k2 * i1 + k3 * i2;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (b1)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result += scaledK1 * i1 * i2;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (b4)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result += scaledK4;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *destination = result;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++source;
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++destination;
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void arithmeticSoftware(unsigned char* source, unsigned char* destination, int pixelArrayLength, float k1, float k2, float k3, float k4)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float upperLimit = std::max(0.0f, k1) + std::max(0.0f, k2) + std::max(0.0f, k3) + k4;
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float lowerLimit = std::min(0.0f, k1) + std::min(0.0f, k2) + std::min(0.0f, k3) + k4;
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((k4 >= 0.0f && k4 <= 1.0f) && (upperLimit >= 0.0f && upperLimit <= 1.0f) && (lowerLimit >= 0.0f && lowerLimit <= 1.0f)) {
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (k4) {
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (k1)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                computeArithmeticPixelsUnclamped<1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                computeArithmeticPixelsUnclamped<0, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (k1)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                computeArithmeticPixelsUnclamped<1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                computeArithmeticPixelsUnclamped<0, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (k4) {
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (k1)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            computeArithmeticPixels<1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            computeArithmeticPixels<0, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (k1)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            computeArithmeticPixels<1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            computeArithmeticPixels<0, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline void FEComposite::platformArithmeticSoftware(Uint8ClampedArray* source, Uint8ClampedArray* destination,
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float k1, float k2, float k3, float k4)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int length = source->length();
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(length == static_cast<int>(destination->length()));
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The selection here eventually should happen dynamically.
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if HAVE(ARM_NEON_INTRINSICS)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!(length & 0x3));
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    platformArithmeticNeon(source->data(), destination->data(), length, k1, k2, k3, k4);
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    arithmeticSoftware(source->data(), destination->data(), length, k1, k2, k3, k4);
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect requestedRect = originalRequestedRect;
23709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (clipsToBounds())
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        requestedRect.intersect(maxEffectRect());
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // We may be called multiple times if result is used more than once. Return
24109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // quickly if nothing new is required.
24209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return requestedRect;
24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // No mapPaintRect required for FEComposite.
24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect);
24709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect affectedRect;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (m_type) {
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_IN:
25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // 'in' has output only in the intersection of both inputs.
25109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect));
25209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_ATOP:
25409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // 'atop' has output only in the extents of the second input.
25509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Make sure first input knows where it needs to produce output.
25609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        inputEffect(0)->determineAbsolutePaintRect(input1Rect);
25709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        affectedRect = input1Rect;
25809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_ARITHMETIC:
26009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (k4() > 0) {
26109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // Make sure first input knows where it needs to produce output.
26209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            inputEffect(0)->determineAbsolutePaintRect(requestedRect);
26309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // Arithmetic with non-zero k4 may influnce the complete filter primitive
26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // region. So we can't optimize the paint region here.
26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            affectedRect = requestedRect;
26609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            break;
26709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (k2() <= 0) {
26909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // Input 0 does not appear where input 1 is not present.
27009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect);
27109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (k3() > 0) {
27209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                affectedRect = input1Rect;
27309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            } else {
27409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                // Just k1 is positive. Use intersection.
27509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                affectedRect = intersection(input1Rect, input0Rect);
27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            }
27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            break;
27809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
27909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // else fall through to use union
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Take the union of both input effects.
28209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect));
28309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
28509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
28609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    affectedRect.intersect(requestedRect);
28709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addAbsolutePaintRect(affectedRect);
28809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return affectedRect;
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEComposite::applySoftware()
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* in = inputEffect(0);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* in2 = inputEffect(1);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!dstPixelArray)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect);
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect);
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformArithmeticSoftware(srcPixelArray.get(), dstPixelArray, m_k1, m_k2, m_k3, m_k4);
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resultImage)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContext* filterContext = resultImage->context();
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ImageBuffer* imageBuffer = in->asImageBuffer();
317926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ImageBuffer* imageBuffer2 = in2->asImageBuffer();
318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(imageBuffer);
319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(imageBuffer2);
320926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (m_type) {
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_OVER:
3235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
3245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()));
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_IN: {
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Applies only to the intersected region.
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        IntRect destinationRect = in->absolutePaintRect();
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationRect.intersect(in2->absolutePaintRect());
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destinationRect.intersect(absolutePaintRect());
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (destinationRect.isEmpty())
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
333f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        FloatRect sourceRect(IntPoint(destinationRect.x() - in->absolutePaintRect().x(),
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                    destinationRect.y() - in->absolutePaintRect().y()), destinationRect.size());
335f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        FloatRect source2Rect(IntPoint(destinationRect.x() - in2->absolutePaintRect().x(),
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                     destinationRect.y() - in2->absolutePaintRect().y()), destinationRect.size());
337197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        destinationRect.move(-absolutePaintRect().x(), -absolutePaintRect().y());
338197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        filterContext->drawImageBuffer(imageBuffer2, destinationRect, &source2Rect);
339197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        filterContext->drawImageBuffer(imageBuffer, destinationRect, &sourceRect, CompositeSourceIn);
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_OUT:
3435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()));
344f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()), 0, CompositeDestinationOut);
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_ATOP:
3475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
348f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeSourceAtop);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_XOR:
3515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
352f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeXOR);
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
359e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)SkXfermode::Mode toXfermode(CompositeOperationType mode)
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
36153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    switch (mode) {
362e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case FECOMPOSITE_OPERATOR_OVER:
36353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kSrcOver_Mode;
364e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case FECOMPOSITE_OPERATOR_IN:
36553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kSrcIn_Mode;
366e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case FECOMPOSITE_OPERATOR_OUT:
36753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kSrcOut_Mode;
368e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case FECOMPOSITE_OPERATOR_ATOP:
36953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kSrcATop_Mode;
370e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    case FECOMPOSITE_OPERATOR_XOR:
37153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kXor_Mode;
37253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    default:
37353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ASSERT_NOT_REACHED();
37453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return SkXfermode::kSrcOver_Mode;
37553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
37653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
37753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3783c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben MurdochPassRefPtr<SkImageFilter> FEComposite::createImageFilter(SkiaImageFilterBuilder* builder)
37953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
380a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return createImageFilterInternal(builder, true);
381a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
382a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
383a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPassRefPtr<SkImageFilter> FEComposite::createImageFilterWithoutValidation(SkiaImageFilterBuilder* builder)
384a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
385a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return createImageFilterInternal(builder, false);
386a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
387a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
388a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPassRefPtr<SkImageFilter> FEComposite::createImageFilterInternal(SkiaImageFilterBuilder* builder, bool requiresPMColorValidation)
389a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
390a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
391a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
3921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
39309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SkXfermode> mode;
39409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
395a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        mode = adoptRef(SkArithmeticMode::Create(SkFloatToScalar(m_k1), SkFloatToScalar(m_k2), SkFloatToScalar(m_k3), SkFloatToScalar(m_k4), requiresPMColorValidation));
39609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else
39709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        mode = adoptRef(SkXfermode::Create(toXfermode(m_type)));
39810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (type) {
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_UNKNOWN:
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "UNKNOWN";
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_OVER:
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "OVER";
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_IN:
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "IN";
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_OUT:
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "OUT";
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_ATOP:
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "ATOP";
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_XOR:
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "XOR";
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FECOMPOSITE_OPERATOR_ARITHMETIC:
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << "ARITHMETIC";
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "[feComposite";
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect::externalRepresentation(ts);
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " operation=\"" << m_type << "\"";
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\"";
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "]\n";
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inputEffect(0)->externalRepresentation(ts, indent + 1);
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inputEffect(1)->externalRepresentation(ts, indent + 1);
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
443c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
444