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.
7 #include "base/values.h"
8 #include "cc/base/math_util.h"
9 #include "cc/output/filter_operation.h"
10 #include "third_party/skia/include/core/SkMath.h"
11 #include "ui/gfx/animation/tween.h"
15 bool FilterOperation::operator==(const FilterOperation
& other
) const {
16 if (type_
!= other
.type_
)
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_
;
25 if (type_
== REFERENCE
)
26 return image_filter_
.get() == other
.image_filter_
.get();
27 return amount_
== other
.amount_
;
30 FilterOperation::FilterOperation(FilterType type
, float amount
)
33 drop_shadow_offset_(0, 0),
34 drop_shadow_color_(0),
36 DCHECK_NE(type_
, DROP_SHADOW
);
37 DCHECK_NE(type_
, COLOR_MATRIX
);
38 DCHECK_NE(type_
, REFERENCE
);
39 memset(matrix_
, 0, sizeof(matrix_
));
42 FilterOperation::FilterOperation(FilterType type
,
47 amount_(stdDeviation
),
48 drop_shadow_offset_(offset
),
49 drop_shadow_color_(color
),
51 DCHECK_EQ(type_
, DROP_SHADOW
);
52 memset(matrix_
, 0, sizeof(matrix_
));
55 FilterOperation::FilterOperation(FilterType type
, SkScalar matrix
[20])
58 drop_shadow_offset_(0, 0),
59 drop_shadow_color_(0),
61 DCHECK_EQ(type_
, COLOR_MATRIX
);
62 memcpy(matrix_
, matrix
, sizeof(matrix_
));
65 FilterOperation::FilterOperation(FilterType type
, float amount
, int inset
)
68 drop_shadow_offset_(0, 0),
69 drop_shadow_color_(0),
71 DCHECK_EQ(type_
, ZOOM
);
72 memset(matrix_
, 0, sizeof(matrix_
));
75 FilterOperation::FilterOperation(
77 const skia::RefPtr
<SkImageFilter
>& image_filter
)
80 drop_shadow_offset_(0, 0),
81 drop_shadow_color_(0),
82 image_filter_(image_filter
),
84 DCHECK_EQ(type_
, REFERENCE
);
85 memset(matrix_
, 0, sizeof(matrix_
));
88 FilterOperation::FilterOperation(const FilterOperation
& other
)
90 amount_(other
.amount_
),
91 drop_shadow_offset_(other
.drop_shadow_offset_
),
92 drop_shadow_color_(other
.drop_shadow_color_
),
93 image_filter_(other
.image_filter_
),
94 zoom_inset_(other
.zoom_inset_
) {
95 memcpy(matrix_
, other
.matrix_
, sizeof(matrix_
));
98 FilterOperation::~FilterOperation() {
101 static FilterOperation
CreateNoOpFilter(FilterOperation::FilterType type
) {
103 case FilterOperation::GRAYSCALE
:
104 return FilterOperation::CreateGrayscaleFilter(0.f
);
105 case FilterOperation::SEPIA
:
106 return FilterOperation::CreateSepiaFilter(0.f
);
107 case FilterOperation::SATURATE
:
108 return FilterOperation::CreateSaturateFilter(1.f
);
109 case FilterOperation::HUE_ROTATE
:
110 return FilterOperation::CreateHueRotateFilter(0.f
);
111 case FilterOperation::INVERT
:
112 return FilterOperation::CreateInvertFilter(0.f
);
113 case FilterOperation::BRIGHTNESS
:
114 return FilterOperation::CreateBrightnessFilter(1.f
);
115 case FilterOperation::CONTRAST
:
116 return FilterOperation::CreateContrastFilter(1.f
);
117 case FilterOperation::OPACITY
:
118 return FilterOperation::CreateOpacityFilter(1.f
);
119 case FilterOperation::BLUR
:
120 return FilterOperation::CreateBlurFilter(0.f
);
121 case FilterOperation::DROP_SHADOW
:
122 return FilterOperation::CreateDropShadowFilter(
123 gfx::Point(0, 0), 0.f
, SK_ColorTRANSPARENT
);
124 case FilterOperation::COLOR_MATRIX
: {
126 memset(matrix
, 0, 20 * sizeof(SkScalar
));
127 matrix
[0] = matrix
[6] = matrix
[12] = matrix
[18] = 1.f
;
128 return FilterOperation::CreateColorMatrixFilter(matrix
);
130 case FilterOperation::ZOOM
:
131 return FilterOperation::CreateZoomFilter(1.f
, 0);
132 case FilterOperation::SATURATING_BRIGHTNESS
:
133 return FilterOperation::CreateSaturatingBrightnessFilter(0.f
);
134 case FilterOperation::REFERENCE
:
135 return FilterOperation::CreateReferenceFilter(
136 skia::RefPtr
<SkImageFilter
>());
139 return FilterOperation::CreateEmptyFilter();
142 static float ClampAmountForFilterType(float amount
,
143 FilterOperation::FilterType type
) {
145 case FilterOperation::GRAYSCALE
:
146 case FilterOperation::SEPIA
:
147 case FilterOperation::INVERT
:
148 case FilterOperation::OPACITY
:
149 return MathUtil::ClampToRange(amount
, 0.f
, 1.f
);
150 case FilterOperation::SATURATE
:
151 case FilterOperation::BRIGHTNESS
:
152 case FilterOperation::CONTRAST
:
153 case FilterOperation::BLUR
:
154 case FilterOperation::DROP_SHADOW
:
155 return std::max(amount
, 0.f
);
156 case FilterOperation::ZOOM
:
157 return std::max(amount
, 1.f
);
158 case FilterOperation::HUE_ROTATE
:
159 case FilterOperation::SATURATING_BRIGHTNESS
:
161 case FilterOperation::COLOR_MATRIX
:
162 case FilterOperation::REFERENCE
:
171 FilterOperation
FilterOperation::Blend(const FilterOperation
* from
,
172 const FilterOperation
* to
,
174 FilterOperation blended_filter
= FilterOperation::CreateEmptyFilter();
177 return blended_filter
;
179 const FilterOperation
& from_op
= from
? *from
: CreateNoOpFilter(to
->type());
180 const FilterOperation
& to_op
= to
? *to
: CreateNoOpFilter(from
->type());
182 if (from_op
.type() != to_op
.type())
183 return blended_filter
;
185 DCHECK(to_op
.type() != FilterOperation::COLOR_MATRIX
);
186 blended_filter
.set_type(to_op
.type());
188 if (to_op
.type() == FilterOperation::REFERENCE
) {
190 blended_filter
.set_image_filter(to_op
.image_filter());
192 blended_filter
.set_image_filter(from_op
.image_filter());
193 return blended_filter
;
196 blended_filter
.set_amount(ClampAmountForFilterType(
197 gfx::Tween::FloatValueBetween(progress
, from_op
.amount(), to_op
.amount()),
200 if (to_op
.type() == FilterOperation::DROP_SHADOW
) {
201 gfx::Point
blended_offset(
202 gfx::Tween::LinearIntValueBetween(progress
,
203 from_op
.drop_shadow_offset().x(),
204 to_op
.drop_shadow_offset().x()),
205 gfx::Tween::LinearIntValueBetween(progress
,
206 from_op
.drop_shadow_offset().y(),
207 to_op
.drop_shadow_offset().y()));
208 blended_filter
.set_drop_shadow_offset(blended_offset
);
209 blended_filter
.set_drop_shadow_color(gfx::Tween::ColorValueBetween(
210 progress
, from_op
.drop_shadow_color(), to_op
.drop_shadow_color()));
211 } else if (to_op
.type() == FilterOperation::ZOOM
) {
212 blended_filter
.set_zoom_inset(
213 std::max(gfx::Tween::LinearIntValueBetween(
214 from_op
.zoom_inset(), to_op
.zoom_inset(), progress
),
218 return blended_filter
;
221 scoped_ptr
<base::Value
> FilterOperation::AsValue() const {
222 scoped_ptr
<base::DictionaryValue
> value(new base::DictionaryValue
);
223 value
->SetInteger("type", type_
);
225 case FilterOperation::GRAYSCALE
:
226 case FilterOperation::SEPIA
:
227 case FilterOperation::SATURATE
:
228 case FilterOperation::HUE_ROTATE
:
229 case FilterOperation::INVERT
:
230 case FilterOperation::BRIGHTNESS
:
231 case FilterOperation::CONTRAST
:
232 case FilterOperation::OPACITY
:
233 case FilterOperation::BLUR
:
234 case FilterOperation::SATURATING_BRIGHTNESS
:
235 value
->SetDouble("amount", amount_
);
237 case FilterOperation::DROP_SHADOW
:
238 value
->SetDouble("std_deviation", amount_
);
239 value
->Set("offset", MathUtil::AsValue(drop_shadow_offset_
).release());
240 value
->SetInteger("color", drop_shadow_color_
);
242 case FilterOperation::COLOR_MATRIX
: {
243 scoped_ptr
<base::ListValue
> matrix(new base::ListValue
);
244 for (size_t i
= 0; i
< arraysize(matrix_
); ++i
)
245 matrix
->AppendDouble(matrix_
[i
]);
246 value
->Set("matrix", matrix
.release());
249 case FilterOperation::ZOOM
:
250 value
->SetDouble("amount", amount_
);
251 value
->SetDouble("inset", zoom_inset_
);
253 case FilterOperation::REFERENCE
: {
254 int count_inputs
= 0;
255 bool can_filter_image_gpu
= false;
257 count_inputs
= image_filter_
->countInputs();
258 can_filter_image_gpu
= image_filter_
->canFilterImageGPU();
260 value
->SetBoolean("is_null", !image_filter_
);
261 value
->SetInteger("count_inputs", count_inputs
);
262 value
->SetBoolean("can_filter_image_gpu", can_filter_image_gpu
);
266 return value
.PassAs
<base::Value
>();