2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
29 #include "SkBlurImageFilter.h"
30 #include "SkColorFilterImageFilter.h"
31 #include "SkColorMatrixFilter.h"
32 #include "SkDropShadowImageFilter.h"
33 #include "SkMatrixImageFilter.h"
34 #include "SkTableColorFilter.h"
35 #include "platform/graphics/ImageBuffer.h"
36 #include "platform/graphics/filters/FilterEffect.h"
37 #include "platform/graphics/filters/FilterOperations.h"
38 #include "platform/graphics/filters/SourceGraphic.h"
39 #include "public/platform/WebPoint.h"
43 SkiaImageFilterBuilder::SkiaImageFilterBuilder()
48 SkiaImageFilterBuilder::SkiaImageFilterBuilder(GraphicsContext* context)
53 SkiaImageFilterBuilder::~SkiaImageFilterBuilder()
57 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace, bool destinationRequiresValidPreMultipliedPixels)
62 bool requiresPMColorValidation = effect->mayProduceInvalidPreMultipliedPixels() && destinationRequiresValidPreMultipliedPixels;
64 if (SkImageFilter* filter = effect->getImageFilter(colorSpace, requiresPMColorValidation))
67 // Note that we may still need the color transform even if the filter is null
68 RefPtr<SkImageFilter> origFilter = requiresPMColorValidation ? effect->createImageFilter(this) : effect->createImageFilterWithoutValidation(this);
69 RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
70 effect->setImageFilter(colorSpace, requiresPMColorValidation, filter.get());
71 if (filter.get() != origFilter.get())
72 effect->setImageFilter(effect->operatingColorSpace(), requiresPMColorValidation, origFilter.get());
73 return filter.release();
76 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::transformColorSpace(
77 SkImageFilter* input, ColorSpace srcColorSpace, ColorSpace dstColorSpace) {
79 RefPtr<SkColorFilter> colorFilter = ImageBuffer::createColorSpaceFilter(srcColorSpace, dstColorSpace);
83 return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input));
86 bool SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& operations, blink::WebFilterOperations* filters)
91 ColorSpace currentColorSpace = ColorSpaceDeviceRGB;
92 SkImageFilter* const nullFilter = 0;
94 for (size_t i = 0; i < operations.size(); ++i) {
95 const FilterOperation& op = *operations.at(i);
97 case FilterOperation::REFERENCE: {
98 RefPtr<SkImageFilter> filter;
99 ReferenceFilter* referenceFilter = toReferenceFilterOperation(op).filter();
100 if (referenceFilter && referenceFilter->lastEffect()) {
101 FilterEffect* filterEffect = referenceFilter->lastEffect();
102 // Prepopulate SourceGraphic with two image filters: one with a null image
103 // filter, and the other with a colorspace conversion filter.
104 // We don't know what color space the interior nodes will request, so we have to
105 // initialize SourceGraphic with both options.
106 // Since we know SourceGraphic is always PM-valid, we also use
107 // these for the PM-validated options.
108 RefPtr<SkImageFilter> deviceFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
109 RefPtr<SkImageFilter> linearFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceLinearRGB);
110 FilterEffect* sourceGraphic = referenceFilter->sourceGraphic();
111 sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, false, deviceFilter.get());
112 sourceGraphic->setImageFilter(ColorSpaceLinearRGB, false, linearFilter.get());
113 sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, true, deviceFilter.get());
114 sourceGraphic->setImageFilter(ColorSpaceLinearRGB, true, linearFilter.get());
116 currentColorSpace = filterEffect->operatingColorSpace();
117 filter = SkiaImageFilterBuilder::build(filterEffect, currentColorSpace);
118 filters->appendReferenceFilter(filter.get());
122 case FilterOperation::GRAYSCALE:
123 case FilterOperation::SEPIA:
124 case FilterOperation::SATURATE:
125 case FilterOperation::HUE_ROTATE: {
126 float amount = toBasicColorMatrixFilterOperation(op).amount();
128 case FilterOperation::GRAYSCALE:
129 filters->appendGrayscaleFilter(amount);
131 case FilterOperation::SEPIA:
132 filters->appendSepiaFilter(amount);
134 case FilterOperation::SATURATE:
135 filters->appendSaturateFilter(amount);
137 case FilterOperation::HUE_ROTATE:
138 filters->appendHueRotateFilter(amount);
141 ASSERT_NOT_REACHED();
145 case FilterOperation::INVERT:
146 case FilterOperation::OPACITY:
147 case FilterOperation::BRIGHTNESS:
148 case FilterOperation::CONTRAST: {
149 float amount = toBasicComponentTransferFilterOperation(op).amount();
151 case FilterOperation::INVERT:
152 filters->appendInvertFilter(amount);
154 case FilterOperation::OPACITY:
155 filters->appendOpacityFilter(amount);
157 case FilterOperation::BRIGHTNESS:
158 filters->appendBrightnessFilter(amount);
160 case FilterOperation::CONTRAST:
161 filters->appendContrastFilter(amount);
164 ASSERT_NOT_REACHED();
168 case FilterOperation::BLUR: {
169 float pixelRadius = toBlurFilterOperation(op).stdDeviation().getFloatValue();
170 filters->appendBlurFilter(pixelRadius);
173 case FilterOperation::DROP_SHADOW: {
174 const DropShadowFilterOperation& drop = toDropShadowFilterOperation(op);
175 filters->appendDropShadowFilter(blink::WebPoint(drop.x(), drop.y()), drop.stdDeviation(), drop.color().rgb());
178 case FilterOperation::NONE:
182 if (currentColorSpace != ColorSpaceDeviceRGB) {
183 // Transform to device color space at the end of processing, if required
184 RefPtr<SkImageFilter> filter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
185 filters->appendReferenceFilter(filter.get());
190 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::buildTransform(const AffineTransform& transform, SkImageFilter* input)
192 return adoptRef(SkMatrixImageFilter::Create(affineTransformToSkMatrix(transform), SkPaint::kHigh_FilterLevel, input));