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 <stddef.h> | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/trace_event/trace_event_argument.h" | |
10 #include "base/values.h" | |
11 #include "cc/base/math_util.h" | |
12 #include "cc/output/filter_operation.h" | |
13 #include "ui/gfx/animation/tween.h" | |
14 #include "ui/gfx/geometry/rect.h" | |
15 #include "ui/gfx/geometry/rect_conversions.h" | |
16 #include "ui/gfx/skia_util.h" | |
17 | |
18 namespace cc { | |
19 | |
20 bool FilterOperation::operator==(const FilterOperation& other) const { | |
21 if (type_ != other.type_) | |
22 return false; | |
23 if (type_ == COLOR_MATRIX) | |
24 return !memcmp(matrix_, other.matrix_, sizeof(matrix_)); | |
25 if (type_ == DROP_SHADOW) { | |
26 return amount_ == other.amount_ && | |
27 drop_shadow_offset_ == other.drop_shadow_offset_ && | |
28 drop_shadow_color_ == other.drop_shadow_color_; | |
29 } | |
30 if (type_ == REFERENCE) { | |
31 return image_filter_.get() == other.image_filter_.get(); | |
32 } | |
33 if (type_ == ALPHA_THRESHOLD) { | |
34 return region_ == other.region_ && | |
35 amount_ == other.amount_ && | |
36 outer_threshold_ == other.outer_threshold_; | |
37 } | |
38 return amount_ == other.amount_; | |
39 } | |
40 | |
41 FilterOperation::FilterOperation() : FilterOperation(GRAYSCALE, 0.f) {} | |
42 | |
43 FilterOperation::FilterOperation(FilterType type, float amount) | |
44 : type_(type), | |
45 amount_(amount), | |
46 outer_threshold_(0), | |
47 drop_shadow_offset_(0, 0), | |
48 drop_shadow_color_(0), | |
49 zoom_inset_(0) { | |
50 DCHECK_NE(type_, DROP_SHADOW); | |
51 DCHECK_NE(type_, COLOR_MATRIX); | |
52 DCHECK_NE(type_, REFERENCE); | |
53 memset(matrix_, 0, sizeof(matrix_)); | |
54 } | |
55 | |
56 FilterOperation::FilterOperation(FilterType type, | |
57 const gfx::Point& offset, | |
58 float stdDeviation, | |
59 SkColor color) | |
60 : type_(type), | |
61 amount_(stdDeviation), | |
62 outer_threshold_(0), | |
63 drop_shadow_offset_(offset), | |
64 drop_shadow_color_(color), | |
65 zoom_inset_(0) { | |
66 DCHECK_EQ(type_, DROP_SHADOW); | |
67 memset(matrix_, 0, sizeof(matrix_)); | |
68 } | |
69 | |
70 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20]) | |
71 : type_(type), | |
72 amount_(0), | |
73 outer_threshold_(0), | |
74 drop_shadow_offset_(0, 0), | |
75 drop_shadow_color_(0), | |
76 zoom_inset_(0) { | |
77 DCHECK_EQ(type_, COLOR_MATRIX); | |
78 memcpy(matrix_, matrix, sizeof(matrix_)); | |
79 } | |
80 | |
81 FilterOperation::FilterOperation(FilterType type, float amount, int inset) | |
82 : type_(type), | |
83 amount_(amount), | |
84 outer_threshold_(0), | |
85 drop_shadow_offset_(0, 0), | |
86 drop_shadow_color_(0), | |
87 zoom_inset_(inset) { | |
88 DCHECK_EQ(type_, ZOOM); | |
89 memset(matrix_, 0, sizeof(matrix_)); | |
90 } | |
91 | |
92 FilterOperation::FilterOperation(FilterType type, | |
93 sk_sp<SkImageFilter> image_filter) | |
94 : type_(type), | |
95 amount_(0), | |
96 outer_threshold_(0), | |
97 drop_shadow_offset_(0, 0), | |
98 drop_shadow_color_(0), | |
99 image_filter_(std::move(image_filter)), | |
100 zoom_inset_(0) { | |
101 DCHECK_EQ(type_, REFERENCE); | |
102 memset(matrix_, 0, sizeof(matrix_)); | |
103 } | |
104 | |
105 FilterOperation::FilterOperation(FilterType type, | |
106 const SkRegion& region, | |
107 float inner_threshold, | |
108 float outer_threshold) | |
109 : type_(type), | |
110 amount_(inner_threshold), | |
111 outer_threshold_(outer_threshold), | |
112 drop_shadow_offset_(0, 0), | |
113 drop_shadow_color_(0), | |
114 zoom_inset_(0), | |
115 region_(region) { | |
116 DCHECK_EQ(type_, ALPHA_THRESHOLD); | |
117 memset(matrix_, 0, sizeof(matrix_)); | |
118 } | |
119 | |
120 FilterOperation::FilterOperation(const FilterOperation& other) | |
121 : type_(other.type_), | |
122 amount_(other.amount_), | |
123 outer_threshold_(other.outer_threshold_), | |
124 drop_shadow_offset_(other.drop_shadow_offset_), | |
125 drop_shadow_color_(other.drop_shadow_color_), | |
126 image_filter_(other.image_filter_), | |
127 zoom_inset_(other.zoom_inset_), | |
128 region_(other.region_) { | |
129 memcpy(matrix_, other.matrix_, sizeof(matrix_)); | |
130 } | |
131 | |
132 FilterOperation::~FilterOperation() { | |
133 } | |
134 | |
135 static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { | |
136 switch (type) { | |
137 case FilterOperation::GRAYSCALE: | |
138 return FilterOperation::CreateGrayscaleFilter(0.f); | |
139 case FilterOperation::SEPIA: | |
140 return FilterOperation::CreateSepiaFilter(0.f); | |
141 case FilterOperation::SATURATE: | |
142 return FilterOperation::CreateSaturateFilter(1.f); | |
143 case FilterOperation::HUE_ROTATE: | |
144 return FilterOperation::CreateHueRotateFilter(0.f); | |
145 case FilterOperation::INVERT: | |
146 return FilterOperation::CreateInvertFilter(0.f); | |
147 case FilterOperation::BRIGHTNESS: | |
148 return FilterOperation::CreateBrightnessFilter(1.f); | |
149 case FilterOperation::CONTRAST: | |
150 return FilterOperation::CreateContrastFilter(1.f); | |
151 case FilterOperation::OPACITY: | |
152 return FilterOperation::CreateOpacityFilter(1.f); | |
153 case FilterOperation::BLUR: | |
154 return FilterOperation::CreateBlurFilter(0.f); | |
155 case FilterOperation::DROP_SHADOW: | |
156 return FilterOperation::CreateDropShadowFilter( | |
157 gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT); | |
158 case FilterOperation::COLOR_MATRIX: { | |
159 SkScalar matrix[20]; | |
160 memset(matrix, 0, 20 * sizeof(SkScalar)); | |
161 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f; | |
162 return FilterOperation::CreateColorMatrixFilter(matrix); | |
163 } | |
164 case FilterOperation::ZOOM: | |
165 return FilterOperation::CreateZoomFilter(1.f, 0); | |
166 case FilterOperation::SATURATING_BRIGHTNESS: | |
167 return FilterOperation::CreateSaturatingBrightnessFilter(0.f); | |
168 case FilterOperation::REFERENCE: | |
169 return FilterOperation::CreateReferenceFilter(nullptr); | |
170 case FilterOperation::ALPHA_THRESHOLD: | |
171 return FilterOperation::CreateAlphaThresholdFilter(SkRegion(), 1.f, 0.f); | |
172 } | |
173 NOTREACHED(); | |
174 return FilterOperation::CreateEmptyFilter(); | |
175 } | |
176 | |
177 static float ClampAmountForFilterType(float amount, | |
178 FilterOperation::FilterType type) { | |
179 switch (type) { | |
180 case FilterOperation::GRAYSCALE: | |
181 case FilterOperation::SEPIA: | |
182 case FilterOperation::INVERT: | |
183 case FilterOperation::OPACITY: | |
184 case FilterOperation::ALPHA_THRESHOLD: | |
185 return MathUtil::ClampToRange(amount, 0.f, 1.f); | |
186 case FilterOperation::SATURATE: | |
187 case FilterOperation::BRIGHTNESS: | |
188 case FilterOperation::CONTRAST: | |
189 case FilterOperation::BLUR: | |
190 case FilterOperation::DROP_SHADOW: | |
191 return std::max(amount, 0.f); | |
192 case FilterOperation::ZOOM: | |
193 return std::max(amount, 1.f); | |
194 case FilterOperation::HUE_ROTATE: | |
195 case FilterOperation::SATURATING_BRIGHTNESS: | |
196 return amount; | |
197 case FilterOperation::COLOR_MATRIX: | |
198 case FilterOperation::REFERENCE: | |
199 NOTREACHED(); | |
200 return amount; | |
201 } | |
202 NOTREACHED(); | |
203 return amount; | |
204 } | |
205 | |
206 // static | |
207 FilterOperation FilterOperation::Blend(const FilterOperation* from, | |
208 const FilterOperation* to, | |
209 double progress) { | |
210 FilterOperation blended_filter = FilterOperation::CreateEmptyFilter(); | |
211 | |
212 if (!from && !to) | |
213 return blended_filter; | |
214 | |
215 const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type()); | |
216 const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type()); | |
217 | |
218 if (from_op.type() != to_op.type()) | |
219 return blended_filter; | |
220 | |
221 DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX); | |
222 blended_filter.set_type(to_op.type()); | |
223 | |
224 if (to_op.type() == FilterOperation::REFERENCE) { | |
225 if (progress > 0.5) | |
226 blended_filter.set_image_filter(to_op.image_filter()); | |
227 else | |
228 blended_filter.set_image_filter(from_op.image_filter()); | |
229 return blended_filter; | |
230 } | |
231 | |
232 blended_filter.set_amount(ClampAmountForFilterType( | |
233 gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()), | |
234 to_op.type())); | |
235 | |
236 if (to_op.type() == FilterOperation::DROP_SHADOW) { | |
237 gfx::Point blended_offset( | |
238 gfx::Tween::LinearIntValueBetween(progress, | |
239 from_op.drop_shadow_offset().x(), | |
240 to_op.drop_shadow_offset().x()), | |
241 gfx::Tween::LinearIntValueBetween(progress, | |
242 from_op.drop_shadow_offset().y(), | |
243 to_op.drop_shadow_offset().y())); | |
244 blended_filter.set_drop_shadow_offset(blended_offset); | |
245 blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( | |
246 progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); | |
247 } else if (to_op.type() == FilterOperation::ZOOM) { | |
248 blended_filter.set_zoom_inset( | |
249 std::max(gfx::Tween::LinearIntValueBetween( | |
250 progress, from_op.zoom_inset(), to_op.zoom_inset()), | |
251 0)); | |
252 } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) { | |
253 blended_filter.set_outer_threshold(ClampAmountForFilterType( | |
254 gfx::Tween::FloatValueBetween(progress, | |
255 from_op.outer_threshold(), | |
256 to_op.outer_threshold()), | |
257 to_op.type())); | |
258 blended_filter.set_region(to_op.region()); | |
259 } | |
260 | |
261 return blended_filter; | |
262 } | |
263 | |
264 void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const { | |
265 value->SetInteger("type", type_); | |
266 switch (type_) { | |
267 case FilterOperation::GRAYSCALE: | |
268 case FilterOperation::SEPIA: | |
269 case FilterOperation::SATURATE: | |
270 case FilterOperation::HUE_ROTATE: | |
271 case FilterOperation::INVERT: | |
272 case FilterOperation::BRIGHTNESS: | |
273 case FilterOperation::CONTRAST: | |
274 case FilterOperation::OPACITY: | |
275 case FilterOperation::BLUR: | |
276 case FilterOperation::SATURATING_BRIGHTNESS: | |
277 value->SetDouble("amount", amount_); | |
278 break; | |
279 case FilterOperation::DROP_SHADOW: | |
280 value->SetDouble("std_deviation", amount_); | |
281 MathUtil::AddToTracedValue("offset", drop_shadow_offset_, value); | |
282 value->SetInteger("color", drop_shadow_color_); | |
283 break; | |
284 case FilterOperation::COLOR_MATRIX: { | |
285 value->BeginArray("matrix"); | |
286 for (size_t i = 0; i < arraysize(matrix_); ++i) | |
287 value->AppendDouble(matrix_[i]); | |
288 value->EndArray(); | |
289 break; | |
290 } | |
291 case FilterOperation::ZOOM: | |
292 value->SetDouble("amount", amount_); | |
293 value->SetDouble("inset", zoom_inset_); | |
294 break; | |
295 case FilterOperation::REFERENCE: { | |
296 int count_inputs = 0; | |
297 if (image_filter_) { | |
298 count_inputs = image_filter_->countInputs(); | |
299 } | |
300 value->SetBoolean("is_null", !image_filter_); | |
301 value->SetInteger("count_inputs", count_inputs); | |
302 break; | |
303 } | |
304 case FilterOperation::ALPHA_THRESHOLD: { | |
305 value->SetDouble("inner_threshold", amount_); | |
306 value->SetDouble("outer_threshold", outer_threshold_); | |
307 std::unique_ptr<base::ListValue> region_value(new base::ListValue()); | |
308 value->BeginArray("region"); | |
309 for (SkRegion::Iterator it(region_); !it.done(); it.next()) { | |
310 value->AppendInteger(it.rect().x()); | |
311 value->AppendInteger(it.rect().y()); | |
312 value->AppendInteger(it.rect().width()); | |
313 value->AppendInteger(it.rect().height()); | |
314 } | |
315 value->EndArray(); | |
316 } | |
317 break; | |
318 } | |
319 } | |
320 | |
321 namespace { | |
322 | |
323 SkVector MapStdDeviation(float std_deviation, const SkMatrix& matrix) { | |
324 // Corresponds to SpreadForStdDeviation in filter_operations.cc. | |
325 SkVector sigma = SkVector::Make(std_deviation, std_deviation); | |
326 matrix.mapVectors(&sigma, 1); | |
327 return sigma * SkIntToScalar(3); | |
328 } | |
329 | |
330 gfx::Rect MapRectInternal(const FilterOperation& op, | |
331 const gfx::Rect& rect, | |
332 const SkMatrix& matrix, | |
333 SkImageFilter::MapDirection direction) { | |
334 switch (op.type()) { | |
335 case FilterOperation::BLUR: { | |
336 SkVector spread = MapStdDeviation(op.amount(), matrix); | |
337 float spread_x = std::abs(spread.x()); | |
338 float spread_y = std::abs(spread.y()); | |
339 gfx::RectF result(rect); | |
340 result.Inset(-spread_x, -spread_y, -spread_x, -spread_y); | |
341 return gfx::ToEnclosingRect(result); | |
342 } | |
343 case FilterOperation::DROP_SHADOW: { | |
344 SkVector spread = MapStdDeviation(op.amount(), matrix); | |
345 float spread_x = std::abs(spread.x()); | |
346 float spread_y = std::abs(spread.y()); | |
347 gfx::RectF result(rect); | |
348 result.Inset(-spread_x, -spread_y, -spread_x, -spread_y); | |
349 | |
350 gfx::Point drop_shadow_offset = op.drop_shadow_offset(); | |
351 SkVector mapped_drop_shadow_offset; | |
352 matrix.mapVector(drop_shadow_offset.x(), drop_shadow_offset.y(), | |
353 &mapped_drop_shadow_offset); | |
354 if (direction == SkImageFilter::kReverse_MapDirection) | |
355 mapped_drop_shadow_offset = -mapped_drop_shadow_offset; | |
356 result += gfx::Vector2dF(mapped_drop_shadow_offset.x(), | |
357 mapped_drop_shadow_offset.y()); | |
358 result.Union(gfx::RectF(rect)); | |
359 return gfx::ToEnclosingRect(result); | |
360 } | |
361 case FilterOperation::REFERENCE: { | |
362 if (!op.image_filter()) | |
363 return rect; | |
364 return gfx::SkIRectToRect(op.image_filter()->filterBounds( | |
365 gfx::RectToSkIRect(rect), matrix, direction)); | |
366 } | |
367 default: | |
368 return rect; | |
369 } | |
370 } | |
371 | |
372 } // namespace | |
373 | |
374 gfx::Rect FilterOperation::MapRect(const gfx::Rect& rect, | |
375 const SkMatrix& matrix) const { | |
376 return MapRectInternal(*this, rect, matrix, | |
377 SkImageFilter::kForward_MapDirection); | |
378 } | |
379 | |
380 gfx::Rect FilterOperation::MapRectReverse(const gfx::Rect& rect, | |
381 const SkMatrix& matrix) const { | |
382 return MapRectInternal(*this, rect, matrix, | |
383 SkImageFilter::kReverse_MapDirection); | |
384 } | |
385 | |
386 } // namespace cc | |
OLD | NEW |