Index: third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp |
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp |
index 73ccf1576962a10dc17972e6ef72f2d4b301752d..11c6b5755893a7a9a95294ac19d49249887e5bb3 100644 |
--- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp |
+++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp |
@@ -32,6 +32,7 @@ |
#include "core/svg/graphics/filters/SVGFilterBuilder.h" |
#include "platform/LengthFunctions.h" |
#include "platform/graphics/ColorSpace.h" |
+#include "platform/graphics/CompositorFilterOperations.h" |
#include "platform/graphics/filters/FEBoxReflect.h" |
#include "platform/graphics/filters/FEColorMatrix.h" |
#include "platform/graphics/filters/FEComponentTransfer.h" |
@@ -40,7 +41,9 @@ |
#include "platform/graphics/filters/Filter.h" |
#include "platform/graphics/filters/FilterEffect.h" |
#include "platform/graphics/filters/FilterOperations.h" |
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h" |
#include "platform/graphics/filters/SourceGraphic.h" |
+#include "public/platform/WebPoint.h" |
#include "wtf/MathExtras.h" |
#include <algorithm> |
@@ -122,7 +125,7 @@ Vector<float> sepiaMatrix(double amount) |
} // namespace |
FilterEffectBuilder::FilterEffectBuilder( |
- Element* target, |
+ Node* target, |
const FloatRect& zoomedReferenceBox, float zoom, |
const SkPaint* fillPaint, const SkPaint* strokePaint) |
: m_targetContext(target) |
@@ -140,14 +143,19 @@ FilterEffect* FilterEffectBuilder::buildFilterEffect(const FilterOperations& ope |
// Create a parent filter for shorthand filters. These have already been scaled by the CSS code for page zoom, so scale is 1.0 here. |
Filter* parentFilter = Filter::create(1.0f); |
FilterEffect* previousEffect = parentFilter->getSourceGraphic(); |
- for (size_t i = 0; i < operations.operations().size(); ++i) { |
+ for (FilterOperation* filterOperation : operations.operations()) { |
FilterEffect* effect = nullptr; |
- FilterOperation* filterOperation = operations.operations().at(i).get(); |
switch (filterOperation->type()) { |
case FilterOperation::REFERENCE: { |
- Filter* referenceFilter = buildReferenceFilter(toReferenceFilterOperation(*filterOperation), previousEffect); |
- if (referenceFilter) |
+ ReferenceFilterOperation& referenceOperation = toReferenceFilterOperation(*filterOperation); |
+ if (Filter* referenceFilter = buildReferenceFilter(referenceOperation, previousEffect)) { |
+ // TODO(fs): This is essentially only needed for the |
+ // side-effects (mapRect). The filter differs from the one |
+ // computed just above in what the SourceGraphic is, and how |
+ // it's connected to the filter-chain. |
+ referenceOperation.setFilter(buildReferenceFilter(referenceOperation, nullptr)); |
effect = referenceFilter->lastEffect(); |
+ } |
break; |
} |
case FilterOperation::GRAYSCALE: { |
@@ -255,12 +263,107 @@ FilterEffect* FilterEffectBuilder::buildFilterEffect(const FilterOperations& ope |
return previousEffect; |
} |
+CompositorFilterOperations FilterEffectBuilder::buildFilterOperations(const FilterOperations& operations) const |
+{ |
+ ColorSpace currentColorSpace = ColorSpaceDeviceRGB; |
+ |
+ CompositorFilterOperations filters; |
+ for (FilterOperation* op : operations.operations()) { |
+ switch (op->type()) { |
+ case FilterOperation::REFERENCE: { |
+ ReferenceFilterOperation& referenceOperation = toReferenceFilterOperation(*op); |
+ Filter* referenceFilter = buildReferenceFilter(referenceOperation, nullptr); |
+ if (referenceFilter && referenceFilter->lastEffect()) { |
+ referenceOperation.setFilter(referenceFilter); |
+ SkiaImageFilterBuilder::populateSourceGraphicImageFilters(referenceFilter->getSourceGraphic(), nullptr, currentColorSpace); |
+ |
+ FilterEffect* filterEffect = referenceFilter->lastEffect(); |
+ currentColorSpace = filterEffect->operatingColorSpace(); |
+ filters.appendReferenceFilter(SkiaImageFilterBuilder::build(filterEffect, currentColorSpace)); |
+ } |
+ break; |
+ } |
+ case FilterOperation::GRAYSCALE: |
+ case FilterOperation::SEPIA: |
+ case FilterOperation::SATURATE: |
+ case FilterOperation::HUE_ROTATE: { |
+ float amount = toBasicColorMatrixFilterOperation(*op).amount(); |
+ switch (op->type()) { |
+ case FilterOperation::GRAYSCALE: |
+ filters.appendGrayscaleFilter(amount); |
+ break; |
+ case FilterOperation::SEPIA: |
+ filters.appendSepiaFilter(amount); |
+ break; |
+ case FilterOperation::SATURATE: |
+ filters.appendSaturateFilter(amount); |
+ break; |
+ case FilterOperation::HUE_ROTATE: |
+ filters.appendHueRotateFilter(amount); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ break; |
+ } |
+ case FilterOperation::INVERT: |
+ case FilterOperation::OPACITY: |
+ case FilterOperation::BRIGHTNESS: |
+ case FilterOperation::CONTRAST: { |
+ float amount = toBasicComponentTransferFilterOperation(*op).amount(); |
+ switch (op->type()) { |
+ case FilterOperation::INVERT: |
+ filters.appendInvertFilter(amount); |
+ break; |
+ case FilterOperation::OPACITY: |
+ filters.appendOpacityFilter(amount); |
+ break; |
+ case FilterOperation::BRIGHTNESS: |
+ filters.appendBrightnessFilter(amount); |
+ break; |
+ case FilterOperation::CONTRAST: |
+ filters.appendContrastFilter(amount); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ break; |
+ } |
+ case FilterOperation::BLUR: { |
+ float pixelRadius = toBlurFilterOperation(*op).stdDeviation().getFloatValue(); |
+ filters.appendBlurFilter(pixelRadius); |
+ break; |
+ } |
+ case FilterOperation::DROP_SHADOW: { |
+ const DropShadowFilterOperation& drop = toDropShadowFilterOperation(*op); |
+ filters.appendDropShadowFilter(WebPoint(drop.x(), drop.y()), drop.stdDeviation(), drop.getColor().rgb()); |
+ break; |
+ } |
+ case FilterOperation::BOX_REFLECT: { |
+ // TODO(jbroman): Consider explaining box reflect to the compositor, |
+ // instead of calling this a "reference filter". |
+ const auto& reflection = toBoxReflectFilterOperation(*op).reflection(); |
+ filters.appendReferenceFilter(SkiaImageFilterBuilder::buildBoxReflectFilter(reflection, nullptr)); |
+ break; |
+ } |
+ case FilterOperation::NONE: |
+ break; |
+ } |
+ } |
+ if (currentColorSpace != ColorSpaceDeviceRGB) { |
+ // Transform to device color space at the end of processing, if required. |
+ sk_sp<SkImageFilter> filter = SkiaImageFilterBuilder::transformColorSpace(nullptr, currentColorSpace, ColorSpaceDeviceRGB); |
+ filters.appendReferenceFilter(std::move(filter)); |
+ } |
+ return filters; |
+} |
+ |
Filter* FilterEffectBuilder::buildReferenceFilter( |
const ReferenceFilterOperation& referenceOperation, |
FilterEffect* previousEffect) const |
{ |
- DCHECK(m_targetContext); |
- SVGFilterElement* filterElement = ReferenceFilterBuilder::resolveFilterReference(referenceOperation, *m_targetContext); |
+ DCHECK(m_targetContext && m_targetContext->isElementNode()); |
+ SVGFilterElement* filterElement = ReferenceFilterBuilder::resolveFilterReference(referenceOperation, toElement(*m_targetContext)); |
if (!filterElement) |
return nullptr; |
return buildReferenceFilter(*filterElement, previousEffect); |