• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2009 Dirk Schulze <krit@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 
FEBlend(Filter * filter,WebBlendMode mode)42 FEBlend::FEBlend(Filter* filter, WebBlendMode mode)
43     : FilterEffect(filter)
44     , m_mode(mode)
45 {
46 }
47 
create(Filter * filter,WebBlendMode mode)48 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, WebBlendMode mode)
49 {
50     return adoptRef(new FEBlend(filter, mode));
51 }
52 
blendMode() const53 WebBlendMode FEBlend::blendMode() const
54 {
55     return m_mode;
56 }
57 
setBlendMode(WebBlendMode mode)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)
applySoftwareNEON()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 
applySoftware()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 
createImageFilter(SkiaImageFilterBuilder * builder)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 
externalRepresentation(TextStream & ts,int indent) const142 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