| 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 <stddef.h> | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/trace_event/trace_event_argument.h" | |
| 10 #include "base/values.h" | |
| 11 #include "cc/base/math_util.h" | |
| 12 #include "cc/output/filter_operation.h" | |
| 13 #include "ui/gfx/animation/tween.h" | |
| 14 #include "ui/gfx/geometry/rect.h" | |
| 15 #include "ui/gfx/geometry/rect_conversions.h" | |
| 16 #include "ui/gfx/skia_util.h" | |
| 17 | |
| 18 namespace cc { | |
| 19 | |
| 20 bool FilterOperation::operator==(const FilterOperation& other) const { | |
| 21 if (type_ != other.type_) | |
| 22 return false; | |
| 23 if (type_ == COLOR_MATRIX) | |
| 24 return !memcmp(matrix_, other.matrix_, sizeof(matrix_)); | |
| 25 if (type_ == DROP_SHADOW) { | |
| 26 return amount_ == other.amount_ && | |
| 27 drop_shadow_offset_ == other.drop_shadow_offset_ && | |
| 28 drop_shadow_color_ == other.drop_shadow_color_; | |
| 29 } | |
| 30 if (type_ == REFERENCE) { | |
| 31 return image_filter_.get() == other.image_filter_.get(); | |
| 32 } | |
| 33 if (type_ == ALPHA_THRESHOLD) { | |
| 34 return region_ == other.region_ && | |
| 35 amount_ == other.amount_ && | |
| 36 outer_threshold_ == other.outer_threshold_; | |
| 37 } | |
| 38 return amount_ == other.amount_; | |
| 39 } | |
| 40 | |
| 41 FilterOperation::FilterOperation() : FilterOperation(GRAYSCALE, 0.f) {} | |
| 42 | |
| 43 FilterOperation::FilterOperation(FilterType type, float amount) | |
| 44 : type_(type), | |
| 45 amount_(amount), | |
| 46 outer_threshold_(0), | |
| 47 drop_shadow_offset_(0, 0), | |
| 48 drop_shadow_color_(0), | |
| 49 zoom_inset_(0) { | |
| 50 DCHECK_NE(type_, DROP_SHADOW); | |
| 51 DCHECK_NE(type_, COLOR_MATRIX); | |
| 52 DCHECK_NE(type_, REFERENCE); | |
| 53 memset(matrix_, 0, sizeof(matrix_)); | |
| 54 } | |
| 55 | |
| 56 FilterOperation::FilterOperation(FilterType type, | |
| 57 const gfx::Point& offset, | |
| 58 float stdDeviation, | |
| 59 SkColor color) | |
| 60 : type_(type), | |
| 61 amount_(stdDeviation), | |
| 62 outer_threshold_(0), | |
| 63 drop_shadow_offset_(offset), | |
| 64 drop_shadow_color_(color), | |
| 65 zoom_inset_(0) { | |
| 66 DCHECK_EQ(type_, DROP_SHADOW); | |
| 67 memset(matrix_, 0, sizeof(matrix_)); | |
| 68 } | |
| 69 | |
| 70 FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20]) | |
| 71 : type_(type), | |
| 72 amount_(0), | |
| 73 outer_threshold_(0), | |
| 74 drop_shadow_offset_(0, 0), | |
| 75 drop_shadow_color_(0), | |
| 76 zoom_inset_(0) { | |
| 77 DCHECK_EQ(type_, COLOR_MATRIX); | |
| 78 memcpy(matrix_, matrix, sizeof(matrix_)); | |
| 79 } | |
| 80 | |
| 81 FilterOperation::FilterOperation(FilterType type, float amount, int inset) | |
| 82 : type_(type), | |
| 83 amount_(amount), | |
| 84 outer_threshold_(0), | |
| 85 drop_shadow_offset_(0, 0), | |
| 86 drop_shadow_color_(0), | |
| 87 zoom_inset_(inset) { | |
| 88 DCHECK_EQ(type_, ZOOM); | |
| 89 memset(matrix_, 0, sizeof(matrix_)); | |
| 90 } | |
| 91 | |
| 92 FilterOperation::FilterOperation(FilterType type, | |
| 93 sk_sp<SkImageFilter> image_filter) | |
| 94 : type_(type), | |
| 95 amount_(0), | |
| 96 outer_threshold_(0), | |
| 97 drop_shadow_offset_(0, 0), | |
| 98 drop_shadow_color_(0), | |
| 99 image_filter_(std::move(image_filter)), | |
| 100 zoom_inset_(0) { | |
| 101 DCHECK_EQ(type_, REFERENCE); | |
| 102 memset(matrix_, 0, sizeof(matrix_)); | |
| 103 } | |
| 104 | |
| 105 FilterOperation::FilterOperation(FilterType type, | |
| 106 const SkRegion& region, | |
| 107 float inner_threshold, | |
| 108 float outer_threshold) | |
| 109 : type_(type), | |
| 110 amount_(inner_threshold), | |
| 111 outer_threshold_(outer_threshold), | |
| 112 drop_shadow_offset_(0, 0), | |
| 113 drop_shadow_color_(0), | |
| 114 zoom_inset_(0), | |
| 115 region_(region) { | |
| 116 DCHECK_EQ(type_, ALPHA_THRESHOLD); | |
| 117 memset(matrix_, 0, sizeof(matrix_)); | |
| 118 } | |
| 119 | |
| 120 FilterOperation::FilterOperation(const FilterOperation& other) | |
| 121 : type_(other.type_), | |
| 122 amount_(other.amount_), | |
| 123 outer_threshold_(other.outer_threshold_), | |
| 124 drop_shadow_offset_(other.drop_shadow_offset_), | |
| 125 drop_shadow_color_(other.drop_shadow_color_), | |
| 126 image_filter_(other.image_filter_), | |
| 127 zoom_inset_(other.zoom_inset_), | |
| 128 region_(other.region_) { | |
| 129 memcpy(matrix_, other.matrix_, sizeof(matrix_)); | |
| 130 } | |
| 131 | |
| 132 FilterOperation::~FilterOperation() { | |
| 133 } | |
| 134 | |
| 135 static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { | |
| 136 switch (type) { | |
| 137 case FilterOperation::GRAYSCALE: | |
| 138 return FilterOperation::CreateGrayscaleFilter(0.f); | |
| 139 case FilterOperation::SEPIA: | |
| 140 return FilterOperation::CreateSepiaFilter(0.f); | |
| 141 case FilterOperation::SATURATE: | |
| 142 return FilterOperation::CreateSaturateFilter(1.f); | |
| 143 case FilterOperation::HUE_ROTATE: | |
| 144 return FilterOperation::CreateHueRotateFilter(0.f); | |
| 145 case FilterOperation::INVERT: | |
| 146 return FilterOperation::CreateInvertFilter(0.f); | |
| 147 case FilterOperation::BRIGHTNESS: | |
| 148 return FilterOperation::CreateBrightnessFilter(1.f); | |
| 149 case FilterOperation::CONTRAST: | |
| 150 return FilterOperation::CreateContrastFilter(1.f); | |
| 151 case FilterOperation::OPACITY: | |
| 152 return FilterOperation::CreateOpacityFilter(1.f); | |
| 153 case FilterOperation::BLUR: | |
| 154 return FilterOperation::CreateBlurFilter(0.f); | |
| 155 case FilterOperation::DROP_SHADOW: | |
| 156 return FilterOperation::CreateDropShadowFilter( | |
| 157 gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT); | |
| 158 case FilterOperation::COLOR_MATRIX: { | |
| 159 SkScalar matrix[20]; | |
| 160 memset(matrix, 0, 20 * sizeof(SkScalar)); | |
| 161 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f; | |
| 162 return FilterOperation::CreateColorMatrixFilter(matrix); | |
| 163 } | |
| 164 case FilterOperation::ZOOM: | |
| 165 return FilterOperation::CreateZoomFilter(1.f, 0); | |
| 166 case FilterOperation::SATURATING_BRIGHTNESS: | |
| 167 return FilterOperation::CreateSaturatingBrightnessFilter(0.f); | |
| 168 case FilterOperation::REFERENCE: | |
| 169 return FilterOperation::CreateReferenceFilter(nullptr); | |
| 170 case FilterOperation::ALPHA_THRESHOLD: | |
| 171 return FilterOperation::CreateAlphaThresholdFilter(SkRegion(), 1.f, 0.f); | |
| 172 } | |
| 173 NOTREACHED(); | |
| 174 return FilterOperation::CreateEmptyFilter(); | |
| 175 } | |
| 176 | |
| 177 static float ClampAmountForFilterType(float amount, | |
| 178 FilterOperation::FilterType type) { | |
| 179 switch (type) { | |
| 180 case FilterOperation::GRAYSCALE: | |
| 181 case FilterOperation::SEPIA: | |
| 182 case FilterOperation::INVERT: | |
| 183 case FilterOperation::OPACITY: | |
| 184 case FilterOperation::ALPHA_THRESHOLD: | |
| 185 return MathUtil::ClampToRange(amount, 0.f, 1.f); | |
| 186 case FilterOperation::SATURATE: | |
| 187 case FilterOperation::BRIGHTNESS: | |
| 188 case FilterOperation::CONTRAST: | |
| 189 case FilterOperation::BLUR: | |
| 190 case FilterOperation::DROP_SHADOW: | |
| 191 return std::max(amount, 0.f); | |
| 192 case FilterOperation::ZOOM: | |
| 193 return std::max(amount, 1.f); | |
| 194 case FilterOperation::HUE_ROTATE: | |
| 195 case FilterOperation::SATURATING_BRIGHTNESS: | |
| 196 return amount; | |
| 197 case FilterOperation::COLOR_MATRIX: | |
| 198 case FilterOperation::REFERENCE: | |
| 199 NOTREACHED(); | |
| 200 return amount; | |
| 201 } | |
| 202 NOTREACHED(); | |
| 203 return amount; | |
| 204 } | |
| 205 | |
| 206 // static | |
| 207 FilterOperation FilterOperation::Blend(const FilterOperation* from, | |
| 208 const FilterOperation* to, | |
| 209 double progress) { | |
| 210 FilterOperation blended_filter = FilterOperation::CreateEmptyFilter(); | |
| 211 | |
| 212 if (!from && !to) | |
| 213 return blended_filter; | |
| 214 | |
| 215 const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type()); | |
| 216 const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type()); | |
| 217 | |
| 218 if (from_op.type() != to_op.type()) | |
| 219 return blended_filter; | |
| 220 | |
| 221 DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX); | |
| 222 blended_filter.set_type(to_op.type()); | |
| 223 | |
| 224 if (to_op.type() == FilterOperation::REFERENCE) { | |
| 225 if (progress > 0.5) | |
| 226 blended_filter.set_image_filter(to_op.image_filter()); | |
| 227 else | |
| 228 blended_filter.set_image_filter(from_op.image_filter()); | |
| 229 return blended_filter; | |
| 230 } | |
| 231 | |
| 232 blended_filter.set_amount(ClampAmountForFilterType( | |
| 233 gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()), | |
| 234 to_op.type())); | |
| 235 | |
| 236 if (to_op.type() == FilterOperation::DROP_SHADOW) { | |
| 237 gfx::Point blended_offset( | |
| 238 gfx::Tween::LinearIntValueBetween(progress, | |
| 239 from_op.drop_shadow_offset().x(), | |
| 240 to_op.drop_shadow_offset().x()), | |
| 241 gfx::Tween::LinearIntValueBetween(progress, | |
| 242 from_op.drop_shadow_offset().y(), | |
| 243 to_op.drop_shadow_offset().y())); | |
| 244 blended_filter.set_drop_shadow_offset(blended_offset); | |
| 245 blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( | |
| 246 progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); | |
| 247 } else if (to_op.type() == FilterOperation::ZOOM) { | |
| 248 blended_filter.set_zoom_inset( | |
| 249 std::max(gfx::Tween::LinearIntValueBetween( | |
| 250 progress, from_op.zoom_inset(), to_op.zoom_inset()), | |
| 251 0)); | |
| 252 } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) { | |
| 253 blended_filter.set_outer_threshold(ClampAmountForFilterType( | |
| 254 gfx::Tween::FloatValueBetween(progress, | |
| 255 from_op.outer_threshold(), | |
| 256 to_op.outer_threshold()), | |
| 257 to_op.type())); | |
| 258 blended_filter.set_region(to_op.region()); | |
| 259 } | |
| 260 | |
| 261 return blended_filter; | |
| 262 } | |
| 263 | |
| 264 void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const { | |
| 265 value->SetInteger("type", type_); | |
| 266 switch (type_) { | |
| 267 case FilterOperation::GRAYSCALE: | |
| 268 case FilterOperation::SEPIA: | |
| 269 case FilterOperation::SATURATE: | |
| 270 case FilterOperation::HUE_ROTATE: | |
| 271 case FilterOperation::INVERT: | |
| 272 case FilterOperation::BRIGHTNESS: | |
| 273 case FilterOperation::CONTRAST: | |
| 274 case FilterOperation::OPACITY: | |
| 275 case FilterOperation::BLUR: | |
| 276 case FilterOperation::SATURATING_BRIGHTNESS: | |
| 277 value->SetDouble("amount", amount_); | |
| 278 break; | |
| 279 case FilterOperation::DROP_SHADOW: | |
| 280 value->SetDouble("std_deviation", amount_); | |
| 281 MathUtil::AddToTracedValue("offset", drop_shadow_offset_, value); | |
| 282 value->SetInteger("color", drop_shadow_color_); | |
| 283 break; | |
| 284 case FilterOperation::COLOR_MATRIX: { | |
| 285 value->BeginArray("matrix"); | |
| 286 for (size_t i = 0; i < arraysize(matrix_); ++i) | |
| 287 value->AppendDouble(matrix_[i]); | |
| 288 value->EndArray(); | |
| 289 break; | |
| 290 } | |
| 291 case FilterOperation::ZOOM: | |
| 292 value->SetDouble("amount", amount_); | |
| 293 value->SetDouble("inset", zoom_inset_); | |
| 294 break; | |
| 295 case FilterOperation::REFERENCE: { | |
| 296 int count_inputs = 0; | |
| 297 if (image_filter_) { | |
| 298 count_inputs = image_filter_->countInputs(); | |
| 299 } | |
| 300 value->SetBoolean("is_null", !image_filter_); | |
| 301 value->SetInteger("count_inputs", count_inputs); | |
| 302 break; | |
| 303 } | |
| 304 case FilterOperation::ALPHA_THRESHOLD: { | |
| 305 value->SetDouble("inner_threshold", amount_); | |
| 306 value->SetDouble("outer_threshold", outer_threshold_); | |
| 307 std::unique_ptr<base::ListValue> region_value(new base::ListValue()); | |
| 308 value->BeginArray("region"); | |
| 309 for (SkRegion::Iterator it(region_); !it.done(); it.next()) { | |
| 310 value->AppendInteger(it.rect().x()); | |
| 311 value->AppendInteger(it.rect().y()); | |
| 312 value->AppendInteger(it.rect().width()); | |
| 313 value->AppendInteger(it.rect().height()); | |
| 314 } | |
| 315 value->EndArray(); | |
| 316 } | |
| 317 break; | |
| 318 } | |
| 319 } | |
| 320 | |
| 321 namespace { | |
| 322 | |
| 323 SkVector MapStdDeviation(float std_deviation, const SkMatrix& matrix) { | |
| 324 // Corresponds to SpreadForStdDeviation in filter_operations.cc. | |
| 325 SkVector sigma = SkVector::Make(std_deviation, std_deviation); | |
| 326 matrix.mapVectors(&sigma, 1); | |
| 327 return sigma * SkIntToScalar(3); | |
| 328 } | |
| 329 | |
| 330 gfx::Rect MapRectInternal(const FilterOperation& op, | |
| 331 const gfx::Rect& rect, | |
| 332 const SkMatrix& matrix, | |
| 333 SkImageFilter::MapDirection direction) { | |
| 334 switch (op.type()) { | |
| 335 case FilterOperation::BLUR: { | |
| 336 SkVector spread = MapStdDeviation(op.amount(), matrix); | |
| 337 float spread_x = std::abs(spread.x()); | |
| 338 float spread_y = std::abs(spread.y()); | |
| 339 gfx::RectF result(rect); | |
| 340 result.Inset(-spread_x, -spread_y, -spread_x, -spread_y); | |
| 341 return gfx::ToEnclosingRect(result); | |
| 342 } | |
| 343 case FilterOperation::DROP_SHADOW: { | |
| 344 SkVector spread = MapStdDeviation(op.amount(), matrix); | |
| 345 float spread_x = std::abs(spread.x()); | |
| 346 float spread_y = std::abs(spread.y()); | |
| 347 gfx::RectF result(rect); | |
| 348 result.Inset(-spread_x, -spread_y, -spread_x, -spread_y); | |
| 349 | |
| 350 gfx::Point drop_shadow_offset = op.drop_shadow_offset(); | |
| 351 SkVector mapped_drop_shadow_offset; | |
| 352 matrix.mapVector(drop_shadow_offset.x(), drop_shadow_offset.y(), | |
| 353 &mapped_drop_shadow_offset); | |
| 354 if (direction == SkImageFilter::kReverse_MapDirection) | |
| 355 mapped_drop_shadow_offset = -mapped_drop_shadow_offset; | |
| 356 result += gfx::Vector2dF(mapped_drop_shadow_offset.x(), | |
| 357 mapped_drop_shadow_offset.y()); | |
| 358 result.Union(gfx::RectF(rect)); | |
| 359 return gfx::ToEnclosingRect(result); | |
| 360 } | |
| 361 case FilterOperation::REFERENCE: { | |
| 362 if (!op.image_filter()) | |
| 363 return rect; | |
| 364 return gfx::SkIRectToRect(op.image_filter()->filterBounds( | |
| 365 gfx::RectToSkIRect(rect), matrix, direction)); | |
| 366 } | |
| 367 default: | |
| 368 return rect; | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 } // namespace | |
| 373 | |
| 374 gfx::Rect FilterOperation::MapRect(const gfx::Rect& rect, | |
| 375 const SkMatrix& matrix) const { | |
| 376 return MapRectInternal(*this, rect, matrix, | |
| 377 SkImageFilter::kForward_MapDirection); | |
| 378 } | |
| 379 | |
| 380 gfx::Rect FilterOperation::MapRectReverse(const gfx::Rect& rect, | |
| 381 const SkMatrix& matrix) const { | |
| 382 return MapRectInternal(*this, rect, matrix, | |
| 383 SkImageFilter::kReverse_MapDirection); | |
| 384 } | |
| 385 | |
| 386 } // namespace cc | |
| OLD | NEW |