Add missing OWNERS for chrome_android.gypi
[chromium-blink-merge.git] / cc / output / filter_operation.cc
blobe8a08804632c12c9ba550d6abfcb771464352b66
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.
5 #include <algorithm>
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"
12 namespace cc {
14 bool FilterOperation::operator==(const FilterOperation& other) const {
15 if (type_ != other.type_)
16 return false;
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)
28 : type_(type),
29 amount_(amount),
30 drop_shadow_offset_(0, 0),
31 drop_shadow_color_(0),
32 zoom_inset_(0) {
33 DCHECK_NE(type_, DROP_SHADOW);
34 DCHECK_NE(type_, COLOR_MATRIX);
35 memset(matrix_, 0, sizeof(matrix_));
38 FilterOperation::FilterOperation(FilterType type,
39 gfx::Point offset,
40 float stdDeviation,
41 SkColor color)
42 : type_(type),
43 amount_(stdDeviation),
44 drop_shadow_offset_(offset),
45 drop_shadow_color_(color),
46 zoom_inset_(0) {
47 DCHECK_EQ(type_, DROP_SHADOW);
48 memset(matrix_, 0, sizeof(matrix_));
51 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20])
52 : type_(type),
53 amount_(0),
54 drop_shadow_offset_(0, 0),
55 drop_shadow_color_(0),
56 zoom_inset_(0) {
57 DCHECK_EQ(type_, COLOR_MATRIX);
58 memcpy(matrix_, matrix, sizeof(matrix_));
61 FilterOperation::FilterOperation(FilterType type, float amount, int inset)
62 : type_(type),
63 amount_(amount),
64 drop_shadow_offset_(0, 0),
65 drop_shadow_color_(0),
66 zoom_inset_(inset) {
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
72 // that instead.
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,
83 uint8_t to,
84 uint8_t from_alpha,
85 uint8_t to_alpha,
86 uint8_t blended_alpha,
87 double progress) {
88 // Since progress can be outside [0, 1], blending can produce a value outside
89 // [0, 255].
90 int blended_premultiplied = BlendInts(SkMulDiv255Round(from, from_alpha),
91 SkMulDiv255Round(to, to_alpha),
92 progress);
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);
102 if (blended_a <= 0)
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) {
118 switch (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: {
141 SkScalar matrix[20];
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);
151 NOTREACHED();
152 return FilterOperation::CreateEmptyFilter();
155 static float ClampAmountForFilterType(float amount,
156 FilterOperation::FilterType type) {
157 switch (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:
173 return amount;
174 case FilterOperation::COLOR_MATRIX:
175 NOTREACHED();
176 return amount;
178 NOTREACHED();
179 return amount;
182 // static
183 FilterOperation FilterOperation::Blend(const FilterOperation* from,
184 const FilterOperation* to,
185 double progress) {
186 FilterOperation blended_filter = FilterOperation::CreateEmptyFilter();
188 if (!from && !to)
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(),
206 progress),
207 BlendInts(from_op.drop_shadow_offset().y(),
208 to_op.drop_shadow_offset().y(),
209 progress));
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_);
224 switch (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_);
236 break;
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_);
241 break;
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());
247 break;
249 case FilterOperation::ZOOM:
250 value->SetDouble("amount", amount_);
251 value->SetDouble("inset", zoom_inset_);
252 break;
254 return value.PassAs<base::Value>();
257 } // namespace cc