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 13namespace cc { 14 15bool 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 35FilterOperation::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 48FilterOperation::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 62FilterOperation::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 73FilterOperation::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 84FilterOperation::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 98FilterOperation::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 113FilterOperation::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 125FilterOperation::~FilterOperation() { 126} 127 128static 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 171static 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 201FilterOperation 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 258void 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 321