- add sources.
[platform/framework/web/crosswalk.git] / src / cc / output / filter_operation.cc
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/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"
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   return amount_ == other.amount_;
28 }
29
30 FilterOperation::FilterOperation(FilterType type, float amount)
31     : type_(type),
32       amount_(amount),
33       drop_shadow_offset_(0, 0),
34       drop_shadow_color_(0),
35       zoom_inset_(0) {
36   DCHECK_NE(type_, DROP_SHADOW);
37   DCHECK_NE(type_, COLOR_MATRIX);
38   DCHECK_NE(type_, REFERENCE);
39   memset(matrix_, 0, sizeof(matrix_));
40 }
41
42 FilterOperation::FilterOperation(FilterType type,
43                                  gfx::Point offset,
44                                  float stdDeviation,
45                                  SkColor color)
46     : type_(type),
47       amount_(stdDeviation),
48       drop_shadow_offset_(offset),
49       drop_shadow_color_(color),
50       zoom_inset_(0) {
51   DCHECK_EQ(type_, DROP_SHADOW);
52   memset(matrix_, 0, sizeof(matrix_));
53 }
54
55 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20])
56     : type_(type),
57       amount_(0),
58       drop_shadow_offset_(0, 0),
59       drop_shadow_color_(0),
60       zoom_inset_(0) {
61   DCHECK_EQ(type_, COLOR_MATRIX);
62   memcpy(matrix_, matrix, sizeof(matrix_));
63 }
64
65 FilterOperation::FilterOperation(FilterType type, float amount, int inset)
66     : type_(type),
67       amount_(amount),
68       drop_shadow_offset_(0, 0),
69       drop_shadow_color_(0),
70       zoom_inset_(inset) {
71   DCHECK_EQ(type_, ZOOM);
72   memset(matrix_, 0, sizeof(matrix_));
73 }
74
75 FilterOperation::FilterOperation(
76     FilterType type,
77     const skia::RefPtr<SkImageFilter>& image_filter)
78     : type_(type),
79       amount_(0),
80       drop_shadow_offset_(0, 0),
81       drop_shadow_color_(0),
82       image_filter_(image_filter),
83       zoom_inset_(0) {
84   DCHECK_EQ(type_, REFERENCE);
85   memset(matrix_, 0, sizeof(matrix_));
86 }
87
88 FilterOperation::FilterOperation(const FilterOperation& other)
89     : type_(other.type_),
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_));
96 }
97
98 FilterOperation::~FilterOperation() {
99 }
100
101 static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
102   switch (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: {
125       SkScalar matrix[20];
126       memset(matrix, 0, 20 * sizeof(SkScalar));
127       matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
128       return FilterOperation::CreateColorMatrixFilter(matrix);
129     }
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>());
137   }
138   NOTREACHED();
139   return FilterOperation::CreateEmptyFilter();
140 }
141
142 static float ClampAmountForFilterType(float amount,
143                                       FilterOperation::FilterType type) {
144   switch (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:
160       return amount;
161     case FilterOperation::COLOR_MATRIX:
162     case FilterOperation::REFERENCE:
163       NOTREACHED();
164       return amount;
165   }
166   NOTREACHED();
167   return amount;
168 }
169
170 // static
171 FilterOperation FilterOperation::Blend(const FilterOperation* from,
172                                        const FilterOperation* to,
173                                        double progress) {
174   FilterOperation blended_filter = FilterOperation::CreateEmptyFilter();
175
176   if (!from && !to)
177     return blended_filter;
178
179   const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type());
180   const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type());
181
182   if (from_op.type() != to_op.type())
183     return blended_filter;
184
185   DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX);
186   blended_filter.set_type(to_op.type());
187
188   if (to_op.type() == FilterOperation::REFERENCE) {
189     if (progress > 0.5)
190       blended_filter.set_image_filter(to_op.image_filter());
191     else
192       blended_filter.set_image_filter(from_op.image_filter());
193     return blended_filter;
194   }
195
196   blended_filter.set_amount(ClampAmountForFilterType(
197       gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()),
198       to_op.type()));
199
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),
215                  0));
216   }
217
218   return blended_filter;
219 }
220
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;
248     }
249     case FilterOperation::ZOOM:
250       value->SetDouble("amount", amount_);
251       value->SetDouble("inset", zoom_inset_);
252       break;
253     case FilterOperation::REFERENCE: {
254       int count_inputs = 0;
255       bool can_filter_image_gpu = false;
256       if (image_filter_) {
257         count_inputs = image_filter_->countInputs();
258         can_filter_image_gpu = image_filter_->canFilterImageGPU();
259       }
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);
263       break;
264     }
265   }
266   return value.PassAs<base::Value>();
267 }
268
269 }  // namespace cc