OLD | NEW |
| (Empty) |
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 "cc/output/filter_operations.h" | |
6 | |
7 #include <cmath> | |
8 | |
9 #include "base/trace_event/trace_event_argument.h" | |
10 #include "base/values.h" | |
11 #include "cc/output/filter_operation.h" | |
12 | |
13 namespace cc { | |
14 | |
15 FilterOperations::FilterOperations() {} | |
16 | |
17 FilterOperations::FilterOperations(const FilterOperations& other) | |
18 : operations_(other.operations_) {} | |
19 | |
20 FilterOperations::~FilterOperations() {} | |
21 | |
22 FilterOperations& FilterOperations::operator=(const FilterOperations& other) { | |
23 operations_ = other.operations_; | |
24 return *this; | |
25 } | |
26 | |
27 bool FilterOperations::operator==(const FilterOperations& other) const { | |
28 if (other.size() != size()) | |
29 return false; | |
30 for (size_t i = 0; i < size(); ++i) { | |
31 if (other.at(i) != at(i)) | |
32 return false; | |
33 } | |
34 return true; | |
35 } | |
36 | |
37 void FilterOperations::Append(const FilterOperation& filter) { | |
38 operations_.push_back(filter); | |
39 } | |
40 | |
41 void FilterOperations::Clear() { | |
42 operations_.clear(); | |
43 } | |
44 | |
45 bool FilterOperations::IsEmpty() const { | |
46 return operations_.empty(); | |
47 } | |
48 | |
49 static int SpreadForStdDeviation(float std_deviation) { | |
50 // https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#feGaussianBlurE
lement | |
51 // provides this approximation for evaluating a gaussian blur by a triple box | |
52 // filter. | |
53 float d = floorf(std_deviation * 3.f * sqrt(8.f * atan(1.f)) / 4.f + 0.5f); | |
54 return static_cast<int>(ceilf(d * 3.f / 2.f)); | |
55 } | |
56 | |
57 void FilterOperations::GetOutsets(int* top, | |
58 int* right, | |
59 int* bottom, | |
60 int* left) const { | |
61 *top = *right = *bottom = *left = 0; | |
62 for (size_t i = 0; i < operations_.size(); ++i) { | |
63 const FilterOperation& op = operations_[i]; | |
64 // TODO(ajuma): Add support for reference filters once SkImageFilter | |
65 // reports its outsets. | |
66 DCHECK(op.type() != FilterOperation::REFERENCE); | |
67 if (op.type() == FilterOperation::BLUR || | |
68 op.type() == FilterOperation::DROP_SHADOW) { | |
69 int spread = SpreadForStdDeviation(op.amount()); | |
70 if (op.type() == FilterOperation::BLUR) { | |
71 *top += spread; | |
72 *right += spread; | |
73 *bottom += spread; | |
74 *left += spread; | |
75 } else { | |
76 *top += spread - op.drop_shadow_offset().y(); | |
77 *right += spread + op.drop_shadow_offset().x(); | |
78 *bottom += spread + op.drop_shadow_offset().y(); | |
79 *left += spread - op.drop_shadow_offset().x(); | |
80 } | |
81 } | |
82 } | |
83 } | |
84 | |
85 bool FilterOperations::HasFilterThatMovesPixels() const { | |
86 for (size_t i = 0; i < operations_.size(); ++i) { | |
87 const FilterOperation& op = operations_[i]; | |
88 // TODO(ajuma): Once SkImageFilter reports its outsets, use those here to | |
89 // determine whether a reference filter really moves pixels. | |
90 switch (op.type()) { | |
91 case FilterOperation::BLUR: | |
92 case FilterOperation::DROP_SHADOW: | |
93 case FilterOperation::ZOOM: | |
94 case FilterOperation::REFERENCE: | |
95 return true; | |
96 case FilterOperation::OPACITY: | |
97 case FilterOperation::COLOR_MATRIX: | |
98 case FilterOperation::GRAYSCALE: | |
99 case FilterOperation::SEPIA: | |
100 case FilterOperation::SATURATE: | |
101 case FilterOperation::HUE_ROTATE: | |
102 case FilterOperation::INVERT: | |
103 case FilterOperation::BRIGHTNESS: | |
104 case FilterOperation::CONTRAST: | |
105 case FilterOperation::SATURATING_BRIGHTNESS: | |
106 case FilterOperation::ALPHA_THRESHOLD: | |
107 break; | |
108 } | |
109 } | |
110 return false; | |
111 } | |
112 | |
113 bool FilterOperations::HasFilterThatAffectsOpacity() const { | |
114 for (size_t i = 0; i < operations_.size(); ++i) { | |
115 const FilterOperation& op = operations_[i]; | |
116 // TODO(ajuma): Make this smarter for reference filters. Once SkImageFilter | |
117 // can report affectsOpacity(), call that. | |
118 switch (op.type()) { | |
119 case FilterOperation::OPACITY: | |
120 case FilterOperation::BLUR: | |
121 case FilterOperation::DROP_SHADOW: | |
122 case FilterOperation::ZOOM: | |
123 case FilterOperation::REFERENCE: | |
124 case FilterOperation::ALPHA_THRESHOLD: | |
125 return true; | |
126 case FilterOperation::COLOR_MATRIX: { | |
127 const SkScalar* matrix = op.matrix(); | |
128 if (matrix[15] || | |
129 matrix[16] || | |
130 matrix[17] || | |
131 matrix[18] != 1 || | |
132 matrix[19]) | |
133 return true; | |
134 break; | |
135 } | |
136 case FilterOperation::GRAYSCALE: | |
137 case FilterOperation::SEPIA: | |
138 case FilterOperation::SATURATE: | |
139 case FilterOperation::HUE_ROTATE: | |
140 case FilterOperation::INVERT: | |
141 case FilterOperation::BRIGHTNESS: | |
142 case FilterOperation::CONTRAST: | |
143 case FilterOperation::SATURATING_BRIGHTNESS: | |
144 break; | |
145 } | |
146 } | |
147 return false; | |
148 } | |
149 | |
150 bool FilterOperations::HasReferenceFilter() const { | |
151 for (size_t i = 0; i < operations_.size(); ++i) { | |
152 if (operations_[i].type() == FilterOperation::REFERENCE) | |
153 return true; | |
154 } | |
155 return false; | |
156 } | |
157 | |
158 FilterOperations FilterOperations::Blend(const FilterOperations& from, | |
159 double progress) const { | |
160 if (HasReferenceFilter() || from.HasReferenceFilter()) | |
161 return *this; | |
162 | |
163 bool from_is_longer = from.size() > size(); | |
164 | |
165 size_t shorter_size, longer_size; | |
166 if (size() == from.size()) { | |
167 shorter_size = longer_size = size(); | |
168 } else if (from_is_longer) { | |
169 longer_size = from.size(); | |
170 shorter_size = size(); | |
171 } else { | |
172 longer_size = size(); | |
173 shorter_size = from.size(); | |
174 } | |
175 | |
176 for (size_t i = 0; i < shorter_size; i++) { | |
177 if (from.at(i).type() != at(i).type()) | |
178 return *this; | |
179 } | |
180 | |
181 FilterOperations blended_filters; | |
182 for (size_t i = 0; i < shorter_size; i++) { | |
183 blended_filters.Append( | |
184 FilterOperation::Blend(&from.at(i), &at(i), progress)); | |
185 } | |
186 | |
187 if (from_is_longer) { | |
188 for (size_t i = shorter_size; i < longer_size; i++) { | |
189 blended_filters.Append( | |
190 FilterOperation::Blend(&from.at(i), NULL, progress)); | |
191 } | |
192 } else { | |
193 for (size_t i = shorter_size; i < longer_size; i++) | |
194 blended_filters.Append(FilterOperation::Blend(NULL, &at(i), progress)); | |
195 } | |
196 | |
197 return blended_filters; | |
198 } | |
199 | |
200 void FilterOperations::AsValueInto( | |
201 base::trace_event::TracedValue* value) const { | |
202 for (size_t i = 0; i < operations_.size(); ++i) { | |
203 value->BeginDictionary(); | |
204 operations_[i].AsValueInto(value); | |
205 value->EndDictionary(); | |
206 } | |
207 } | |
208 | |
209 } // namespace cc | |
OLD | NEW |