Filters need to affect visual overflow
[WebKit-https.git] / Source / WebCore / rendering / FilterEffectRenderer.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(CSS_FILTERS)
29
30 #include "FilterEffectRenderer.h"
31
32 #include "FEColorMatrix.h"
33 #include "FEComponentTransfer.h"
34 #include "FEDropShadow.h"
35 #include "FEGaussianBlur.h"
36 #include "FEMerge.h"
37 #include "FloatConversion.h"
38
39 #include <algorithm>
40 #include <wtf/MathExtras.h>
41
42 namespace WebCore {
43
44 static inline void endMatrixRow(Vector<float>& parameters)
45 {
46     parameters.append(0);
47     parameters.append(0);
48 }
49
50 static inline void lastMatrixRow(Vector<float>& parameters)
51 {
52     parameters.append(0);
53     parameters.append(0);
54     parameters.append(0);
55     parameters.append(1);
56     parameters.append(0);
57 }
58
59 FilterEffectRenderer::FilterEffectRenderer()
60     : m_graphicsBufferAttached(false)
61 {
62     setFilterResolution(FloatSize(1, 1));
63     m_sourceGraphic = SourceGraphic::create(this);
64 }
65
66 FilterEffectRenderer::~FilterEffectRenderer()
67 {
68 }
69
70 GraphicsContext* FilterEffectRenderer::inputContext()
71 {
72     return sourceImage()->context();
73 }
74
75 void FilterEffectRenderer::build(const FilterOperations& operations, const LayoutRect& borderBox)
76 {
77     m_effects.clear();
78
79     RefPtr<FilterEffect> effect;
80     RefPtr<FilterEffect> previousEffect;
81     for (size_t i = 0; i < operations.operations().size(); ++i) {
82         FilterOperation* filterOperation = operations.operations().at(i).get();
83         switch (filterOperation->getOperationType()) {
84         case FilterOperation::REFERENCE: {
85             // FIXME: Not yet implemented.
86             // https://bugs.webkit.org/show_bug.cgi?id=72443
87             break;
88         }
89         case FilterOperation::GRAYSCALE: {
90             BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
91             Vector<float> inputParameters;
92             double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0);
93
94             // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
95             // for information on parameters.
96
97             inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount));
98             inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount));
99             inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount));
100             endMatrixRow(inputParameters);
101
102             inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount));
103             inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount));
104             inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount));
105             endMatrixRow(inputParameters);
106
107             inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount));
108             inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount));
109             inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount));
110             endMatrixRow(inputParameters);
111
112             lastMatrixRow(inputParameters);
113
114             effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
115             break;
116         }
117         case FilterOperation::SEPIA: {
118             BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
119             Vector<float> inputParameters;
120             double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0);
121
122             // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
123             // for information on parameters.
124
125             inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount));
126             inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount));
127             inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount));
128             endMatrixRow(inputParameters);
129
130             inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount));
131             inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount));
132             inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount));
133             endMatrixRow(inputParameters);
134
135             inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount));
136             inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount));
137             inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount));
138             endMatrixRow(inputParameters);
139
140             lastMatrixRow(inputParameters);
141
142             effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
143             break;
144         }
145         case FilterOperation::SATURATE: {
146             BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
147             Vector<float> inputParameters;
148             inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
149             effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters);
150             break;
151         }
152         case FilterOperation::HUE_ROTATE: {
153             BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
154             Vector<float> inputParameters;
155             inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
156             effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters);
157             break;
158         }
159         case FilterOperation::INVERT: {
160             BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
161             ComponentTransferFunction transferFunction;
162             transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
163             Vector<float> transferParameters;
164             transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
165             transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount()));
166             transferFunction.tableValues = transferParameters;
167
168             ComponentTransferFunction nullFunction;
169             effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
170             break;
171         }
172         case FilterOperation::OPACITY: {
173             BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
174             ComponentTransferFunction transferFunction;
175             transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
176             Vector<float> transferParameters;
177             transferParameters.append(0);
178             transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
179             transferFunction.tableValues = transferParameters;
180
181             ComponentTransferFunction nullFunction;
182             effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction);
183             break;
184         }
185         case FilterOperation::GAMMA: {
186             GammaFilterOperation* gammaOperation = static_cast<GammaFilterOperation*>(filterOperation);
187             ComponentTransferFunction transferFunction;
188             transferFunction.type = FECOMPONENTTRANSFER_TYPE_GAMMA;
189             transferFunction.amplitude = narrowPrecisionToFloat(gammaOperation->amplitude());
190             transferFunction.exponent = narrowPrecisionToFloat(gammaOperation->exponent());
191             transferFunction.offset = narrowPrecisionToFloat(gammaOperation->offset());
192
193             ComponentTransferFunction nullFunction;
194             effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
195             break;
196         }
197         case FilterOperation::BLUR: {
198             BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
199             float stdDeviationX = blurOperation->stdDeviationX().calcFloatValue(borderBox.width());
200             float stdDeviationY = blurOperation->stdDeviationY().calcFloatValue(borderBox.height());
201             effect = FEGaussianBlur::create(this, stdDeviationX, stdDeviationY);
202             break;
203         }
204         case FilterOperation::SHARPEN: {
205             // FIXME: Currently unimplemented.
206             // https://bugs.webkit.org/show_bug.cgi?id=72442
207             break;
208         }
209         case FilterOperation::DROP_SHADOW: {
210             DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
211             effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(),
212                                                 dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1);
213             break;
214         }
215 #if ENABLE(CSS_SHADERS)
216         case FilterOperation::CUSTOM: {
217             // Not implemented in the software path.
218             break;
219         }
220 #endif
221         default:
222             break;
223         }
224
225         if (effect) {
226             // Unlike SVG, filters applied here should not clip to their primitive subregions.
227             effect->setClipsToBounds(false);
228             
229             if (previousEffect)
230                 effect->inputEffects().append(previousEffect);
231             m_effects.append(effect);
232             previousEffect = effect;
233         }
234     }
235
236     // If we didn't make a real filter, create a null-op (FEMerge with one input).
237     if (!effect)
238         m_effects.append(FEMerge::create(this));
239
240     m_effects.first()->inputEffects().append(m_sourceGraphic);
241     setMaxEffectRects(m_sourceDrawingRegion);
242 }
243
244 void FilterEffectRenderer::prepare()
245 {
246     // At this point the effect chain has been built, and the
247     // source image sizes set. We just need to attach the graphic
248     // buffer if we have not yet done so.
249     if (!m_graphicsBufferAttached) {
250         setSourceImage(ImageBuffer::create(IntSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height()), ColorSpaceDeviceRGB, renderingMode()));
251         m_graphicsBufferAttached = true;
252     }
253     m_sourceGraphic->clearResult();
254     lastEffect()->clearResult();
255 }
256
257 void FilterEffectRenderer::apply()
258 {
259     lastEffect()->apply();
260 }
261
262 } // namespace WebCore
263
264 #endif // ENABLE(CSS_FILTERS)