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 <cmath> 6 7 #include "cc/output/filter_operations.h" 8 9 #include "base/values.h" 10 #include "cc/output/filter_operation.h" 11 12 namespace cc { 13 14 FilterOperations::FilterOperations() {} 15 16 FilterOperations::FilterOperations(const FilterOperations& other) 17 : operations_(other.operations_) {} 18 19 FilterOperations::~FilterOperations() {} 20 21 FilterOperations& FilterOperations::operator=(const FilterOperations& other) { 22 operations_ = other.operations_; 23 return *this; 24 } 25 26 bool FilterOperations::operator==(const FilterOperations& other) const { 27 if (other.size() != size()) 28 return false; 29 for (size_t i = 0; i < size(); ++i) { 30 if (other.at(i) != at(i)) 31 return false; 32 } 33 return true; 34 } 35 36 void FilterOperations::Append(const FilterOperation& filter) { 37 operations_.push_back(filter); 38 } 39 40 void FilterOperations::Clear() { 41 operations_.clear(); 42 } 43 44 bool FilterOperations::IsEmpty() const { 45 return operations_.empty(); 46 } 47 48 static int SpreadForStdDeviation(float std_deviation) { 49 // https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#feGaussianBlurElement 50 // provides this approximation for evaluating a gaussian blur by a triple box 51 // filter. 52 float d = floorf(std_deviation * 3.f * sqrt(8.f * atan(1.f)) / 4.f + 0.5f); 53 return static_cast<int>(ceilf(d * 3.f / 2.f)); 54 } 55 56 void FilterOperations::GetOutsets(int* top, 57 int* right, 58 int* bottom, 59 int* left) const { 60 *top = *right = *bottom = *left = 0; 61 for (size_t i = 0; i < operations_.size(); ++i) { 62 const FilterOperation op = operations_[i]; 63 if (op.type() == FilterOperation::BLUR || 64 op.type() == FilterOperation::DROP_SHADOW) { 65 int spread = SpreadForStdDeviation(op.amount()); 66 if (op.type() == FilterOperation::BLUR) { 67 *top += spread; 68 *right += spread; 69 *bottom += spread; 70 *left += spread; 71 } else { 72 *top += spread - op.drop_shadow_offset().y(); 73 *right += spread + op.drop_shadow_offset().x(); 74 *bottom += spread + op.drop_shadow_offset().y(); 75 *left += spread - op.drop_shadow_offset().x(); 76 } 77 } 78 } 79 } 80 81 bool FilterOperations::HasFilterThatMovesPixels() const { 82 for (size_t i = 0; i < operations_.size(); ++i) { 83 const FilterOperation op = operations_[i]; 84 switch (op.type()) { 85 case FilterOperation::BLUR: 86 case FilterOperation::DROP_SHADOW: 87 case FilterOperation::ZOOM: 88 return true; 89 default: 90 break; 91 } 92 } 93 return false; 94 } 95 96 bool FilterOperations::HasFilterThatAffectsOpacity() const { 97 for (size_t i = 0; i < operations_.size(); ++i) { 98 const FilterOperation op = operations_[i]; 99 switch (op.type()) { 100 case FilterOperation::OPACITY: 101 case FilterOperation::BLUR: 102 case FilterOperation::DROP_SHADOW: 103 case FilterOperation::ZOOM: 104 return true; 105 case FilterOperation::COLOR_MATRIX: { 106 const SkScalar* matrix = op.matrix(); 107 return matrix[15] || matrix[16] || matrix[17] || matrix[18] != 1 || 108 matrix[19]; 109 } 110 default: 111 break; 112 } 113 } 114 return false; 115 } 116 117 FilterOperations FilterOperations::Blend(const FilterOperations& from, 118 double progress) const { 119 FilterOperations blended_filters; 120 if (from.size() == 0) { 121 for (size_t i = 0; i < size(); i++) 122 blended_filters.Append(FilterOperation::Blend(NULL, &at(i), progress)); 123 return blended_filters; 124 } 125 126 if (size() == 0) { 127 for (size_t i = 0; i < from.size(); i++) { 128 blended_filters.Append( 129 FilterOperation::Blend(&from.at(i), NULL, progress)); 130 } 131 return blended_filters; 132 } 133 134 if (from.size() != size()) 135 return *this; 136 137 for (size_t i = 0; i < size(); i++) { 138 if (from.at(i).type() != at(i).type()) 139 return *this; 140 } 141 142 for (size_t i = 0; i < size(); i++) { 143 blended_filters.Append( 144 FilterOperation::Blend(&from.at(i), &at(i), progress)); 145 } 146 147 return blended_filters; 148 } 149 150 scoped_ptr<base::Value> FilterOperations::AsValue() const { 151 scoped_ptr<base::ListValue> value(new ListValue); 152 for (size_t i = 0; i < operations_.size(); ++i) 153 value->Append(operations_[i].AsValue().release()); 154 return value.PassAs<base::Value>(); 155 } 156 157 } // namespace cc 158