Upstream version 11.40.277.0
[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/debug/trace_event_argument.h"
8 #include "base/values.h"
9 #include "cc/base/math_util.h"
10 #include "cc/output/filter_operation.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   if (type_ == ALPHA_THRESHOLD) {
28     return region_ == other.region_ &&
29         amount_ == other.amount_ &&
30         outer_threshold_ == other.outer_threshold_;
31   }
32   return amount_ == other.amount_;
33 }
34
35 FilterOperation::FilterOperation(FilterType type, float amount)
36     : type_(type),
37       amount_(amount),
38       outer_threshold_(0),
39       drop_shadow_offset_(0, 0),
40       drop_shadow_color_(0),
41       zoom_inset_(0) {
42   DCHECK_NE(type_, DROP_SHADOW);
43   DCHECK_NE(type_, COLOR_MATRIX);
44   DCHECK_NE(type_, REFERENCE);
45   memset(matrix_, 0, sizeof(matrix_));
46 }
47
48 FilterOperation::FilterOperation(FilterType type,
49                                  const gfx::Point& offset,
50                                  float stdDeviation,
51                                  SkColor color)
52     : type_(type),
53       amount_(stdDeviation),
54       outer_threshold_(0),
55       drop_shadow_offset_(offset),
56       drop_shadow_color_(color),
57       zoom_inset_(0) {
58   DCHECK_EQ(type_, DROP_SHADOW);
59   memset(matrix_, 0, sizeof(matrix_));
60 }
61
62 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20])
63     : type_(type),
64       amount_(0),
65       outer_threshold_(0),
66       drop_shadow_offset_(0, 0),
67       drop_shadow_color_(0),
68       zoom_inset_(0) {
69   DCHECK_EQ(type_, COLOR_MATRIX);
70   memcpy(matrix_, matrix, sizeof(matrix_));
71 }
72
73 FilterOperation::FilterOperation(FilterType type, float amount, int inset)
74     : type_(type),
75       amount_(amount),
76       outer_threshold_(0),
77       drop_shadow_offset_(0, 0),
78       drop_shadow_color_(0),
79       zoom_inset_(inset) {
80   DCHECK_EQ(type_, ZOOM);
81   memset(matrix_, 0, sizeof(matrix_));
82 }
83
84 FilterOperation::FilterOperation(
85     FilterType type,
86     const skia::RefPtr<SkImageFilter>& image_filter)
87     : type_(type),
88       amount_(0),
89       outer_threshold_(0),
90       drop_shadow_offset_(0, 0),
91       drop_shadow_color_(0),
92       image_filter_(image_filter),
93       zoom_inset_(0) {
94   DCHECK_EQ(type_, REFERENCE);
95   memset(matrix_, 0, sizeof(matrix_));
96 }
97
98 FilterOperation::FilterOperation(FilterType type,
99                                  const SkRegion& region,
100                                  float inner_threshold,
101                                  float outer_threshold)
102     : type_(type),
103       amount_(inner_threshold),
104       outer_threshold_(outer_threshold),
105       drop_shadow_offset_(0, 0),
106       drop_shadow_color_(0),
107       zoom_inset_(0),
108       region_(region) {
109   DCHECK_EQ(type_, ALPHA_THRESHOLD);
110   memset(matrix_, 0, sizeof(matrix_));
111 }
112
113 FilterOperation::FilterOperation(const FilterOperation& other)
114     : type_(other.type_),
115       amount_(other.amount_),
116       outer_threshold_(other.outer_threshold_),
117       drop_shadow_offset_(other.drop_shadow_offset_),
118       drop_shadow_color_(other.drop_shadow_color_),
119       image_filter_(other.image_filter_),
120       zoom_inset_(other.zoom_inset_),
121       region_(other.region_) {
122   memcpy(matrix_, other.matrix_, sizeof(matrix_));
123 }
124
125 FilterOperation::~FilterOperation() {
126 }
127
128 static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
129   switch (type) {
130     case FilterOperation::GRAYSCALE:
131       return FilterOperation::CreateGrayscaleFilter(0.f);
132     case FilterOperation::SEPIA:
133       return FilterOperation::CreateSepiaFilter(0.f);
134     case FilterOperation::SATURATE:
135       return FilterOperation::CreateSaturateFilter(1.f);
136     case FilterOperation::HUE_ROTATE:
137       return FilterOperation::CreateHueRotateFilter(0.f);
138     case FilterOperation::INVERT:
139       return FilterOperation::CreateInvertFilter(0.f);
140     case FilterOperation::BRIGHTNESS:
141       return FilterOperation::CreateBrightnessFilter(1.f);
142     case FilterOperation::CONTRAST:
143       return FilterOperation::CreateContrastFilter(1.f);
144     case FilterOperation::OPACITY:
145       return FilterOperation::CreateOpacityFilter(1.f);
146     case FilterOperation::BLUR:
147       return FilterOperation::CreateBlurFilter(0.f);
148     case FilterOperation::DROP_SHADOW:
149       return FilterOperation::CreateDropShadowFilter(
150           gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT);
151     case FilterOperation::COLOR_MATRIX: {
152       SkScalar matrix[20];
153       memset(matrix, 0, 20 * sizeof(SkScalar));
154       matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
155       return FilterOperation::CreateColorMatrixFilter(matrix);
156     }
157     case FilterOperation::ZOOM:
158       return FilterOperation::CreateZoomFilter(1.f, 0);
159     case FilterOperation::SATURATING_BRIGHTNESS:
160       return FilterOperation::CreateSaturatingBrightnessFilter(0.f);
161     case FilterOperation::REFERENCE:
162       return FilterOperation::CreateReferenceFilter(
163           skia::RefPtr<SkImageFilter>());
164     case FilterOperation::ALPHA_THRESHOLD:
165       return FilterOperation::CreateAlphaThresholdFilter(SkRegion(), 1.f, 0.f);
166   }
167   NOTREACHED();
168   return FilterOperation::CreateEmptyFilter();
169 }
170
171 static float ClampAmountForFilterType(float amount,
172                                       FilterOperation::FilterType type) {
173   switch (type) {
174     case FilterOperation::GRAYSCALE:
175     case FilterOperation::SEPIA:
176     case FilterOperation::INVERT:
177     case FilterOperation::OPACITY:
178     case FilterOperation::ALPHA_THRESHOLD:
179       return MathUtil::ClampToRange(amount, 0.f, 1.f);
180     case FilterOperation::SATURATE:
181     case FilterOperation::BRIGHTNESS:
182     case FilterOperation::CONTRAST:
183     case FilterOperation::BLUR:
184     case FilterOperation::DROP_SHADOW:
185       return std::max(amount, 0.f);
186     case FilterOperation::ZOOM:
187       return std::max(amount, 1.f);
188     case FilterOperation::HUE_ROTATE:
189     case FilterOperation::SATURATING_BRIGHTNESS:
190       return amount;
191     case FilterOperation::COLOR_MATRIX:
192     case FilterOperation::REFERENCE:
193       NOTREACHED();
194       return amount;
195   }
196   NOTREACHED();
197   return amount;
198 }
199
200 // static
201 FilterOperation FilterOperation::Blend(const FilterOperation* from,
202                                        const FilterOperation* to,
203                                        double progress) {
204   FilterOperation blended_filter = FilterOperation::CreateEmptyFilter();
205
206   if (!from && !to)
207     return blended_filter;
208
209   const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type());
210   const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type());
211
212   if (from_op.type() != to_op.type())
213     return blended_filter;
214
215   DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX);
216   blended_filter.set_type(to_op.type());
217
218   if (to_op.type() == FilterOperation::REFERENCE) {
219     if (progress > 0.5)
220       blended_filter.set_image_filter(to_op.image_filter());
221     else
222       blended_filter.set_image_filter(from_op.image_filter());
223     return blended_filter;
224   }
225
226   blended_filter.set_amount(ClampAmountForFilterType(
227       gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()),
228       to_op.type()));
229
230   if (to_op.type() == FilterOperation::DROP_SHADOW) {
231     gfx::Point blended_offset(
232         gfx::Tween::LinearIntValueBetween(progress,
233                                           from_op.drop_shadow_offset().x(),
234                                           to_op.drop_shadow_offset().x()),
235         gfx::Tween::LinearIntValueBetween(progress,
236                                           from_op.drop_shadow_offset().y(),
237                                           to_op.drop_shadow_offset().y()));
238     blended_filter.set_drop_shadow_offset(blended_offset);
239     blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween(
240         progress, from_op.drop_shadow_color(), to_op.drop_shadow_color()));
241   } else if (to_op.type() == FilterOperation::ZOOM) {
242     blended_filter.set_zoom_inset(
243         std::max(gfx::Tween::LinearIntValueBetween(
244                      from_op.zoom_inset(), to_op.zoom_inset(), progress),
245                  0));
246   } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) {
247     blended_filter.set_outer_threshold(ClampAmountForFilterType(
248             gfx::Tween::FloatValueBetween(progress,
249                                           from_op.outer_threshold(),
250                                           to_op.outer_threshold()),
251             to_op.type()));
252     blended_filter.set_region(to_op.region());
253   }
254
255   return blended_filter;
256 }
257
258 void FilterOperation::AsValueInto(base::debug::TracedValue* value) const {
259   value->SetInteger("type", type_);
260   switch (type_) {
261     case FilterOperation::GRAYSCALE:
262     case FilterOperation::SEPIA:
263     case FilterOperation::SATURATE:
264     case FilterOperation::HUE_ROTATE:
265     case FilterOperation::INVERT:
266     case FilterOperation::BRIGHTNESS:
267     case FilterOperation::CONTRAST:
268     case FilterOperation::OPACITY:
269     case FilterOperation::BLUR:
270     case FilterOperation::SATURATING_BRIGHTNESS:
271       value->SetDouble("amount", amount_);
272       break;
273     case FilterOperation::DROP_SHADOW:
274       value->SetDouble("std_deviation", amount_);
275       value->BeginArray("offset");
276       MathUtil::AddToTracedValue(drop_shadow_offset_, value);
277       value->EndArray();
278       value->SetInteger("color", drop_shadow_color_);
279       break;
280     case FilterOperation::COLOR_MATRIX: {
281       value->BeginArray("matrix");
282       for (size_t i = 0; i < arraysize(matrix_); ++i)
283         value->AppendDouble(matrix_[i]);
284       value->EndArray();
285       break;
286     }
287     case FilterOperation::ZOOM:
288       value->SetDouble("amount", amount_);
289       value->SetDouble("inset", zoom_inset_);
290       break;
291     case FilterOperation::REFERENCE: {
292       int count_inputs = 0;
293       bool can_filter_image_gpu = false;
294       if (image_filter_) {
295         count_inputs = image_filter_->countInputs();
296         can_filter_image_gpu = image_filter_->canFilterImageGPU();
297       }
298       value->SetBoolean("is_null", !image_filter_);
299       value->SetInteger("count_inputs", count_inputs);
300       value->SetBoolean("can_filter_image_gpu", can_filter_image_gpu);
301       break;
302     }
303     case FilterOperation::ALPHA_THRESHOLD: {
304         value->SetDouble("inner_threshold", amount_);
305         value->SetDouble("outer_threshold", outer_threshold_);
306         scoped_ptr<base::ListValue> region_value(new base::ListValue());
307         value->BeginArray("region");
308         for (SkRegion::Iterator it(region_); !it.done(); it.next()) {
309           value->AppendInteger(it.rect().x());
310           value->AppendInteger(it.rect().y());
311           value->AppendInteger(it.rect().width());
312           value->AppendInteger(it.rect().height());
313         }
314         value->EndArray();
315       }
316       break;
317   }
318 }
319
320 }  // namespace cc