OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <algorithm> | |
6 | |
7 #include "base/trace_event/trace_event_argument.h" | |
8 #include "base/values.h" | |
9 #include "cc/base/math_util.h" | |
10 #include "cc/output/filter_operation.h" | |
11 #include "ui/gfx/animation/tween.h" | |
12 | |
13 namespace cc { | |
14 | |
15 bool FilterOperation::operator==(const FilterOperation& other) const { | |
16 if (type_ != other.type_) | |
17 return false; | |
18 if (type_ == COLOR_MATRIX) | |
19 return !memcmp(matrix_, other.matrix_, sizeof(matrix_)); | |
20 if (type_ == DROP_SHADOW) { | |
21 return amount_ == other.amount_ && | |
22 drop_shadow_offset_ == other.drop_shadow_offset_ && | |
23 drop_shadow_color_ == other.drop_shadow_color_; | |
24 } | |
25 if (type_ == REFERENCE) | |
26 return image_filter_.get() == other.image_filter_.get(); | |
27 if (type_ == ALPHA_THRESHOLD) { | |
28 return region_ == other.region_ && | |
29 amount_ == other.amount_ && | |
30 outer_threshold_ == other.outer_threshold_; | |
31 } | |
32 return amount_ == other.amount_; | |
33 } | |
34 | |
35 FilterOperation::FilterOperation(FilterType type, float amount) | |
36 : type_(type), | |
37 amount_(amount), | |
38 outer_threshold_(0), | |
39 drop_shadow_offset_(0, 0), | |
40 drop_shadow_color_(0), | |
41 zoom_inset_(0) { | |
42 DCHECK_NE(type_, DROP_SHADOW); | |
43 DCHECK_NE(type_, COLOR_MATRIX); | |
44 DCHECK_NE(type_, REFERENCE); | |
45 memset(matrix_, 0, sizeof(matrix_)); | |
46 } | |
47 | |
48 FilterOperation::FilterOperation(FilterType type, | |
49 const gfx::Point& offset, | |
50 float stdDeviation, | |
51 SkColor color) | |
52 : type_(type), | |
53 amount_(stdDeviation), | |
54 outer_threshold_(0), | |
55 drop_shadow_offset_(offset), | |
56 drop_shadow_color_(color), | |
57 zoom_inset_(0) { | |
58 DCHECK_EQ(type_, DROP_SHADOW); | |
59 memset(matrix_, 0, sizeof(matrix_)); | |
60 } | |
61 | |
62 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20]) | |
63 : type_(type), | |
64 amount_(0), | |
65 outer_threshold_(0), | |
66 drop_shadow_offset_(0, 0), | |
67 drop_shadow_color_(0), | |
68 zoom_inset_(0) { | |
69 DCHECK_EQ(type_, COLOR_MATRIX); | |
70 memcpy(matrix_, matrix, sizeof(matrix_)); | |
71 } | |
72 | |
73 FilterOperation::FilterOperation(FilterType type, float amount, int inset) | |
74 : type_(type), | |
75 amount_(amount), | |
76 outer_threshold_(0), | |
77 drop_shadow_offset_(0, 0), | |
78 drop_shadow_color_(0), | |
79 zoom_inset_(inset) { | |
80 DCHECK_EQ(type_, ZOOM); | |
81 memset(matrix_, 0, sizeof(matrix_)); | |
82 } | |
83 | |
84 FilterOperation::FilterOperation( | |
85 FilterType type, | |
86 const skia::RefPtr<SkImageFilter>& image_filter) | |
87 : type_(type), | |
88 amount_(0), | |
89 outer_threshold_(0), | |
90 drop_shadow_offset_(0, 0), | |
91 drop_shadow_color_(0), | |
92 image_filter_(image_filter), | |
93 zoom_inset_(0) { | |
94 DCHECK_EQ(type_, REFERENCE); | |
95 memset(matrix_, 0, sizeof(matrix_)); | |
96 } | |
97 | |
98 FilterOperation::FilterOperation(FilterType type, | |
99 const SkRegion& region, | |
100 float inner_threshold, | |
101 float outer_threshold) | |
102 : type_(type), | |
103 amount_(inner_threshold), | |
104 outer_threshold_(outer_threshold), | |
105 drop_shadow_offset_(0, 0), | |
106 drop_shadow_color_(0), | |
107 zoom_inset_(0), | |
108 region_(region) { | |
109 DCHECK_EQ(type_, ALPHA_THRESHOLD); | |
110 memset(matrix_, 0, sizeof(matrix_)); | |
111 } | |
112 | |
113 FilterOperation::FilterOperation(const FilterOperation& other) | |
114 : type_(other.type_), | |
115 amount_(other.amount_), | |
116 outer_threshold_(other.outer_threshold_), | |
117 drop_shadow_offset_(other.drop_shadow_offset_), | |
118 drop_shadow_color_(other.drop_shadow_color_), | |
119 image_filter_(other.image_filter_), | |
120 zoom_inset_(other.zoom_inset_), | |
121 region_(other.region_) { | |
122 memcpy(matrix_, other.matrix_, sizeof(matrix_)); | |
123 } | |
124 | |
125 FilterOperation::~FilterOperation() { | |
126 } | |
127 | |
128 static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { | |
129 switch (type) { | |
130 case FilterOperation::GRAYSCALE: | |
131 return FilterOperation::CreateGrayscaleFilter(0.f); | |
132 case FilterOperation::SEPIA: | |
133 return FilterOperation::CreateSepiaFilter(0.f); | |
134 case FilterOperation::SATURATE: | |
135 return FilterOperation::CreateSaturateFilter(1.f); | |
136 case FilterOperation::HUE_ROTATE: | |
137 return FilterOperation::CreateHueRotateFilter(0.f); | |
138 case FilterOperation::INVERT: | |
139 return FilterOperation::CreateInvertFilter(0.f); | |
140 case FilterOperation::BRIGHTNESS: | |
141 return FilterOperation::CreateBrightnessFilter(1.f); | |
142 case FilterOperation::CONTRAST: | |
143 return FilterOperation::CreateContrastFilter(1.f); | |
144 case FilterOperation::OPACITY: | |
145 return FilterOperation::CreateOpacityFilter(1.f); | |
146 case FilterOperation::BLUR: | |
147 return FilterOperation::CreateBlurFilter(0.f); | |
148 case FilterOperation::DROP_SHADOW: | |
149 return FilterOperation::CreateDropShadowFilter( | |
150 gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT); | |
151 case FilterOperation::COLOR_MATRIX: { | |
152 SkScalar matrix[20]; | |
153 memset(matrix, 0, 20 * sizeof(SkScalar)); | |
154 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f; | |
155 return FilterOperation::CreateColorMatrixFilter(matrix); | |
156 } | |
157 case FilterOperation::ZOOM: | |
158 return FilterOperation::CreateZoomFilter(1.f, 0); | |
159 case FilterOperation::SATURATING_BRIGHTNESS: | |
160 return FilterOperation::CreateSaturatingBrightnessFilter(0.f); | |
161 case FilterOperation::REFERENCE: | |
162 return FilterOperation::CreateReferenceFilter( | |
163 skia::RefPtr<SkImageFilter>()); | |
164 case FilterOperation::ALPHA_THRESHOLD: | |
165 return FilterOperation::CreateAlphaThresholdFilter(SkRegion(), 1.f, 0.f); | |
166 } | |
167 NOTREACHED(); | |
168 return FilterOperation::CreateEmptyFilter(); | |
169 } | |
170 | |
171 static float ClampAmountForFilterType(float amount, | |
172 FilterOperation::FilterType type) { | |
173 switch (type) { | |
174 case FilterOperation::GRAYSCALE: | |
175 case FilterOperation::SEPIA: | |
176 case FilterOperation::INVERT: | |
177 case FilterOperation::OPACITY: | |
178 case FilterOperation::ALPHA_THRESHOLD: | |
179 return MathUtil::ClampToRange(amount, 0.f, 1.f); | |
180 case FilterOperation::SATURATE: | |
181 case FilterOperation::BRIGHTNESS: | |
182 case FilterOperation::CONTRAST: | |
183 case FilterOperation::BLUR: | |
184 case FilterOperation::DROP_SHADOW: | |
185 return std::max(amount, 0.f); | |
186 case FilterOperation::ZOOM: | |
187 return std::max(amount, 1.f); | |
188 case FilterOperation::HUE_ROTATE: | |
189 case FilterOperation::SATURATING_BRIGHTNESS: | |
190 return amount; | |
191 case FilterOperation::COLOR_MATRIX: | |
192 case FilterOperation::REFERENCE: | |
193 NOTREACHED(); | |
194 return amount; | |
195 } | |
196 NOTREACHED(); | |
197 return amount; | |
198 } | |
199 | |
200 // static | |
201 FilterOperation FilterOperation::Blend(const FilterOperation* from, | |
202 const FilterOperation* to, | |
203 double progress) { | |
204 FilterOperation blended_filter = FilterOperation::CreateEmptyFilter(); | |
205 | |
206 if (!from && !to) | |
207 return blended_filter; | |
208 | |
209 const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type()); | |
210 const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type()); | |
211 | |
212 if (from_op.type() != to_op.type()) | |
213 return blended_filter; | |
214 | |
215 DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX); | |
216 blended_filter.set_type(to_op.type()); | |
217 | |
218 if (to_op.type() == FilterOperation::REFERENCE) { | |
219 if (progress > 0.5) | |
220 blended_filter.set_image_filter(to_op.image_filter()); | |
221 else | |
222 blended_filter.set_image_filter(from_op.image_filter()); | |
223 return blended_filter; | |
224 } | |
225 | |
226 blended_filter.set_amount(ClampAmountForFilterType( | |
227 gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()), | |
228 to_op.type())); | |
229 | |
230 if (to_op.type() == FilterOperation::DROP_SHADOW) { | |
231 gfx::Point blended_offset( | |
232 gfx::Tween::LinearIntValueBetween(progress, | |
233 from_op.drop_shadow_offset().x(), | |
234 to_op.drop_shadow_offset().x()), | |
235 gfx::Tween::LinearIntValueBetween(progress, | |
236 from_op.drop_shadow_offset().y(), | |
237 to_op.drop_shadow_offset().y())); | |
238 blended_filter.set_drop_shadow_offset(blended_offset); | |
239 blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( | |
240 progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); | |
241 } else if (to_op.type() == FilterOperation::ZOOM) { | |
242 blended_filter.set_zoom_inset( | |
243 std::max(gfx::Tween::LinearIntValueBetween( | |
244 from_op.zoom_inset(), to_op.zoom_inset(), progress), | |
245 0)); | |
246 } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) { | |
247 blended_filter.set_outer_threshold(ClampAmountForFilterType( | |
248 gfx::Tween::FloatValueBetween(progress, | |
249 from_op.outer_threshold(), | |
250 to_op.outer_threshold()), | |
251 to_op.type())); | |
252 blended_filter.set_region(to_op.region()); | |
253 } | |
254 | |
255 return blended_filter; | |
256 } | |
257 | |
258 void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const { | |
259 value->SetInteger("type", type_); | |
260 switch (type_) { | |
261 case FilterOperation::GRAYSCALE: | |
262 case FilterOperation::SEPIA: | |
263 case FilterOperation::SATURATE: | |
264 case FilterOperation::HUE_ROTATE: | |
265 case FilterOperation::INVERT: | |
266 case FilterOperation::BRIGHTNESS: | |
267 case FilterOperation::CONTRAST: | |
268 case FilterOperation::OPACITY: | |
269 case FilterOperation::BLUR: | |
270 case FilterOperation::SATURATING_BRIGHTNESS: | |
271 value->SetDouble("amount", amount_); | |
272 break; | |
273 case FilterOperation::DROP_SHADOW: | |
274 value->SetDouble("std_deviation", amount_); | |
275 MathUtil::AddToTracedValue("offset", drop_shadow_offset_, value); | |
276 value->SetInteger("color", drop_shadow_color_); | |
277 break; | |
278 case FilterOperation::COLOR_MATRIX: { | |
279 value->BeginArray("matrix"); | |
280 for (size_t i = 0; i < arraysize(matrix_); ++i) | |
281 value->AppendDouble(matrix_[i]); | |
282 value->EndArray(); | |
283 break; | |
284 } | |
285 case FilterOperation::ZOOM: | |
286 value->SetDouble("amount", amount_); | |
287 value->SetDouble("inset", zoom_inset_); | |
288 break; | |
289 case FilterOperation::REFERENCE: { | |
290 int count_inputs = 0; | |
291 bool can_filter_image_gpu = false; | |
292 if (image_filter_) { | |
293 count_inputs = image_filter_->countInputs(); | |
294 can_filter_image_gpu = image_filter_->canFilterImageGPU(); | |
295 } | |
296 value->SetBoolean("is_null", !image_filter_); | |
297 value->SetInteger("count_inputs", count_inputs); | |
298 value->SetBoolean("can_filter_image_gpu", can_filter_image_gpu); | |
299 break; | |
300 } | |
301 case FilterOperation::ALPHA_THRESHOLD: { | |
302 value->SetDouble("inner_threshold", amount_); | |
303 value->SetDouble("outer_threshold", outer_threshold_); | |
304 scoped_ptr<base::ListValue> region_value(new base::ListValue()); | |
305 value->BeginArray("region"); | |
306 for (SkRegion::Iterator it(region_); !it.done(); it.next()) { | |
307 value->AppendInteger(it.rect().x()); | |
308 value->AppendInteger(it.rect().y()); | |
309 value->AppendInteger(it.rect().width()); | |
310 value->AppendInteger(it.rect().height()); | |
311 } | |
312 value->EndArray(); | |
313 } | |
314 break; | |
315 } | |
316 } | |
317 | |
318 } // namespace cc | |
OLD | NEW |