OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2013 Google Inc. All rights reserved. | 3 * Copyright (C) 2013 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 20 matching lines...) Expand all Loading... | |
31 #include "core/svg/SVGLengthContext.h" | 31 #include "core/svg/SVGLengthContext.h" |
32 #include "core/svg/graphics/filters/SVGFilterBuilder.h" | 32 #include "core/svg/graphics/filters/SVGFilterBuilder.h" |
33 #include "platform/LengthFunctions.h" | 33 #include "platform/LengthFunctions.h" |
34 #include "platform/graphics/ColorSpace.h" | 34 #include "platform/graphics/ColorSpace.h" |
35 #include "platform/graphics/filters/FEBoxReflect.h" | 35 #include "platform/graphics/filters/FEBoxReflect.h" |
36 #include "platform/graphics/filters/FEColorMatrix.h" | 36 #include "platform/graphics/filters/FEColorMatrix.h" |
37 #include "platform/graphics/filters/FEComponentTransfer.h" | 37 #include "platform/graphics/filters/FEComponentTransfer.h" |
38 #include "platform/graphics/filters/FEDropShadow.h" | 38 #include "platform/graphics/filters/FEDropShadow.h" |
39 #include "platform/graphics/filters/FEGaussianBlur.h" | 39 #include "platform/graphics/filters/FEGaussianBlur.h" |
40 #include "platform/graphics/filters/Filter.h" | 40 #include "platform/graphics/filters/Filter.h" |
41 #include "platform/graphics/filters/FilterEffect.h" | |
41 #include "platform/graphics/filters/FilterOperations.h" | 42 #include "platform/graphics/filters/FilterOperations.h" |
42 #include "platform/graphics/filters/SourceGraphic.h" | 43 #include "platform/graphics/filters/SourceGraphic.h" |
43 #include "wtf/MathExtras.h" | 44 #include "wtf/MathExtras.h" |
44 #include <algorithm> | 45 #include <algorithm> |
45 | 46 |
46 namespace blink { | 47 namespace blink { |
47 | 48 |
48 namespace { | 49 namespace { |
49 | 50 |
50 inline void endMatrixRow(Vector<float>& matrix) | 51 inline void endMatrixRow(Vector<float>& matrix) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 matrix.uncheckedAppend(clampTo<float>(0.534 - 0.534 * oneMinusAmount)); | 114 matrix.uncheckedAppend(clampTo<float>(0.534 - 0.534 * oneMinusAmount)); |
114 matrix.uncheckedAppend(clampTo<float>(0.131 + 0.869 * oneMinusAmount)); | 115 matrix.uncheckedAppend(clampTo<float>(0.131 + 0.869 * oneMinusAmount)); |
115 endMatrixRow(matrix); | 116 endMatrixRow(matrix); |
116 | 117 |
117 lastMatrixRow(matrix); | 118 lastMatrixRow(matrix); |
118 return matrix; | 119 return matrix; |
119 } | 120 } |
120 | 121 |
121 } // namespace | 122 } // namespace |
122 | 123 |
123 FilterEffectBuilder::FilterEffectBuilder() | 124 FilterEffectBuilder::FilterEffectBuilder( |
125 Element* target, | |
126 const FloatRect& zoomedReferenceBox, float zoom, | |
127 const SkPaint* fillPaint, const SkPaint* strokePaint) | |
128 : m_targetContext(target) | |
129 , m_referenceBox(zoomedReferenceBox) | |
130 , m_zoom(zoom) | |
131 , m_fillPaint(fillPaint) | |
132 , m_strokePaint(strokePaint) | |
124 { | 133 { |
134 if (m_zoom != 1) | |
135 m_referenceBox.scale(1 / m_zoom); | |
125 } | 136 } |
126 | 137 |
127 FilterEffectBuilder::~FilterEffectBuilder() | 138 FilterEffect* FilterEffectBuilder::buildFilterEffect(const FilterOperations& ope rations) const |
128 { | |
129 } | |
130 | |
131 DEFINE_TRACE(FilterEffectBuilder) | |
132 { | |
133 visitor->trace(m_lastEffect); | |
134 } | |
135 | |
136 bool FilterEffectBuilder::build(Element* element, const FilterOperations& operat ions, float zoom, const FloatRect& zoomedReferenceBox, const SkPaint* fillPaint, const SkPaint* strokePaint) | |
137 { | 139 { |
138 // 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. | 140 // 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. |
139 Filter* parentFilter = Filter::create(1.0f); | 141 Filter* parentFilter = Filter::create(1.0f); |
140 FilterEffect* previousEffect = parentFilter->getSourceGraphic(); | 142 FilterEffect* previousEffect = parentFilter->getSourceGraphic(); |
141 for (size_t i = 0; i < operations.operations().size(); ++i) { | 143 for (size_t i = 0; i < operations.operations().size(); ++i) { |
142 FilterEffect* effect = nullptr; | 144 FilterEffect* effect = nullptr; |
143 FilterOperation* filterOperation = operations.operations().at(i).get(); | 145 FilterOperation* filterOperation = operations.operations().at(i).get(); |
144 switch (filterOperation->type()) { | 146 switch (filterOperation->type()) { |
145 case FilterOperation::REFERENCE: { | 147 case FilterOperation::REFERENCE: { |
146 Filter* referenceFilter = buildReferenceFilter(toReferenceFilterOper ation(*filterOperation), zoomedReferenceBox, fillPaint, strokePaint, *element, p reviousEffect, zoom); | 148 Filter* referenceFilter = buildReferenceFilter(toReferenceFilterOper ation(*filterOperation), previousEffect); |
147 if (referenceFilter) | 149 if (referenceFilter) |
148 effect = referenceFilter->lastEffect(); | 150 effect = referenceFilter->lastEffect(); |
149 break; | 151 break; |
150 } | 152 } |
151 case FilterOperation::GRAYSCALE: { | 153 case FilterOperation::GRAYSCALE: { |
152 Vector<float> inputParameters = grayscaleMatrix(toBasicColorMatrixFi lterOperation(filterOperation)->amount()); | 154 Vector<float> inputParameters = grayscaleMatrix(toBasicColorMatrixFi lterOperation(filterOperation)->amount()); |
153 effect = FEColorMatrix::create(parentFilter, FECOLORMATRIX_TYPE_MATR IX, inputParameters); | 155 effect = FEColorMatrix::create(parentFilter, FECOLORMATRIX_TYPE_MATR IX, inputParameters); |
154 break; | 156 break; |
155 } | 157 } |
156 case FilterOperation::SEPIA: { | 158 case FilterOperation::SEPIA: { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 // Unlike SVG, filters applied here should not clip to their pri mitive subregions. | 245 // Unlike SVG, filters applied here should not clip to their pri mitive subregions. |
244 effect->setClipsToBounds(false); | 246 effect->setClipsToBounds(false); |
245 effect->setOperatingColorSpace(ColorSpaceDeviceRGB); | 247 effect->setOperatingColorSpace(ColorSpaceDeviceRGB); |
246 effect->inputEffects().append(previousEffect); | 248 effect->inputEffects().append(previousEffect); |
247 } | 249 } |
248 if (previousEffect->originTainted()) | 250 if (previousEffect->originTainted()) |
249 effect->setOriginTainted(); | 251 effect->setOriginTainted(); |
250 previousEffect = effect; | 252 previousEffect = effect; |
251 } | 253 } |
252 } | 254 } |
253 | 255 return previousEffect; |
254 // We need to keep the old effects alive until this point, so that SVG refer ence filters | |
255 // can share cached resources across frames. | |
256 m_lastEffect = previousEffect; | |
257 | |
258 // If we didn't make any effects, tell our caller we are not valid | |
259 if (!m_lastEffect.get()) | |
260 return false; | |
261 | |
262 return true; | |
263 } | 256 } |
264 | 257 |
265 Filter* FilterEffectBuilder::buildReferenceFilter( | 258 Filter* FilterEffectBuilder::buildReferenceFilter( |
Stephen White
2016/09/19 14:59:36
I wonder if we should now just have two constructo
fs
2016/09/20 08:17:28
My plan is one constructor and one buildReferenceF
| |
266 const ReferenceFilterOperation& referenceOperation, | 259 const ReferenceFilterOperation& referenceOperation, |
267 const FloatRect& zoomedReferenceBox, | 260 FilterEffect* previousEffect) const |
268 const SkPaint* fillPaint, | |
269 const SkPaint* strokePaint, | |
270 Element& element, | |
271 FilterEffect* previousEffect, | |
272 float zoom) | |
273 { | 261 { |
274 SVGFilterElement* filterElement = ReferenceFilterBuilder::resolveFilterRefer ence(referenceOperation, element); | 262 DCHECK(m_targetContext); |
263 SVGFilterElement* filterElement = ReferenceFilterBuilder::resolveFilterRefer ence(referenceOperation, *m_targetContext); | |
275 if (!filterElement) | 264 if (!filterElement) |
276 return nullptr; | 265 return nullptr; |
277 FloatRect referenceBox = zoomedReferenceBox; | 266 return buildReferenceFilter(*filterElement, previousEffect); |
278 referenceBox.scale(1.0f / zoom); | |
279 return buildReferenceFilter(*filterElement, referenceBox, fillPaint, strokeP aint, previousEffect, zoom); | |
280 } | 267 } |
281 | 268 |
282 Filter* FilterEffectBuilder::buildReferenceFilter( | 269 Filter* FilterEffectBuilder::buildReferenceFilter( |
283 SVGFilterElement& filterElement, | 270 SVGFilterElement& filterElement, |
284 const FloatRect& referenceBox, | |
285 const SkPaint* fillPaint, | |
286 const SkPaint* strokePaint, | |
287 FilterEffect* previousEffect, | 271 FilterEffect* previousEffect, |
288 float zoom, | 272 SVGFilterGraphNodeMap* nodeMap) const |
289 SVGFilterGraphNodeMap* nodeMap) | |
290 { | 273 { |
291 FloatRect filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement >(&filterElement, filterElement.filterUnits()->currentValue()->enumValue(), refe renceBox); | 274 FloatRect filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement >(&filterElement, filterElement.filterUnits()->currentValue()->enumValue(), m_re ferenceBox); |
292 // TODO(fs): We rely on the presence of a node map here to opt-in to the | 275 // TODO(fs): We rely on the presence of a node map here to opt-in to the |
293 // check for an empty filter region. The reason for this is that we lack a | 276 // check for an empty filter region. The reason for this is that we lack a |
294 // viewport to resolve against for HTML content. This is crbug.com/512453. | 277 // viewport to resolve against for HTML content. This is crbug.com/512453. |
295 if (nodeMap && filterRegion.isEmpty()) | 278 if (nodeMap && filterRegion.isEmpty()) |
296 return nullptr; | 279 return nullptr; |
297 | 280 |
298 bool primitiveBoundingBoxMode = filterElement.primitiveUnits()->currentValue ()->enumValue() == SVGUnitTypes::kSvgUnitTypeObjectboundingbox; | 281 bool primitiveBoundingBoxMode = filterElement.primitiveUnits()->currentValue ()->enumValue() == SVGUnitTypes::kSvgUnitTypeObjectboundingbox; |
299 Filter::UnitScaling unitScaling = primitiveBoundingBoxMode ? Filter::Boundin gBox : Filter::UserSpace; | 282 Filter::UnitScaling unitScaling = primitiveBoundingBoxMode ? Filter::Boundin gBox : Filter::UserSpace; |
300 Filter* result = Filter::create(referenceBox, filterRegion, zoom, unitScalin g); | 283 Filter* result = Filter::create(m_referenceBox, filterRegion, m_zoom, unitSc aling); |
301 if (!previousEffect) | 284 if (!previousEffect) |
302 previousEffect = result->getSourceGraphic(); | 285 previousEffect = result->getSourceGraphic(); |
303 SVGFilterBuilder builder(previousEffect, nodeMap, fillPaint, strokePaint); | 286 SVGFilterBuilder builder(previousEffect, nodeMap, m_fillPaint, m_strokePaint ); |
304 builder.buildGraph(result, filterElement, referenceBox); | 287 builder.buildGraph(result, filterElement, m_referenceBox); |
305 result->setLastEffect(builder.lastEffect()); | 288 result->setLastEffect(builder.lastEffect()); |
306 return result; | 289 return result; |
307 } | 290 } |
308 | 291 |
309 } // namespace blink | 292 } // namespace blink |
310 | 293 |
OLD | NEW |