OLD | NEW |
| (Empty) |
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 "core/platform/graphics/filters/SkiaImageFilterBuilder.h" | |
28 | |
29 #include "SkBlurImageFilter.h" | |
30 #include "SkColorFilterImageFilter.h" | |
31 #include "SkColorMatrixFilter.h" | |
32 #include "SkDropShadowImageFilter.h" | |
33 #include "SkTableColorFilter.h" | |
34 #include "core/platform/graphics/ImageBuffer.h" | |
35 #include "core/platform/graphics/filters/FilterEffect.h" | |
36 #include "core/platform/graphics/filters/FilterOperations.h" | |
37 #include "core/platform/graphics/filters/SourceGraphic.h" | |
38 #include "public/platform/WebPoint.h" | |
39 | |
40 namespace { | |
41 | |
42 PassRefPtr<SkImageFilter> createMatrixImageFilter(SkScalar matrix[20], SkImageFi
lter* input) | |
43 { | |
44 RefPtr<SkColorFilter> colorFilter(adoptRef(new SkColorMatrixFilter(matrix)))
; | |
45 return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input)); | |
46 } | |
47 | |
48 }; | |
49 | |
50 namespace WebCore { | |
51 | |
52 SkiaImageFilterBuilder::SkiaImageFilterBuilder() | |
53 { | |
54 } | |
55 | |
56 SkiaImageFilterBuilder::~SkiaImageFilterBuilder() | |
57 { | |
58 } | |
59 | |
60 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::build(FilterEffect* effect, Co
lorSpace colorSpace) | |
61 { | |
62 if (!effect) | |
63 return 0; | |
64 | |
65 FilterColorSpacePair key(effect, colorSpace); | |
66 FilterBuilderHashMap::iterator it = m_map.find(key); | |
67 if (it != m_map.end()) { | |
68 return it->value; | |
69 } else { | |
70 // Note that we may still need the color transform even if the filter is
null | |
71 RefPtr<SkImageFilter> origFilter = effect->createImageFilter(this); | |
72 RefPtr<SkImageFilter> filter = transformColorSpace(origFilter.get(), eff
ect->operatingColorSpace(), colorSpace); | |
73 m_map.set(key, filter); | |
74 return filter.release(); | |
75 } | |
76 } | |
77 | |
78 PassRefPtr<SkImageFilter> SkiaImageFilterBuilder::transformColorSpace( | |
79 SkImageFilter* input, ColorSpace srcColorSpace, ColorSpace dstColorSpace) { | |
80 | |
81 RefPtr<SkColorFilter> colorFilter = ImageBuffer::createColorSpaceFilter(srcC
olorSpace, dstColorSpace); | |
82 if (!colorFilter) | |
83 return input; | |
84 | |
85 return adoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), input)); | |
86 } | |
87 | |
88 bool SkiaImageFilterBuilder::buildFilterOperations(const FilterOperations& opera
tions, blink::WebFilterOperations* filters) | |
89 { | |
90 if (!filters) | |
91 return false; | |
92 | |
93 ColorSpace currentColorSpace = ColorSpaceDeviceRGB; | |
94 | |
95 RefPtr<SkImageFilter> noopFilter; | |
96 SkScalar matrix[20]; | |
97 memset(matrix, 0, 20 * sizeof(SkScalar)); | |
98 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f; | |
99 noopFilter = createMatrixImageFilter(matrix, 0); | |
100 | |
101 for (size_t i = 0; i < operations.size(); ++i) { | |
102 const FilterOperation& op = *operations.at(i); | |
103 switch (op.type()) { | |
104 case FilterOperation::REFERENCE: { | |
105 RefPtr<SkImageFilter> filter; | |
106 ReferenceFilter* referenceFilter = toReferenceFilterOperation(op).fi
lter(); | |
107 if (referenceFilter && referenceFilter->lastEffect()) { | |
108 FilterEffect* filterEffect = referenceFilter->lastEffect(); | |
109 // Link SourceGraphic to a noop filter that serves as a plachold
er for | |
110 // the previous filter in the chain. We don't know what color sp
ace the | |
111 // interior nodes will request, so we have to populate the map w
ith both | |
112 // options. (Only one of these will actually have a color transf
orm on it.) | |
113 FilterColorSpacePair deviceKey(referenceFilter->sourceGraphic(),
ColorSpaceDeviceRGB); | |
114 FilterColorSpacePair linearKey(referenceFilter->sourceGraphic(),
ColorSpaceLinearRGB); | |
115 m_map.set(deviceKey, transformColorSpace(noopFilter.get(), curre
ntColorSpace, ColorSpaceDeviceRGB)); | |
116 m_map.set(linearKey, transformColorSpace(noopFilter.get(), curre
ntColorSpace, ColorSpaceLinearRGB)); | |
117 | |
118 currentColorSpace = filterEffect->operatingColorSpace(); | |
119 filter = SkiaImageFilterBuilder::build(filterEffect, currentColo
rSpace); | |
120 // We might have no reference to the SourceGraphic's Skia filter
now, so make | |
121 // sure we don't keep it in the map anymore. | |
122 m_map.remove(deviceKey); | |
123 m_map.remove(linearKey); | |
124 filters->appendReferenceFilter(filter.get()); | |
125 } | |
126 break; | |
127 } | |
128 case FilterOperation::GRAYSCALE: | |
129 case FilterOperation::SEPIA: | |
130 case FilterOperation::SATURATE: | |
131 case FilterOperation::HUE_ROTATE: { | |
132 float amount = toBasicColorMatrixFilterOperation(op).amount(); | |
133 switch (op.type()) { | |
134 case FilterOperation::GRAYSCALE: | |
135 filters->appendGrayscaleFilter(amount); | |
136 break; | |
137 case FilterOperation::SEPIA: | |
138 filters->appendSepiaFilter(amount); | |
139 break; | |
140 case FilterOperation::SATURATE: | |
141 filters->appendSaturateFilter(amount); | |
142 break; | |
143 case FilterOperation::HUE_ROTATE: | |
144 filters->appendHueRotateFilter(amount); | |
145 break; | |
146 default: | |
147 ASSERT_NOT_REACHED(); | |
148 } | |
149 break; | |
150 } | |
151 case FilterOperation::INVERT: | |
152 case FilterOperation::OPACITY: | |
153 case FilterOperation::BRIGHTNESS: | |
154 case FilterOperation::CONTRAST: { | |
155 float amount = toBasicComponentTransferFilterOperation(op).amount(); | |
156 switch (op.type()) { | |
157 case FilterOperation::INVERT: | |
158 filters->appendInvertFilter(amount); | |
159 break; | |
160 case FilterOperation::OPACITY: | |
161 filters->appendOpacityFilter(amount); | |
162 break; | |
163 case FilterOperation::BRIGHTNESS: | |
164 filters->appendBrightnessFilter(amount); | |
165 break; | |
166 case FilterOperation::CONTRAST: | |
167 filters->appendContrastFilter(amount); | |
168 break; | |
169 default: | |
170 ASSERT_NOT_REACHED(); | |
171 } | |
172 break; | |
173 } | |
174 case FilterOperation::BLUR: { | |
175 float pixelRadius = toBlurFilterOperation(op).stdDeviation().getFloa
tValue(); | |
176 filters->appendBlurFilter(pixelRadius); | |
177 break; | |
178 } | |
179 case FilterOperation::DROP_SHADOW: { | |
180 const DropShadowFilterOperation& drop = toDropShadowFilterOperation(
op); | |
181 filters->appendDropShadowFilter(blink::WebPoint(drop.x(), drop.y()),
drop.stdDeviation(), drop.color().rgb()); | |
182 break; | |
183 } | |
184 case FilterOperation::VALIDATED_CUSTOM: | |
185 case FilterOperation::CUSTOM: | |
186 return false; // Not supported. | |
187 case FilterOperation::NONE: | |
188 break; | |
189 } | |
190 } | |
191 if (currentColorSpace != ColorSpaceDeviceRGB) { | |
192 // Transform to device color space at the end of processing, if required | |
193 RefPtr<SkImageFilter> filter; | |
194 filter = transformColorSpace(noopFilter.get(), currentColorSpace, ColorS
paceDeviceRGB); | |
195 if (filter != noopFilter) | |
196 filters->appendReferenceFilter(filter.get()); | |
197 } | |
198 return true; | |
199 } | |
200 | |
201 }; | |
OLD | NEW |