Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org>
      5  * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org>
      6  * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
      7  * Copyright (C) 2013 Google Inc. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #include "config.h"
     26 #include "platform/graphics/filters/FEBlend.h"
     27 
     28 #include "SkBitmapSource.h"
     29 #include "SkXfermodeImageFilter.h"
     30 #include "platform/graphics/GraphicsContext.h"
     31 #include "platform/graphics/cpu/arm/filters/FEBlendNEON.h"
     32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
     33 #include "platform/graphics/skia/NativeImageSkia.h"
     34 #include "platform/graphics/skia/SkiaUtils.h"
     35 #include "platform/text/TextStream.h"
     36 #include "wtf/Uint8ClampedArray.h"
     37 
     38 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
     39 
     40 namespace blink {
     41 
     42 FEBlend::FEBlend(Filter* filter, WebBlendMode mode)
     43     : FilterEffect(filter)
     44     , m_mode(mode)
     45 {
     46 }
     47 
     48 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, WebBlendMode mode)
     49 {
     50     return adoptRef(new FEBlend(filter, mode));
     51 }
     52 
     53 WebBlendMode FEBlend::blendMode() const
     54 {
     55     return m_mode;
     56 }
     57 
     58 bool FEBlend::setBlendMode(WebBlendMode mode)
     59 {
     60     if (m_mode == mode)
     61         return false;
     62     m_mode = mode;
     63     return true;
     64 }
     65 
     66 #if HAVE(ARM_NEON_INTRINSICS)
     67 bool FEBlend::applySoftwareNEON()
     68 {
     69     if (m_mode != WebBlendModeNormal
     70         && m_mode != WebBlendModeMultiply
     71         && m_mode != WebBlendModeScreen
     72         && m_mode != WebBlendModeDarken
     73         && m_mode != WebBlendModeLighten)
     74         return false;
     75 
     76     Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
     77     if (!dstPixelArray)
     78         return true;
     79 
     80     FilterEffect* in = inputEffect(0);
     81     FilterEffect* in2 = inputEffect(1);
     82 
     83     IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     84     RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
     85 
     86     IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
     87     RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
     88 
     89     unsigned pixelArrayLength = srcPixelArrayA->length();
     90     ASSERT(pixelArrayLength == srcPixelArrayB->length());
     91 
     92     if (pixelArrayLength >= 8) {
     93         platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
     94     } else {
     95         // If there is just one pixel we expand it to two.
     96         ASSERT(pixelArrayLength > 0);
     97         uint32_t sourceA[2] = {0, 0};
     98         uint32_t sourceBAndDest[2] = {0, 0};
     99 
    100         sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
    101         sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0];
    102         platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
    103         reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0];
    104     }
    105     return true;
    106 }
    107 #endif
    108 
    109 void FEBlend::applySoftware()
    110 {
    111 #if HAVE(ARM_NEON_INTRINSICS)
    112     if (applySoftwareNEON())
    113         return;
    114 #endif
    115 
    116     FilterEffect* in = inputEffect(0);
    117     FilterEffect* in2 = inputEffect(1);
    118 
    119     ImageBuffer* resultImage = createImageBufferResult();
    120     if (!resultImage)
    121         return;
    122     GraphicsContext* filterContext = resultImage->context();
    123 
    124     ImageBuffer* imageBuffer = in->asImageBuffer();
    125     ImageBuffer* imageBuffer2 = in2->asImageBuffer();
    126     ASSERT(imageBuffer);
    127     ASSERT(imageBuffer2);
    128 
    129     filterContext->drawImageBuffer(imageBuffer2, drawingRegionOfInputImage(in2->absolutePaintRect()));
    130     filterContext->drawImageBuffer(imageBuffer, drawingRegionOfInputImage(in->absolutePaintRect()), 0, CompositeSourceOver, m_mode);
    131 }
    132 
    133 PassRefPtr<SkImageFilter> FEBlend::createImageFilter(SkiaImageFilterBuilder* builder)
    134 {
    135     RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace()));
    136     RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace()));
    137     RefPtr<SkXfermode> mode(adoptRef(SkXfermode::Create(WebCoreCompositeToSkiaComposite(CompositeSourceOver, m_mode))));
    138     SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
    139     return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
    140 }
    141 
    142 TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const
    143 {
    144     writeIndent(ts, indent);
    145     ts << "[feBlend";
    146     FilterEffect::externalRepresentation(ts);
    147     ts << " mode=\"" << (m_mode == WebBlendModeNormal ? "normal" : compositeOperatorName(CompositeSourceOver, m_mode)) << "\"]\n";
    148     inputEffect(0)->externalRepresentation(ts, indent + 1);
    149     inputEffect(1)->externalRepresentation(ts, indent + 1);
    150     return ts;
    151 }
    152 
    153 } // namespace blink
    154