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"
14 bool FilterOperation::operator==(const FilterOperation
& other
) const {
15 if (type_
!= other
.type_
)
17 if (type_
== COLOR_MATRIX
)
18 return !memcmp(matrix_
, other
.matrix_
, sizeof(matrix_
));
19 if (type_
== DROP_SHADOW
) {
20 return amount_
== other
.amount_
&&
21 drop_shadow_offset_
== other
.drop_shadow_offset_
&&
22 drop_shadow_color_
== other
.drop_shadow_color_
;
24 return amount_
== other
.amount_
;
27 FilterOperation::FilterOperation(FilterType type
, float amount
)
30 drop_shadow_offset_(0, 0),
31 drop_shadow_color_(0),
33 DCHECK_NE(type_
, DROP_SHADOW
);
34 DCHECK_NE(type_
, COLOR_MATRIX
);
35 memset(matrix_
, 0, sizeof(matrix_
));
38 FilterOperation::FilterOperation(FilterType type
,
43 amount_(stdDeviation
),
44 drop_shadow_offset_(offset
),
45 drop_shadow_color_(color
),
47 DCHECK_EQ(type_
, DROP_SHADOW
);
48 memset(matrix_
, 0, sizeof(matrix_
));
51 FilterOperation::FilterOperation(FilterType type
, SkScalar matrix
[20])
54 drop_shadow_offset_(0, 0),
55 drop_shadow_color_(0),
57 DCHECK_EQ(type_
, COLOR_MATRIX
);
58 memcpy(matrix_
, matrix
, sizeof(matrix_
));
61 FilterOperation::FilterOperation(FilterType type
, float amount
, int inset
)
64 drop_shadow_offset_(0, 0),
65 drop_shadow_color_(0),
67 DCHECK_EQ(type_
, ZOOM
);
68 memset(matrix_
, 0, sizeof(matrix_
));
71 // TODO(ajuma): Define a version of ui::Tween::ValueBetween for floats, and use
73 static float BlendFloats(float from
, float to
, double progress
) {
74 return from
* (1.0 - progress
) + to
* progress
;
77 static int BlendInts(int from
, int to
, double progress
) {
78 return static_cast<int>(
79 MathUtil::Round(from
* (1.0 - progress
) + to
* progress
));
82 static uint8_t BlendColorComponents(uint8_t from
,
86 uint8_t blended_alpha
,
88 // Since progress can be outside [0, 1], blending can produce a value outside
90 int blended_premultiplied
= BlendInts(SkMulDiv255Round(from
, from_alpha
),
91 SkMulDiv255Round(to
, to_alpha
),
93 int blended
= static_cast<int>(
94 MathUtil::Round(blended_premultiplied
* 255.f
/ blended_alpha
));
95 return static_cast<uint8_t>(MathUtil::ClampToRange(blended
, 0, 255));
98 static SkColor
BlendSkColors(SkColor from
, SkColor to
, double progress
) {
99 int from_a
= SkColorGetA(from
);
100 int to_a
= SkColorGetA(to
);
101 int blended_a
= BlendInts(from_a
, to_a
, progress
);
103 return SkColorSetARGB(0, 0, 0, 0);
104 blended_a
= std::min(blended_a
, 255);
106 // TODO(ajuma): Use SkFourByteInterp once http://crbug.com/260369 is fixed.
107 uint8_t blended_r
= BlendColorComponents(
108 SkColorGetR(from
), SkColorGetR(to
), from_a
, to_a
, blended_a
, progress
);
109 uint8_t blended_g
= BlendColorComponents(
110 SkColorGetG(from
), SkColorGetG(to
), from_a
, to_a
, blended_a
, progress
);
111 uint8_t blended_b
= BlendColorComponents(
112 SkColorGetB(from
), SkColorGetB(to
), from_a
, to_a
, blended_a
, progress
);
114 return SkColorSetARGB(blended_a
, blended_r
, blended_g
, blended_b
);
117 static FilterOperation
CreateNoOpFilter(FilterOperation::FilterType type
) {
119 case FilterOperation::GRAYSCALE
:
120 return FilterOperation::CreateGrayscaleFilter(0.f
);
121 case FilterOperation::SEPIA
:
122 return FilterOperation::CreateSepiaFilter(0.f
);
123 case FilterOperation::SATURATE
:
124 return FilterOperation::CreateSaturateFilter(1.f
);
125 case FilterOperation::HUE_ROTATE
:
126 return FilterOperation::CreateHueRotateFilter(0.f
);
127 case FilterOperation::INVERT
:
128 return FilterOperation::CreateInvertFilter(0.f
);
129 case FilterOperation::BRIGHTNESS
:
130 return FilterOperation::CreateBrightnessFilter(1.f
);
131 case FilterOperation::CONTRAST
:
132 return FilterOperation::CreateContrastFilter(1.f
);
133 case FilterOperation::OPACITY
:
134 return FilterOperation::CreateOpacityFilter(1.f
);
135 case FilterOperation::BLUR
:
136 return FilterOperation::CreateBlurFilter(0.f
);
137 case FilterOperation::DROP_SHADOW
:
138 return FilterOperation::CreateDropShadowFilter(
139 gfx::Point(0, 0), 0.f
, SK_ColorTRANSPARENT
);
140 case FilterOperation::COLOR_MATRIX
: {
142 memset(matrix
, 0, 20 * sizeof(SkScalar
));
143 matrix
[0] = matrix
[6] = matrix
[12] = matrix
[18] = 1.f
;
144 return FilterOperation::CreateColorMatrixFilter(matrix
);
146 case FilterOperation::ZOOM
:
147 return FilterOperation::CreateZoomFilter(1.f
, 0);
148 case FilterOperation::SATURATING_BRIGHTNESS
:
149 return FilterOperation::CreateSaturatingBrightnessFilter(0.f
);
152 return FilterOperation::CreateEmptyFilter();
155 static float ClampAmountForFilterType(float amount
,
156 FilterOperation::FilterType type
) {
158 case FilterOperation::GRAYSCALE
:
159 case FilterOperation::SEPIA
:
160 case FilterOperation::INVERT
:
161 case FilterOperation::OPACITY
:
162 return MathUtil::ClampToRange(amount
, 0.f
, 1.f
);
163 case FilterOperation::SATURATE
:
164 case FilterOperation::BRIGHTNESS
:
165 case FilterOperation::CONTRAST
:
166 case FilterOperation::BLUR
:
167 case FilterOperation::DROP_SHADOW
:
168 return std::max(amount
, 0.f
);
169 case FilterOperation::ZOOM
:
170 return std::max(amount
, 1.f
);
171 case FilterOperation::HUE_ROTATE
:
172 case FilterOperation::SATURATING_BRIGHTNESS
:
174 case FilterOperation::COLOR_MATRIX
:
183 FilterOperation
FilterOperation::Blend(const FilterOperation
* from
,
184 const FilterOperation
* to
,
186 FilterOperation blended_filter
= FilterOperation::CreateEmptyFilter();
189 return blended_filter
;
191 const FilterOperation
& from_op
= from
? *from
: CreateNoOpFilter(to
->type());
192 const FilterOperation
& to_op
= to
? *to
: CreateNoOpFilter(from
->type());
194 if (from_op
.type() != to_op
.type())
195 return blended_filter
;
197 DCHECK(to_op
.type() != FilterOperation::COLOR_MATRIX
);
198 blended_filter
.set_type(to_op
.type());
200 blended_filter
.set_amount(ClampAmountForFilterType(
201 BlendFloats(from_op
.amount(), to_op
.amount(), progress
), to_op
.type()));
203 if (to_op
.type() == FilterOperation::DROP_SHADOW
) {
204 gfx::Point
blended_offset(BlendInts(from_op
.drop_shadow_offset().x(),
205 to_op
.drop_shadow_offset().x(),
207 BlendInts(from_op
.drop_shadow_offset().y(),
208 to_op
.drop_shadow_offset().y(),
210 blended_filter
.set_drop_shadow_offset(blended_offset
);
211 blended_filter
.set_drop_shadow_color(BlendSkColors(
212 from_op
.drop_shadow_color(), to_op
.drop_shadow_color(), progress
));
213 } else if (to_op
.type() == FilterOperation::ZOOM
) {
214 blended_filter
.set_zoom_inset(std::max(
215 BlendInts(from_op
.zoom_inset(), to_op
.zoom_inset(), progress
), 0));
218 return blended_filter
;
221 scoped_ptr
<base::Value
> FilterOperation::AsValue() const {
222 scoped_ptr
<base::DictionaryValue
> value(new 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
<ListValue
> matrix(new 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_
);
254 return value
.PassAs
<base::Value
>();