| Index: cc/output/filter_operation.cc
|
| diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1579e554a04be67b14c3565890c284e88fa3c365
|
| --- /dev/null
|
| +++ b/cc/output/filter_operation.cc
|
| @@ -0,0 +1,318 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/trace_event/trace_event_argument.h"
|
| +#include "base/values.h"
|
| +#include "cc/base/math_util.h"
|
| +#include "cc/output/filter_operation.h"
|
| +#include "ui/gfx/animation/tween.h"
|
| +
|
| +namespace cc {
|
| +
|
| +bool FilterOperation::operator==(const FilterOperation& other) const {
|
| + if (type_ != other.type_)
|
| + return false;
|
| + if (type_ == COLOR_MATRIX)
|
| + return !memcmp(matrix_, other.matrix_, sizeof(matrix_));
|
| + if (type_ == DROP_SHADOW) {
|
| + return amount_ == other.amount_ &&
|
| + drop_shadow_offset_ == other.drop_shadow_offset_ &&
|
| + drop_shadow_color_ == other.drop_shadow_color_;
|
| + }
|
| + if (type_ == REFERENCE)
|
| + return image_filter_.get() == other.image_filter_.get();
|
| + if (type_ == ALPHA_THRESHOLD) {
|
| + return region_ == other.region_ &&
|
| + amount_ == other.amount_ &&
|
| + outer_threshold_ == other.outer_threshold_;
|
| + }
|
| + return amount_ == other.amount_;
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(FilterType type, float amount)
|
| + : type_(type),
|
| + amount_(amount),
|
| + outer_threshold_(0),
|
| + drop_shadow_offset_(0, 0),
|
| + drop_shadow_color_(0),
|
| + zoom_inset_(0) {
|
| + DCHECK_NE(type_, DROP_SHADOW);
|
| + DCHECK_NE(type_, COLOR_MATRIX);
|
| + DCHECK_NE(type_, REFERENCE);
|
| + memset(matrix_, 0, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(FilterType type,
|
| + const gfx::Point& offset,
|
| + float stdDeviation,
|
| + SkColor color)
|
| + : type_(type),
|
| + amount_(stdDeviation),
|
| + outer_threshold_(0),
|
| + drop_shadow_offset_(offset),
|
| + drop_shadow_color_(color),
|
| + zoom_inset_(0) {
|
| + DCHECK_EQ(type_, DROP_SHADOW);
|
| + memset(matrix_, 0, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(FilterType type, SkScalar matrix[20])
|
| + : type_(type),
|
| + amount_(0),
|
| + outer_threshold_(0),
|
| + drop_shadow_offset_(0, 0),
|
| + drop_shadow_color_(0),
|
| + zoom_inset_(0) {
|
| + DCHECK_EQ(type_, COLOR_MATRIX);
|
| + memcpy(matrix_, matrix, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(FilterType type, float amount, int inset)
|
| + : type_(type),
|
| + amount_(amount),
|
| + outer_threshold_(0),
|
| + drop_shadow_offset_(0, 0),
|
| + drop_shadow_color_(0),
|
| + zoom_inset_(inset) {
|
| + DCHECK_EQ(type_, ZOOM);
|
| + memset(matrix_, 0, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(
|
| + FilterType type,
|
| + const skia::RefPtr<SkImageFilter>& image_filter)
|
| + : type_(type),
|
| + amount_(0),
|
| + outer_threshold_(0),
|
| + drop_shadow_offset_(0, 0),
|
| + drop_shadow_color_(0),
|
| + image_filter_(image_filter),
|
| + zoom_inset_(0) {
|
| + DCHECK_EQ(type_, REFERENCE);
|
| + memset(matrix_, 0, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(FilterType type,
|
| + const SkRegion& region,
|
| + float inner_threshold,
|
| + float outer_threshold)
|
| + : type_(type),
|
| + amount_(inner_threshold),
|
| + outer_threshold_(outer_threshold),
|
| + drop_shadow_offset_(0, 0),
|
| + drop_shadow_color_(0),
|
| + zoom_inset_(0),
|
| + region_(region) {
|
| + DCHECK_EQ(type_, ALPHA_THRESHOLD);
|
| + memset(matrix_, 0, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::FilterOperation(const FilterOperation& other)
|
| + : type_(other.type_),
|
| + amount_(other.amount_),
|
| + outer_threshold_(other.outer_threshold_),
|
| + drop_shadow_offset_(other.drop_shadow_offset_),
|
| + drop_shadow_color_(other.drop_shadow_color_),
|
| + image_filter_(other.image_filter_),
|
| + zoom_inset_(other.zoom_inset_),
|
| + region_(other.region_) {
|
| + memcpy(matrix_, other.matrix_, sizeof(matrix_));
|
| +}
|
| +
|
| +FilterOperation::~FilterOperation() {
|
| +}
|
| +
|
| +static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
|
| + switch (type) {
|
| + case FilterOperation::GRAYSCALE:
|
| + return FilterOperation::CreateGrayscaleFilter(0.f);
|
| + case FilterOperation::SEPIA:
|
| + return FilterOperation::CreateSepiaFilter(0.f);
|
| + case FilterOperation::SATURATE:
|
| + return FilterOperation::CreateSaturateFilter(1.f);
|
| + case FilterOperation::HUE_ROTATE:
|
| + return FilterOperation::CreateHueRotateFilter(0.f);
|
| + case FilterOperation::INVERT:
|
| + return FilterOperation::CreateInvertFilter(0.f);
|
| + case FilterOperation::BRIGHTNESS:
|
| + return FilterOperation::CreateBrightnessFilter(1.f);
|
| + case FilterOperation::CONTRAST:
|
| + return FilterOperation::CreateContrastFilter(1.f);
|
| + case FilterOperation::OPACITY:
|
| + return FilterOperation::CreateOpacityFilter(1.f);
|
| + case FilterOperation::BLUR:
|
| + return FilterOperation::CreateBlurFilter(0.f);
|
| + case FilterOperation::DROP_SHADOW:
|
| + return FilterOperation::CreateDropShadowFilter(
|
| + gfx::Point(0, 0), 0.f, SK_ColorTRANSPARENT);
|
| + case FilterOperation::COLOR_MATRIX: {
|
| + SkScalar matrix[20];
|
| + memset(matrix, 0, 20 * sizeof(SkScalar));
|
| + matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
|
| + return FilterOperation::CreateColorMatrixFilter(matrix);
|
| + }
|
| + case FilterOperation::ZOOM:
|
| + return FilterOperation::CreateZoomFilter(1.f, 0);
|
| + case FilterOperation::SATURATING_BRIGHTNESS:
|
| + return FilterOperation::CreateSaturatingBrightnessFilter(0.f);
|
| + case FilterOperation::REFERENCE:
|
| + return FilterOperation::CreateReferenceFilter(
|
| + skia::RefPtr<SkImageFilter>());
|
| + case FilterOperation::ALPHA_THRESHOLD:
|
| + return FilterOperation::CreateAlphaThresholdFilter(SkRegion(), 1.f, 0.f);
|
| + }
|
| + NOTREACHED();
|
| + return FilterOperation::CreateEmptyFilter();
|
| +}
|
| +
|
| +static float ClampAmountForFilterType(float amount,
|
| + FilterOperation::FilterType type) {
|
| + switch (type) {
|
| + case FilterOperation::GRAYSCALE:
|
| + case FilterOperation::SEPIA:
|
| + case FilterOperation::INVERT:
|
| + case FilterOperation::OPACITY:
|
| + case FilterOperation::ALPHA_THRESHOLD:
|
| + return MathUtil::ClampToRange(amount, 0.f, 1.f);
|
| + case FilterOperation::SATURATE:
|
| + case FilterOperation::BRIGHTNESS:
|
| + case FilterOperation::CONTRAST:
|
| + case FilterOperation::BLUR:
|
| + case FilterOperation::DROP_SHADOW:
|
| + return std::max(amount, 0.f);
|
| + case FilterOperation::ZOOM:
|
| + return std::max(amount, 1.f);
|
| + case FilterOperation::HUE_ROTATE:
|
| + case FilterOperation::SATURATING_BRIGHTNESS:
|
| + return amount;
|
| + case FilterOperation::COLOR_MATRIX:
|
| + case FilterOperation::REFERENCE:
|
| + NOTREACHED();
|
| + return amount;
|
| + }
|
| + NOTREACHED();
|
| + return amount;
|
| +}
|
| +
|
| +// static
|
| +FilterOperation FilterOperation::Blend(const FilterOperation* from,
|
| + const FilterOperation* to,
|
| + double progress) {
|
| + FilterOperation blended_filter = FilterOperation::CreateEmptyFilter();
|
| +
|
| + if (!from && !to)
|
| + return blended_filter;
|
| +
|
| + const FilterOperation& from_op = from ? *from : CreateNoOpFilter(to->type());
|
| + const FilterOperation& to_op = to ? *to : CreateNoOpFilter(from->type());
|
| +
|
| + if (from_op.type() != to_op.type())
|
| + return blended_filter;
|
| +
|
| + DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX);
|
| + blended_filter.set_type(to_op.type());
|
| +
|
| + if (to_op.type() == FilterOperation::REFERENCE) {
|
| + if (progress > 0.5)
|
| + blended_filter.set_image_filter(to_op.image_filter());
|
| + else
|
| + blended_filter.set_image_filter(from_op.image_filter());
|
| + return blended_filter;
|
| + }
|
| +
|
| + blended_filter.set_amount(ClampAmountForFilterType(
|
| + gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()),
|
| + to_op.type()));
|
| +
|
| + if (to_op.type() == FilterOperation::DROP_SHADOW) {
|
| + gfx::Point blended_offset(
|
| + gfx::Tween::LinearIntValueBetween(progress,
|
| + from_op.drop_shadow_offset().x(),
|
| + to_op.drop_shadow_offset().x()),
|
| + gfx::Tween::LinearIntValueBetween(progress,
|
| + from_op.drop_shadow_offset().y(),
|
| + to_op.drop_shadow_offset().y()));
|
| + blended_filter.set_drop_shadow_offset(blended_offset);
|
| + blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween(
|
| + progress, from_op.drop_shadow_color(), to_op.drop_shadow_color()));
|
| + } else if (to_op.type() == FilterOperation::ZOOM) {
|
| + blended_filter.set_zoom_inset(
|
| + std::max(gfx::Tween::LinearIntValueBetween(
|
| + from_op.zoom_inset(), to_op.zoom_inset(), progress),
|
| + 0));
|
| + } else if (to_op.type() == FilterOperation::ALPHA_THRESHOLD) {
|
| + blended_filter.set_outer_threshold(ClampAmountForFilterType(
|
| + gfx::Tween::FloatValueBetween(progress,
|
| + from_op.outer_threshold(),
|
| + to_op.outer_threshold()),
|
| + to_op.type()));
|
| + blended_filter.set_region(to_op.region());
|
| + }
|
| +
|
| + return blended_filter;
|
| +}
|
| +
|
| +void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const {
|
| + value->SetInteger("type", type_);
|
| + switch (type_) {
|
| + case FilterOperation::GRAYSCALE:
|
| + case FilterOperation::SEPIA:
|
| + case FilterOperation::SATURATE:
|
| + case FilterOperation::HUE_ROTATE:
|
| + case FilterOperation::INVERT:
|
| + case FilterOperation::BRIGHTNESS:
|
| + case FilterOperation::CONTRAST:
|
| + case FilterOperation::OPACITY:
|
| + case FilterOperation::BLUR:
|
| + case FilterOperation::SATURATING_BRIGHTNESS:
|
| + value->SetDouble("amount", amount_);
|
| + break;
|
| + case FilterOperation::DROP_SHADOW:
|
| + value->SetDouble("std_deviation", amount_);
|
| + MathUtil::AddToTracedValue("offset", drop_shadow_offset_, value);
|
| + value->SetInteger("color", drop_shadow_color_);
|
| + break;
|
| + case FilterOperation::COLOR_MATRIX: {
|
| + value->BeginArray("matrix");
|
| + for (size_t i = 0; i < arraysize(matrix_); ++i)
|
| + value->AppendDouble(matrix_[i]);
|
| + value->EndArray();
|
| + break;
|
| + }
|
| + case FilterOperation::ZOOM:
|
| + value->SetDouble("amount", amount_);
|
| + value->SetDouble("inset", zoom_inset_);
|
| + break;
|
| + case FilterOperation::REFERENCE: {
|
| + int count_inputs = 0;
|
| + bool can_filter_image_gpu = false;
|
| + if (image_filter_) {
|
| + count_inputs = image_filter_->countInputs();
|
| + can_filter_image_gpu = image_filter_->canFilterImageGPU();
|
| + }
|
| + value->SetBoolean("is_null", !image_filter_);
|
| + value->SetInteger("count_inputs", count_inputs);
|
| + value->SetBoolean("can_filter_image_gpu", can_filter_image_gpu);
|
| + break;
|
| + }
|
| + case FilterOperation::ALPHA_THRESHOLD: {
|
| + value->SetDouble("inner_threshold", amount_);
|
| + value->SetDouble("outer_threshold", outer_threshold_);
|
| + scoped_ptr<base::ListValue> region_value(new base::ListValue());
|
| + value->BeginArray("region");
|
| + for (SkRegion::Iterator it(region_); !it.done(); it.next()) {
|
| + value->AppendInteger(it.rect().x());
|
| + value->AppendInteger(it.rect().y());
|
| + value->AppendInteger(it.rect().width());
|
| + value->AppendInteger(it.rect().height());
|
| + }
|
| + value->EndArray();
|
| + }
|
| + break;
|
| + }
|
| +}
|
| +
|
| +} // namespace cc
|
|
|