Home | History | Annotate | Download | only in output
      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