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