/* | |
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> | |
2004, 2005 Rob Buis <buis@kde.org> | |
2005 Eric Seidel <eric@webkit.org> | |
2009 Dirk Schulze <krit@webkit.org> | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Library General Public | |
License as published by the Free Software Foundation; either | |
version 2 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Library General Public License for more details. | |
You should have received a copy of the GNU Library General Public License | |
aint with this library; see the file COPYING.LIB. If not, write to | |
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
Boston, MA 02110-1301, USA. | |
*/ | |
#include "config.h" | |
#if ENABLE(FILTERS) | |
#include "FEComposite.h" | |
#include "CanvasPixelArray.h" | |
#include "Filter.h" | |
#include "GraphicsContext.h" | |
#include "ImageData.h" | |
namespace WebCore { | |
FEComposite::FEComposite(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type, | |
const float& k1, const float& k2, const float& k3, const float& k4) | |
: FilterEffect() | |
, m_in(in) | |
, m_in2(in2) | |
, m_type(type) | |
, m_k1(k1) | |
, m_k2(k2) | |
, m_k3(k3) | |
, m_k4(k4) | |
{ | |
} | |
PassRefPtr<FEComposite> FEComposite::create(FilterEffect* in, FilterEffect* in2, const CompositeOperationType& type, | |
const float& k1, const float& k2, const float& k3, const float& k4) | |
{ | |
return adoptRef(new FEComposite(in, in2, type, k1, k2, k3, k4)); | |
} | |
CompositeOperationType FEComposite::operation() const | |
{ | |
return m_type; | |
} | |
void FEComposite::setOperation(CompositeOperationType type) | |
{ | |
m_type = type; | |
} | |
float FEComposite::k1() const | |
{ | |
return m_k1; | |
} | |
void FEComposite::setK1(float k1) | |
{ | |
m_k1 = k1; | |
} | |
float FEComposite::k2() const | |
{ | |
return m_k2; | |
} | |
void FEComposite::setK2(float k2) | |
{ | |
m_k2 = k2; | |
} | |
float FEComposite::k3() const | |
{ | |
return m_k3; | |
} | |
void FEComposite::setK3(float k3) | |
{ | |
m_k3 = k3; | |
} | |
float FEComposite::k4() const | |
{ | |
return m_k4; | |
} | |
void FEComposite::setK4(float k4) | |
{ | |
m_k4 = k4; | |
} | |
inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPixelArray*& srcPixelArrayB, | |
float k1, float k2, float k3, float k4) | |
{ | |
float scaledK1 = k1 / 255.f; | |
float scaledK4 = k4 * 255.f; | |
for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) { | |
for (unsigned channel = 0; channel < 4; ++channel) { | |
unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel); | |
unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel); | |
double result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4; | |
srcPixelArrayB->set(pixelOffset + channel, result); | |
} | |
} | |
} | |
void FEComposite::apply(Filter* filter) | |
{ | |
m_in->apply(filter); | |
m_in2->apply(filter); | |
if (!m_in->resultImage() || !m_in2->resultImage()) | |
return; | |
GraphicsContext* filterContext = getEffectContext(); | |
if (!filterContext) | |
return; | |
FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f); | |
switch (m_type) { | |
case FECOMPOSITE_OPERATOR_OVER: | |
filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); | |
filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); | |
break; | |
case FECOMPOSITE_OPERATOR_IN: | |
filterContext->save(); | |
filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage()); | |
filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); | |
filterContext->restore(); | |
break; | |
case FECOMPOSITE_OPERATOR_OUT: | |
filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion())); | |
filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut); | |
break; | |
case FECOMPOSITE_OPERATOR_ATOP: | |
filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); | |
filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop); | |
break; | |
case FECOMPOSITE_OPERATOR_XOR: | |
filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion())); | |
filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR); | |
break; | |
case FECOMPOSITE_OPERATOR_ARITHMETIC: { | |
IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); | |
RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data()); | |
IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion()); | |
RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)); | |
CanvasPixelArray* srcPixelArrayB(imageData->data()); | |
arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4); | |
resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint()); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
void FEComposite::dump() | |
{ | |
} | |
} // namespace WebCore | |
#endif // ENABLE(FILTERS) |