OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | |
3 * Copyright (C) 2013 Google Inc. All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 */ | |
26 | |
27 #include "config.h" | |
28 | |
29 #include "core/layout/FilterEffectRenderer.h" | |
30 | |
31 #include "core/fetch/DocumentResource.h" | |
32 #include "core/fetch/DocumentResourceReference.h" | |
33 #include "core/frame/Settings.h" | |
34 #include "core/layout/LayoutObject.h" | |
35 #include "core/layout/svg/ReferenceFilterBuilder.h" | |
36 #include "core/page/Page.h" | |
37 #include "core/svg/SVGElement.h" | |
38 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" | |
39 #include "platform/FloatConversion.h" | |
40 #include "platform/LengthFunctions.h" | |
41 #include "platform/graphics/ColorSpace.h" | |
42 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | |
43 #include "platform/graphics/filters/FEColorMatrix.h" | |
44 #include "platform/graphics/filters/FEComponentTransfer.h" | |
45 #include "platform/graphics/filters/FEDropShadow.h" | |
46 #include "platform/graphics/filters/FEGaussianBlur.h" | |
47 #include "platform/graphics/filters/SourceGraphic.h" | |
48 #include "wtf/MathExtras.h" | |
49 #include <algorithm> | |
50 | |
51 namespace blink { | |
52 | |
53 static inline void endMatrixRow(Vector<float>& parameters) | |
54 { | |
55 parameters.append(0); | |
56 parameters.append(0); | |
57 } | |
58 | |
59 static inline void lastMatrixRow(Vector<float>& parameters) | |
60 { | |
61 parameters.append(0); | |
62 parameters.append(0); | |
63 parameters.append(0); | |
64 parameters.append(1); | |
65 parameters.append(0); | |
66 } | |
67 | |
68 FilterEffectRenderer::FilterEffectRenderer() | |
69 { | |
70 } | |
71 | |
72 FilterEffectRenderer::~FilterEffectRenderer() | |
73 { | |
74 } | |
75 | |
76 DEFINE_TRACE(FilterEffectRenderer) | |
77 { | |
78 visitor->trace(m_lastEffect); | |
79 visitor->trace(m_referenceFilters); | |
80 } | |
81 | |
82 bool FilterEffectRenderer::build(LayoutObject* renderer, const FilterOperations&
operations) | |
83 { | |
84 const ComputedStyle* style = renderer->style(); | |
85 float zoom = style ? style->effectiveZoom() : 1.0f; | |
86 | |
87 // Create a parent filter for shorthand filters. These have already been sca
led by the CSS code for page zoom, so scale is 1.0 here. | |
88 RefPtrWillBeRawPtr<ReferenceFilter> parentFilter = ReferenceFilter::create(1
.0f); | |
89 RefPtrWillBeRawPtr<FilterEffect> previousEffect = SourceGraphic::create(pare
ntFilter.get()); | |
90 for (size_t i = 0; i < operations.operations().size(); ++i) { | |
91 RefPtrWillBeRawPtr<FilterEffect> effect = nullptr; | |
92 FilterOperation* filterOperation = operations.operations().at(i).get(); | |
93 switch (filterOperation->type()) { | |
94 case FilterOperation::REFERENCE: { | |
95 RefPtrWillBeRawPtr<ReferenceFilter> referenceFilter = ReferenceFilte
r::create(zoom); | |
96 effect = ReferenceFilterBuilder::build(referenceFilter.get(), render
er, previousEffect.get(), toReferenceFilterOperation(filterOperation)); | |
97 referenceFilter->setLastEffect(effect); | |
98 m_referenceFilters.append(referenceFilter); | |
99 break; | |
100 } | |
101 case FilterOperation::GRAYSCALE: { | |
102 Vector<float> inputParameters; | |
103 double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperatio
n(filterOperation)->amount(), 0.0, 1.0); | |
104 | |
105 // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#g
rayscaleEquivalent | |
106 // for information on parameters. | |
107 | |
108 inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneM
inusAmount)); | |
109 inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneM
inusAmount)); | |
110 inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneM
inusAmount)); | |
111 endMatrixRow(inputParameters); | |
112 | |
113 inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneM
inusAmount)); | |
114 inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneM
inusAmount)); | |
115 inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneM
inusAmount)); | |
116 endMatrixRow(inputParameters); | |
117 | |
118 inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneM
inusAmount)); | |
119 inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneM
inusAmount)); | |
120 inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneM
inusAmount)); | |
121 endMatrixRow(inputParameters); | |
122 | |
123 lastMatrixRow(inputParameters); | |
124 | |
125 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_MATRIX, inputParameters); | |
126 break; | |
127 } | |
128 case FilterOperation::SEPIA: { | |
129 Vector<float> inputParameters; | |
130 double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperatio
n(filterOperation)->amount(), 0.0, 1.0); | |
131 | |
132 // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#s
epiaEquivalent | |
133 // for information on parameters. | |
134 | |
135 inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMin
usAmount)); | |
136 inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMin
usAmount)); | |
137 inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMin
usAmount)); | |
138 endMatrixRow(inputParameters); | |
139 | |
140 inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMin
usAmount)); | |
141 inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMin
usAmount)); | |
142 inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMin
usAmount)); | |
143 endMatrixRow(inputParameters); | |
144 | |
145 inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMin
usAmount)); | |
146 inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMin
usAmount)); | |
147 inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMin
usAmount)); | |
148 endMatrixRow(inputParameters); | |
149 | |
150 lastMatrixRow(inputParameters); | |
151 | |
152 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_MATRIX, inputParameters); | |
153 break; | |
154 } | |
155 case FilterOperation::SATURATE: { | |
156 Vector<float> inputParameters; | |
157 inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilt
erOperation(filterOperation)->amount())); | |
158 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_SATURATE, inputParameters); | |
159 break; | |
160 } | |
161 case FilterOperation::HUE_ROTATE: { | |
162 Vector<float> inputParameters; | |
163 inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilt
erOperation(filterOperation)->amount())); | |
164 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_HUEROTATE, inputParameters); | |
165 break; | |
166 } | |
167 case FilterOperation::INVERT: { | |
168 BasicComponentTransferFilterOperation* componentTransferOperation =
toBasicComponentTransferFilterOperation(filterOperation); | |
169 ComponentTransferFunction transferFunction; | |
170 transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; | |
171 Vector<float> transferParameters; | |
172 transferParameters.append(narrowPrecisionToFloat(componentTransferOp
eration->amount())); | |
173 transferParameters.append(narrowPrecisionToFloat(1 - componentTransf
erOperation->amount())); | |
174 transferFunction.tableValues = transferParameters; | |
175 | |
176 ComponentTransferFunction nullFunction; | |
177 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
178 break; | |
179 } | |
180 case FilterOperation::OPACITY: { | |
181 ComponentTransferFunction transferFunction; | |
182 transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; | |
183 Vector<float> transferParameters; | |
184 transferParameters.append(0); | |
185 transferParameters.append(narrowPrecisionToFloat(toBasicComponentTra
nsferFilterOperation(filterOperation)->amount())); | |
186 transferFunction.tableValues = transferParameters; | |
187 | |
188 ComponentTransferFunction nullFunction; | |
189 effect = FEComponentTransfer::create(parentFilter.get(), nullFunctio
n, nullFunction, nullFunction, transferFunction); | |
190 break; | |
191 } | |
192 case FilterOperation::BRIGHTNESS: { | |
193 ComponentTransferFunction transferFunction; | |
194 transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; | |
195 transferFunction.slope = narrowPrecisionToFloat(toBasicComponentTran
sferFilterOperation(filterOperation)->amount()); | |
196 transferFunction.intercept = 0; | |
197 | |
198 ComponentTransferFunction nullFunction; | |
199 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
200 break; | |
201 } | |
202 case FilterOperation::CONTRAST: { | |
203 ComponentTransferFunction transferFunction; | |
204 transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; | |
205 float amount = narrowPrecisionToFloat(toBasicComponentTransferFilter
Operation(filterOperation)->amount()); | |
206 transferFunction.slope = amount; | |
207 transferFunction.intercept = -0.5 * amount + 0.5; | |
208 | |
209 ComponentTransferFunction nullFunction; | |
210 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
211 break; | |
212 } | |
213 case FilterOperation::BLUR: { | |
214 float stdDeviation = floatValueForLength(toBlurFilterOperation(filte
rOperation)->stdDeviation(), 0); | |
215 effect = FEGaussianBlur::create(parentFilter.get(), stdDeviation, st
dDeviation); | |
216 break; | |
217 } | |
218 case FilterOperation::DROP_SHADOW: { | |
219 DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterO
peration(filterOperation); | |
220 float stdDeviation = dropShadowOperation->stdDeviation(); | |
221 float x = dropShadowOperation->x(); | |
222 float y = dropShadowOperation->y(); | |
223 effect = FEDropShadow::create(parentFilter.get(), stdDeviation, stdD
eviation, x, y, dropShadowOperation->color(), 1); | |
224 break; | |
225 } | |
226 default: | |
227 break; | |
228 } | |
229 | |
230 if (effect) { | |
231 if (filterOperation->type() != FilterOperation::REFERENCE) { | |
232 // Unlike SVG, filters applied here should not clip to their pri
mitive subregions. | |
233 effect->setClipsToBounds(false); | |
234 effect->setOperatingColorSpace(ColorSpaceDeviceRGB); | |
235 effect->inputEffects().append(previousEffect); | |
236 } | |
237 previousEffect = effect.release(); | |
238 } | |
239 } | |
240 | |
241 m_referenceFilters.append(parentFilter); | |
242 | |
243 // We need to keep the old effects alive until this point, so that SVG refer
ence filters | |
244 // can share cached resources across frames. | |
245 m_lastEffect = previousEffect; | |
246 | |
247 // If we didn't make any effects, tell our caller we are not valid | |
248 if (!m_lastEffect.get()) | |
249 return false; | |
250 | |
251 return true; | |
252 } | |
253 | |
254 void FilterEffectRenderer::clearIntermediateResults() | |
255 { | |
256 if (m_lastEffect.get()) | |
257 m_lastEffect->clearResultsRecursive(); | |
258 } | |
259 | |
260 | |
261 } // namespace blink | |
262 | |
OLD | NEW |