Home | History | Annotate | Download | only in filters
      1 /*
      2     Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      3                   2004, 2005 Rob Buis <buis (at) kde.org>
      4                   2005 Eric Seidel <eric (at) webkit.org>
      5                   2009 Dirk Schulze <krit (at) webkit.org>
      6 
      7     This library is free software; you can redistribute it and/or
      8     modify it under the terms of the GNU Library General Public
      9     License as published by the Free Software Foundation; either
     10     version 2 of the License, or (at your option) any later version.
     11 
     12     This library is distributed in the hope that it will be useful,
     13     but WITHOUT ANY WARRANTY; without even the implied warranty of
     14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15     Library General Public License for more details.
     16 
     17     You should have received a copy of the GNU Library General Public License
     18     aint with this library; see the file COPYING.LIB.  If not, write to
     19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20     Boston, MA 02110-1301, USA.
     21 */
     22 
     23 #include "config.h"
     24 
     25 #if ENABLE(FILTERS)
     26 #include "FEComposite.h"
     27 
     28 #include "CanvasPixelArray.h"
     29 #include "Filter.h"
     30 #include "GraphicsContext.h"
     31 #include "ImageData.h"
     32 
     33 namespace WebCore {
     34 
     35 FEComposite::FEComposite(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type,
     36     const float& k1, const float& k2, const float& k3, const float& k4)
     37     : FilterEffect()
     38     , m_in(in)
     39     , m_in2(in2)
     40     , m_type(type)
     41     , m_k1(k1)
     42     , m_k2(k2)
     43     , m_k3(k3)
     44     , m_k4(k4)
     45 {
     46 }
     47 
     48 PassRefPtr<FEComposite> FEComposite::create(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type,
     49     const float& k1, const float& k2, const float& k3, const float& k4)
     50 {
     51     return adoptRef(new FEComposite(in, in2, type, k1, k2, k3, k4));
     52 }
     53 
     54 CompositeOperationType FEComposite::operation() const
     55 {
     56     return m_type;
     57 }
     58 
     59 void FEComposite::setOperation(CompositeOperationType type)
     60 {
     61     m_type = type;
     62 }
     63 
     64 float FEComposite::k1() const
     65 {
     66     return m_k1;
     67 }
     68 
     69 void FEComposite::setK1(float k1)
     70 {
     71     m_k1 = k1;
     72 }
     73 
     74 float FEComposite::k2() const
     75 {
     76     return m_k2;
     77 }
     78 
     79 void FEComposite::setK2(float k2)
     80 {
     81     m_k2 = k2;
     82 }
     83 
     84 float FEComposite::k3() const
     85 {
     86     return m_k3;
     87 }
     88 
     89 void FEComposite::setK3(float k3)
     90 {
     91     m_k3 = k3;
     92 }
     93 
     94 float FEComposite::k4() const
     95 {
     96     return m_k4;
     97 }
     98 
     99 void FEComposite::setK4(float k4)
    100 {
    101     m_k4 = k4;
    102 }
    103 
    104 inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPixelArray*& srcPixelArrayB,
    105                        float k1, float k2, float k3, float k4)
    106 {
    107     float scaledK1 = k1 / 255.f;
    108     float scaledK4 = k4 * 255.f;
    109     for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
    110         for (unsigned channel = 0; channel < 4; ++channel) {
    111             unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
    112             unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
    113 
    114             double result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
    115             srcPixelArrayB->set(pixelOffset + channel, result);
    116         }
    117     }
    118 }
    119 
    120 void FEComposite::apply(Filter* filter)
    121 {
    122     m_in->apply(filter);
    123     m_in2->apply(filter);
    124     if (!m_in->resultImage() || !m_in2->resultImage())
    125         return;
    126 
    127     GraphicsContext* filterContext = getEffectContext();
    128     if (!filterContext)
    129         return;
    130 
    131     FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f);
    132     switch (m_type) {
    133     case FECOMPOSITE_OPERATOR_OVER:
    134         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    135         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    136         break;
    137     case FECOMPOSITE_OPERATOR_IN:
    138         filterContext->save();
    139         filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
    140         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    141         filterContext->restore();
    142         break;
    143     case FECOMPOSITE_OPERATOR_OUT:
    144         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    145         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
    146         break;
    147     case FECOMPOSITE_OPERATOR_ATOP:
    148         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    149         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
    150         break;
    151     case FECOMPOSITE_OPERATOR_XOR:
    152         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    153         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
    154         break;
    155     case FECOMPOSITE_OPERATOR_ARITHMETIC: {
    156         IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    157         RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
    158 
    159         IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
    160         RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
    161         CanvasPixelArray* srcPixelArrayB(imageData->data());
    162 
    163         arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
    164         resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
    165         }
    166         break;
    167     default:
    168         break;
    169     }
    170 }
    171 
    172 void FEComposite::dump()
    173 {
    174 }
    175 
    176 } // namespace WebCore
    177 
    178 #endif // ENABLE(FILTERS)
    179