1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <cmath> 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/filter_operations.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/values.h" 10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "cc/output/filter_operation.h" 11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace cc { 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFilterOperations::FilterOperations() {} 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFilterOperations::FilterOperations(const FilterOperations& other) 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : operations_(other.operations_) {} 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFilterOperations::~FilterOperations() {} 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFilterOperations& FilterOperations::operator=(const FilterOperations& other) { 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch operations_ = other.operations_; 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return *this; 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FilterOperations::operator==(const FilterOperations& other) const { 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (other.size() != size()) 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < size(); ++i) { 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (other.at(i) != at(i)) 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid FilterOperations::Append(const FilterOperation& filter) { 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch operations_.push_back(filter); 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid FilterOperations::Clear() { 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch operations_.clear(); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FilterOperations::IsEmpty() const { 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return operations_.empty(); 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int SpreadForStdDeviation(float std_deviation) { 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#feGaussianBlurElement 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // provides this approximation for evaluating a gaussian blur by a triple box 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // filter. 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float d = floorf(std_deviation * 3.f * sqrt(8.f * atan(1.f)) / 4.f + 0.5f); 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return static_cast<int>(ceilf(d * 3.f / 2.f)); 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid FilterOperations::GetOutsets(int* top, 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int* right, 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int* bottom, 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int* left) const { 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *top = *right = *bottom = *left = 0; 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < operations_.size(); ++i) { 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const FilterOperation& op = operations_[i]; 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(ajuma): Add support for reference filters once SkImageFilter 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // reports its outsets. 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(op.type() != FilterOperation::REFERENCE); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (op.type() == FilterOperation::BLUR || 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch op.type() == FilterOperation::DROP_SHADOW) { 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int spread = SpreadForStdDeviation(op.amount()); 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (op.type() == FilterOperation::BLUR) { 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *top += spread; 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *right += spread; 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *bottom += spread; 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *left += spread; 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *top += spread - op.drop_shadow_offset().y(); 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *right += spread + op.drop_shadow_offset().x(); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *bottom += spread + op.drop_shadow_offset().y(); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *left += spread - op.drop_shadow_offset().x(); 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FilterOperations::HasFilterThatMovesPixels() const { 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < operations_.size(); ++i) { 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const FilterOperation& op = operations_[i]; 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(ajuma): Once SkImageFilter reports its outsets, use those here to 8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // determine whether a reference filter really moves pixels. 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (op.type()) { 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::BLUR: 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::DROP_SHADOW: 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::ZOOM: 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case FilterOperation::REFERENCE: 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::OPACITY: 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::COLOR_MATRIX: 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::GRAYSCALE: 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SEPIA: 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SATURATE: 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::HUE_ROTATE: 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::INVERT: 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::BRIGHTNESS: 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::CONTRAST: 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SATURATING_BRIGHTNESS: 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case FilterOperation::ALPHA_THRESHOLD: 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool FilterOperations::HasFilterThatAffectsOpacity() const { 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < operations_.size(); ++i) { 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const FilterOperation& op = operations_[i]; 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(ajuma): Make this smarter for reference filters. Once SkImageFilter 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // can report affectsOpacity(), call that. 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (op.type()) { 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::OPACITY: 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::BLUR: 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::DROP_SHADOW: 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::ZOOM: 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case FilterOperation::REFERENCE: 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case FilterOperation::ALPHA_THRESHOLD: 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case FilterOperation::COLOR_MATRIX: { 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SkScalar* matrix = op.matrix(); 127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (matrix[15] || 128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) matrix[16] || 129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) matrix[17] || 130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) matrix[18] != 1 || 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) matrix[19]) 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::GRAYSCALE: 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SEPIA: 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SATURATE: 138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::HUE_ROTATE: 139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::INVERT: 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::BRIGHTNESS: 141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::CONTRAST: 142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case FilterOperation::SATURATING_BRIGHTNESS: 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool FilterOperations::HasReferenceFilter() const { 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = 0; i < operations_.size(); ++i) { 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (operations_[i].type() == FilterOperation::REFERENCE) 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochFilterOperations FilterOperations::Blend(const FilterOperations& from, 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch double progress) const { 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (HasReferenceFilter() || from.HasReferenceFilter()) 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return *this; 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool from_is_longer = from.size() > size(); 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t shorter_size, longer_size; 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (size() == from.size()) { 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) shorter_size = longer_size = size(); 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (from_is_longer) { 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) longer_size = from.size(); 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) shorter_size = size(); 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) longer_size = size(); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) shorter_size = from.size(); 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = 0; i < shorter_size; i++) { 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (from.at(i).type() != at(i).type()) 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return *this; 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FilterOperations blended_filters; 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = 0; i < shorter_size; i++) { 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch blended_filters.Append( 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch FilterOperation::Blend(&from.at(i), &at(i), progress)); 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (from_is_longer) { 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = shorter_size; i < longer_size; i++) { 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blended_filters.Append( 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FilterOperation::Blend(&from.at(i), NULL, progress)); 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = shorter_size; i < longer_size; i++) 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blended_filters.Append(FilterOperation::Blend(NULL, &at(i), progress)); 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return blended_filters; 1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochscoped_ptr<base::Value> FilterOperations::AsValue() const { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> value(new base::ListValue); 201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (size_t i = 0; i < operations_.size(); ++i) 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch value->Append(operations_[i].AsValue().release()); 203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return value.PassAs<base::Value>(); 204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace cc 207