Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / filters / SkiaImageFilterBuilder.cpp
1 /*
2  * Copyright (C) 2012 Google 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  *
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 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.
24  */
25 #include "config.h"
26
27 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
28
29 #include "SkBlurImageFilter.h"
30 #include "SkColorFilterImageFilter.h"
31 #include "SkColorMatrixFilter.h"
32 #include "SkMatrixImageFilter.h"
33 #include "SkTableColorFilter.h"
34 #include "platform/graphics/ImageBuffer.h"
35 #include "platform/graphics/filters/FilterEffect.h"
36 #include "platform/graphics/filters/FilterOperations.h"
37 #include "platform/graphics/filters/SourceGraphic.h"
38 #include "platform/graphics/skia/SkiaUtils.h"
39 #include "public/platform/WebPoint.h"
40
41 namespace blink {
42
43 SkiaImageFilterBuilder::SkiaImageFilterBuilder()
44     : m_context(0)
45     , m_sourceGraphic(0)
46 {
47 }
48
49 SkiaImageFilterBuilder::SkiaImageFilterBuilder(GraphicsContext* context)
50     : m_context(context)
51     , m_sourceGraphic(0)
52 {
53 }
54
55 SkiaImageFilterBuilder::~SkiaImageFilterBuilder()
56 {
57 }
58
59 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, ColorSpace colorSpace, bool destinationRequiresValidPreMultipliedPixels)
60 {
61     if (!effect)
62         return nullptr;
63
64     bool requiresPMColorValidation = effect->mayProduceInvalidPreMultipliedPixels() && destinationRequiresValidPreMultipliedPixels;
65
66     if (SkImageFilter* filter = effect->getImageFilter(colorSpace, requiresPMColorValidation))
67         return filter;
68
69     // Note that we may still need the color transform even if the filter is null
70     RefPtr<SkImageFilter> origFilter = requiresPMColorValidation ? effect->createImageFilter(this) : effect->createImageFilterWithoutValidation(this);
71     RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), effect->operatingColorSpace(), colorSpace);
72     effect->setImageFilter(colorSpace, requiresPMColorValidation, filter.get());
73     if (filter.get() != origFilter.get())
74         effect->setImageFilter(effect->operatingColorSpace(), requiresPMColorValidation, origFilter.get());
75     return filter.release();
76 }
77
78 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::transformColorSpace(
79     SkImageFilter* input, ColorSpace srcColorSpace, ColorSpace dstColorSpace) {
80
81     RefPtr<SkColorFilter> colorFilter = ImageBuffer::createColorSpaceFilter(srcColorSpace, dstColorSpace);
82     if (!colorFilter)
83         return input;
84
85     return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input));
86 }
87
88 void SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& operations, WebFilterOperations* filters)
89 {
90     ColorSpace currentColorSpace = ColorSpaceDeviceRGB;
91     SkImageFilter* const nullFilter = 0;
92
93     for (size_t i = 0; i < operations.size(); ++i) {
94         const FilterOperation& op = *operations.at(i);
95         switch (op.type()) {
96         case FilterOperation::REFERENCE: {
97             RefPtr<SkImageFilter> filter;
98             ReferenceFilter* referenceFilter = toReferenceFilterOperation(op).filter();
99             if (referenceFilter && referenceFilter->lastEffect()) {
100                 FilterEffect* filterEffect = referenceFilter->lastEffect();
101                 // Prepopulate SourceGraphic with two image filters: one with a null image
102                 // filter, and the other with a colorspace conversion filter.
103                 // We don't know what color space the interior nodes will request, so we have to
104                 // initialize SourceGraphic with both options.
105                 // Since we know SourceGraphic is always PM-valid, we also use
106                 // these for the PM-validated options.
107                 RefPtr<SkImageFilter> deviceFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
108                 RefPtr<SkImageFilter> linearFilter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceLinearRGB);
109                 FilterEffect* sourceGraphic = referenceFilter->sourceGraphic();
110                 sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, false, deviceFilter.get());
111                 sourceGraphic->setImageFilter(ColorSpaceLinearRGB, false, linearFilter.get());
112                 sourceGraphic->setImageFilter(ColorSpaceDeviceRGB, true, deviceFilter.get());
113                 sourceGraphic->setImageFilter(ColorSpaceLinearRGB, true, linearFilter.get());
114
115                 currentColorSpace = filterEffect->operatingColorSpace();
116                 filter = SkiaImageFilterBuilder::build(filterEffect, currentColorSpace);
117                 filters->appendReferenceFilter(filter.get());
118             }
119             break;
120         }
121         case FilterOperation::GRAYSCALE:
122         case FilterOperation::SEPIA:
123         case FilterOperation::SATURATE:
124         case FilterOperation::HUE_ROTATE: {
125             float amount = toBasicColorMatrixFilterOperation(op).amount();
126             switch (op.type()) {
127             case FilterOperation::GRAYSCALE:
128                 filters->appendGrayscaleFilter(amount);
129                 break;
130             case FilterOperation::SEPIA:
131                 filters->appendSepiaFilter(amount);
132                 break;
133             case FilterOperation::SATURATE:
134                 filters->appendSaturateFilter(amount);
135                 break;
136             case FilterOperation::HUE_ROTATE:
137                 filters->appendHueRotateFilter(amount);
138                 break;
139             default:
140                 ASSERT_NOT_REACHED();
141             }
142             break;
143         }
144         case FilterOperation::INVERT:
145         case FilterOperation::OPACITY:
146         case FilterOperation::BRIGHTNESS:
147         case FilterOperation::CONTRAST: {
148             float amount = toBasicComponentTransferFilterOperation(op).amount();
149             switch (op.type()) {
150             case FilterOperation::INVERT:
151                 filters->appendInvertFilter(amount);
152                 break;
153             case FilterOperation::OPACITY:
154                 filters->appendOpacityFilter(amount);
155                 break;
156             case FilterOperation::BRIGHTNESS:
157                 filters->appendBrightnessFilter(amount);
158                 break;
159             case FilterOperation::CONTRAST:
160                 filters->appendContrastFilter(amount);
161                 break;
162             default:
163                 ASSERT_NOT_REACHED();
164             }
165             break;
166         }
167         case FilterOperation::BLUR: {
168             float pixelRadius = toBlurFilterOperation(op).stdDeviation().getFloatValue();
169             filters->appendBlurFilter(pixelRadius);
170             break;
171         }
172         case FilterOperation::DROP_SHADOW: {
173             const DropShadowFilterOperation& drop = toDropShadowFilterOperation(op);
174             filters->appendDropShadowFilter(WebPoint(drop.x(), drop.y()), drop.stdDeviation(), drop.color().rgb());
175             break;
176         }
177         case FilterOperation::NONE:
178             break;
179         }
180     }
181     if (currentColorSpace != ColorSpaceDeviceRGB) {
182         // Transform to device color space at the end of processing, if required
183         RefPtr<SkImageFilter> filter = transformColorSpace(nullFilter, currentColorSpace, ColorSpaceDeviceRGB);
184         filters->appendReferenceFilter(filter.get());
185     }
186 }
187
188 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::buildTransform(const AffineTransform& transform, SkImageFilter* input)
189 {
190     return adoptRef(SkMatrixImageFilter::Create(affineTransformToSkMatrix(transform), SkPaint::kHigh_FilterLevel, input));
191 }
192
193 } // namespace blink