// 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 <stddef.h>

#include <algorithm>

#include "base/trace_event/trace_event_argument.h"
#include "base/values.h"
#include "cc/base/filter_operation.h"
#include "cc/base/math_util.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.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() : FilterOperation(GRAYSCALE, 0.f) {}

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,
                                 sk_sp<SkImageFilter> image_filter)
    : type_(type),
      amount_(0),
      outer_threshold_(0),
      drop_shadow_offset_(0, 0),
      drop_shadow_color_(0),
      image_filter_(std::move(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(nullptr);
    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(
                     progress, from_op.zoom_inset(), to_op.zoom_inset()),
                 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;
      if (image_filter_) {
        count_inputs = image_filter_->countInputs();
      }
      value->SetBoolean("is_null", !image_filter_);
      value->SetInteger("count_inputs", count_inputs);
      break;
    }
    case FilterOperation::ALPHA_THRESHOLD: {
      value->SetDouble("inner_threshold", amount_);
      value->SetDouble("outer_threshold", outer_threshold_);
      std::unique_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 {

SkVector MapStdDeviation(float std_deviation, const SkMatrix& matrix) {
  // Corresponds to SpreadForStdDeviation in filter_operations.cc.
  SkVector sigma = SkVector::Make(std_deviation, std_deviation);
  matrix.mapVectors(&sigma, 1);
  return sigma * SkIntToScalar(3);
}

gfx::Rect MapRectInternal(const FilterOperation& op,
                          const gfx::Rect& rect,
                          const SkMatrix& matrix,
                          SkImageFilter::MapDirection direction) {
  switch (op.type()) {
    case FilterOperation::BLUR: {
      SkVector spread = MapStdDeviation(op.amount(), matrix);
      float spread_x = std::abs(spread.x());
      float spread_y = std::abs(spread.y());
      gfx::RectF result(rect);
      result.Inset(-spread_x, -spread_y, -spread_x, -spread_y);
      return gfx::ToEnclosingRect(result);
    }
    case FilterOperation::DROP_SHADOW: {
      SkVector spread = MapStdDeviation(op.amount(), matrix);
      float spread_x = std::abs(spread.x());
      float spread_y = std::abs(spread.y());
      gfx::RectF result(rect);
      result.Inset(-spread_x, -spread_y, -spread_x, -spread_y);

      gfx::Point drop_shadow_offset = op.drop_shadow_offset();
      SkVector mapped_drop_shadow_offset;
      matrix.mapVector(drop_shadow_offset.x(), drop_shadow_offset.y(),
                       &mapped_drop_shadow_offset);
      if (direction == SkImageFilter::kReverse_MapDirection)
        mapped_drop_shadow_offset = -mapped_drop_shadow_offset;
      result += gfx::Vector2dF(mapped_drop_shadow_offset.x(),
                               mapped_drop_shadow_offset.y());
      result.Union(gfx::RectF(rect));
      return gfx::ToEnclosingRect(result);
    }
    case FilterOperation::REFERENCE: {
      if (!op.image_filter())
        return rect;
      return gfx::SkIRectToRect(op.image_filter()->filterBounds(
          gfx::RectToSkIRect(rect), matrix, direction));
    }
    default:
      return rect;
  }
}

}  // namespace

gfx::Rect FilterOperation::MapRect(const gfx::Rect& rect,
                                   const SkMatrix& matrix) const {
  return MapRectInternal(*this, rect, matrix,
                         SkImageFilter::kForward_MapDirection);
}

gfx::Rect FilterOperation::MapRectReverse(const gfx::Rect& rect,
                                          const SkMatrix& matrix) const {
  return MapRectInternal(*this, rect, matrix,
                         SkImageFilter::kReverse_MapDirection);
}

}  // namespace cc
