/*
 * Copyright (C) 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"

#include <algorithm>
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/renderer/core/style/filter_operations.h"
#include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
#include "third_party/blink/renderer/core/svg/svg_filter_element.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h"
#include "third_party/blink/renderer/platform/graphics/interpolation_space.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"

namespace blink {

namespace {

inline void EndMatrixRow(Vector<float>& matrix) {
  matrix.UncheckedAppend(0);
  matrix.UncheckedAppend(0);
}

inline void LastMatrixRow(Vector<float>& matrix) {
  matrix.UncheckedAppend(0);
  matrix.UncheckedAppend(0);
  matrix.UncheckedAppend(0);
  matrix.UncheckedAppend(1);
  matrix.UncheckedAppend(0);
}

Vector<float> GrayscaleMatrix(double amount) {
  double one_minus_amount = clampTo(1 - amount, 0.0, 1.0);

  // See https://drafts.fxtf.org/filter-effects/#grayscaleEquivalent for
  // information on parameters.
  Vector<float> matrix;
  matrix.ReserveInitialCapacity(20);

  matrix.UncheckedAppend(clampTo<float>(0.2126 + 0.7874 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.7152 - 0.7152 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.0722 - 0.0722 * one_minus_amount));
  EndMatrixRow(matrix);

  matrix.UncheckedAppend(clampTo<float>(0.2126 - 0.2126 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.7152 + 0.2848 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.0722 - 0.0722 * one_minus_amount));
  EndMatrixRow(matrix);

  matrix.UncheckedAppend(clampTo<float>(0.2126 - 0.2126 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.7152 - 0.7152 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.0722 + 0.9278 * one_minus_amount));
  EndMatrixRow(matrix);

  LastMatrixRow(matrix);
  return matrix;
}

Vector<float> SepiaMatrix(double amount) {
  double one_minus_amount = clampTo(1 - amount, 0.0, 1.0);

  // See https://drafts.fxtf.org/filter-effects/#sepiaEquivalent for information
  // on parameters.
  Vector<float> matrix;
  matrix.ReserveInitialCapacity(20);

  matrix.UncheckedAppend(clampTo<float>(0.393 + 0.607 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.769 - 0.769 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.189 - 0.189 * one_minus_amount));
  EndMatrixRow(matrix);

  matrix.UncheckedAppend(clampTo<float>(0.349 - 0.349 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.686 + 0.314 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.168 - 0.168 * one_minus_amount));
  EndMatrixRow(matrix);

  matrix.UncheckedAppend(clampTo<float>(0.272 - 0.272 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.534 - 0.534 * one_minus_amount));
  matrix.UncheckedAppend(clampTo<float>(0.131 + 0.869 * one_minus_amount));
  EndMatrixRow(matrix);

  LastMatrixRow(matrix);
  return matrix;
}

}  // namespace

FilterEffectBuilder::FilterEffectBuilder(const FloatRect& reference_box,
                                         float zoom,
                                         const PaintFlags* fill_flags,
                                         const PaintFlags* stroke_flags)
    : reference_box_(reference_box),
      zoom_(zoom),
      fill_flags_(fill_flags),
      stroke_flags_(stroke_flags) {}

FilterEffect* FilterEffectBuilder::BuildFilterEffect(
    const FilterOperations& operations,
    bool input_tainted) const {
  // Create a parent filter for shorthand filters. These have already been
  // scaled by the CSS code for page zoom, so scale is 1.0 here.
  Filter* parent_filter = Filter::Create(1.0f);
  FilterEffect* previous_effect = parent_filter->GetSourceGraphic();
  if (input_tainted)
    previous_effect->SetOriginTainted();
  for (FilterOperation* filter_operation : operations.Operations()) {
    FilterEffect* effect = nullptr;
    switch (filter_operation->GetType()) {
      case FilterOperation::REFERENCE: {
        ReferenceFilterOperation& reference_operation =
            ToReferenceFilterOperation(*filter_operation);
        Filter* reference_filter =
            BuildReferenceFilter(reference_operation, previous_effect);
        if (reference_filter) {
          effect = reference_filter->LastEffect();
          // TODO(fs): This is essentially only needed for the
          // side-effects (mapRect). The filter differs from the one
          // computed just above in what the SourceGraphic is, and how
          // it's connected to the filter-chain.
          reference_filter = BuildReferenceFilter(reference_operation, nullptr);
        }
        reference_operation.SetFilter(reference_filter);
        break;
      }
      case FilterOperation::GRAYSCALE: {
        Vector<float> input_parameters = GrayscaleMatrix(
            ToBasicColorMatrixFilterOperation(filter_operation)->Amount());
        effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX,
                                       input_parameters);
        break;
      }
      case FilterOperation::SEPIA: {
        Vector<float> input_parameters = SepiaMatrix(
            ToBasicColorMatrixFilterOperation(filter_operation)->Amount());
        effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX,
                                       input_parameters);
        break;
      }
      case FilterOperation::SATURATE: {
        Vector<float> input_parameters;
        input_parameters.push_back(clampTo<float>(
            ToBasicColorMatrixFilterOperation(filter_operation)->Amount()));
        effect = FEColorMatrix::Create(
            parent_filter, FECOLORMATRIX_TYPE_SATURATE, input_parameters);
        break;
      }
      case FilterOperation::HUE_ROTATE: {
        Vector<float> input_parameters;
        input_parameters.push_back(clampTo<float>(
            ToBasicColorMatrixFilterOperation(filter_operation)->Amount()));
        effect = FEColorMatrix::Create(
            parent_filter, FECOLORMATRIX_TYPE_HUEROTATE, input_parameters);
        break;
      }
      case FilterOperation::INVERT: {
        BasicComponentTransferFilterOperation* component_transfer_operation =
            ToBasicComponentTransferFilterOperation(filter_operation);
        ComponentTransferFunction transfer_function;
        transfer_function.type = FECOMPONENTTRANSFER_TYPE_TABLE;
        Vector<float> transfer_parameters;
        transfer_parameters.push_back(
            clampTo<float>(component_transfer_operation->Amount()));
        transfer_parameters.push_back(
            clampTo<float>(1 - component_transfer_operation->Amount()));
        transfer_function.table_values = transfer_parameters;

        ComponentTransferFunction null_function;
        effect = FEComponentTransfer::Create(parent_filter, transfer_function,
                                             transfer_function,
                                             transfer_function, null_function);
        break;
      }
      case FilterOperation::OPACITY: {
        ComponentTransferFunction transfer_function;
        transfer_function.type = FECOMPONENTTRANSFER_TYPE_TABLE;
        Vector<float> transfer_parameters;
        transfer_parameters.push_back(0);
        transfer_parameters.push_back(clampTo<float>(
            ToBasicComponentTransferFilterOperation(filter_operation)
                ->Amount()));
        transfer_function.table_values = transfer_parameters;

        ComponentTransferFunction null_function;
        effect = FEComponentTransfer::Create(parent_filter, null_function,
                                             null_function, null_function,
                                             transfer_function);
        break;
      }
      case FilterOperation::BRIGHTNESS: {
        ComponentTransferFunction transfer_function;
        transfer_function.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
        transfer_function.slope = clampTo<float>(
            ToBasicComponentTransferFilterOperation(filter_operation)
                ->Amount());
        transfer_function.intercept = 0;

        ComponentTransferFunction null_function;
        effect = FEComponentTransfer::Create(parent_filter, transfer_function,
                                             transfer_function,
                                             transfer_function, null_function);
        break;
      }
      case FilterOperation::CONTRAST: {
        ComponentTransferFunction transfer_function;
        transfer_function.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
        float amount = clampTo<float>(
            ToBasicComponentTransferFilterOperation(filter_operation)
                ->Amount());
        transfer_function.slope = amount;
        transfer_function.intercept = -0.5 * amount + 0.5;

        ComponentTransferFunction null_function;
        effect = FEComponentTransfer::Create(parent_filter, transfer_function,
                                             transfer_function,
                                             transfer_function, null_function);
        break;
      }
      case FilterOperation::BLUR: {
        float std_deviation = FloatValueForLength(
            ToBlurFilterOperation(filter_operation)->StdDeviation(), 0);
        effect =
            FEGaussianBlur::Create(parent_filter, std_deviation, std_deviation);
        break;
      }
      case FilterOperation::DROP_SHADOW: {
        const ShadowData& shadow =
            ToDropShadowFilterOperation(*filter_operation).Shadow();
        effect = FEDropShadow::Create(parent_filter, shadow.Blur(),
                                      shadow.Blur(), shadow.X(), shadow.Y(),
                                      shadow.GetColor().GetColor(), 1);
        break;
      }
      case FilterOperation::BOX_REFLECT: {
        BoxReflectFilterOperation* box_reflect_operation =
            ToBoxReflectFilterOperation(filter_operation);
        effect = FEBoxReflect::Create(parent_filter,
                                      box_reflect_operation->Reflection());
        break;
      }
      default:
        break;
    }

    if (effect) {
      if (filter_operation->GetType() != FilterOperation::REFERENCE) {
        // Unlike SVG, filters applied here should not clip to their primitive
        // subregions.
        effect->SetClipsToBounds(false);
        effect->SetOperatingInterpolationSpace(kInterpolationSpaceSRGB);
        effect->InputEffects().push_back(previous_effect);
      }
      if (previous_effect->OriginTainted())
        effect->SetOriginTainted();
      previous_effect = effect;
    }
  }
  return previous_effect;
}

CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
    const FilterOperations& operations) const {
  InterpolationSpace current_interpolation_space = kInterpolationSpaceSRGB;

  CompositorFilterOperations filters;
  for (FilterOperation* op : operations.Operations()) {
    switch (op->GetType()) {
      case FilterOperation::REFERENCE: {
        ReferenceFilterOperation& reference_operation =
            ToReferenceFilterOperation(*op);
        Filter* reference_filter =
            BuildReferenceFilter(reference_operation, nullptr);
        if (reference_filter && reference_filter->LastEffect()) {
          paint_filter_builder::PopulateSourceGraphicImageFilters(
              reference_filter->GetSourceGraphic(), nullptr,
              current_interpolation_space);

          FilterEffect* filter_effect = reference_filter->LastEffect();
          current_interpolation_space =
              filter_effect->OperatingInterpolationSpace();
          auto paint_filter = paint_filter_builder::Build(
              filter_effect, current_interpolation_space);
          if (!paint_filter)
            continue;
          filters.AppendReferenceFilter(std::move(paint_filter));
        }
        reference_operation.SetFilter(reference_filter);
        break;
      }
      case FilterOperation::GRAYSCALE:
      case FilterOperation::SEPIA:
      case FilterOperation::SATURATE:
      case FilterOperation::HUE_ROTATE: {
        float amount = ToBasicColorMatrixFilterOperation(*op).Amount();
        switch (op->GetType()) {
          case FilterOperation::GRAYSCALE:
            filters.AppendGrayscaleFilter(amount);
            break;
          case FilterOperation::SEPIA:
            filters.AppendSepiaFilter(amount);
            break;
          case FilterOperation::SATURATE:
            filters.AppendSaturateFilter(amount);
            break;
          case FilterOperation::HUE_ROTATE:
            filters.AppendHueRotateFilter(amount);
            break;
          default:
            NOTREACHED();
        }
        break;
      }
      case FilterOperation::INVERT:
      case FilterOperation::OPACITY:
      case FilterOperation::BRIGHTNESS:
      case FilterOperation::CONTRAST: {
        float amount = ToBasicComponentTransferFilterOperation(*op).Amount();
        switch (op->GetType()) {
          case FilterOperation::INVERT:
            filters.AppendInvertFilter(amount);
            break;
          case FilterOperation::OPACITY:
            filters.AppendOpacityFilter(amount);
            break;
          case FilterOperation::BRIGHTNESS:
            filters.AppendBrightnessFilter(amount);
            break;
          case FilterOperation::CONTRAST:
            filters.AppendContrastFilter(amount);
            break;
          default:
            NOTREACHED();
        }
        break;
      }
      case FilterOperation::BLUR: {
        float pixel_radius =
            ToBlurFilterOperation(*op).StdDeviation().GetFloatValue();
        filters.AppendBlurFilter(pixel_radius);
        break;
      }
      case FilterOperation::DROP_SHADOW: {
        const ShadowData& shadow = ToDropShadowFilterOperation(*op).Shadow();
        filters.AppendDropShadowFilter(FlooredIntPoint(shadow.Location()),
                                       shadow.Blur(),
                                       shadow.GetColor().GetColor());
        break;
      }
      case FilterOperation::BOX_REFLECT: {
        // TODO(jbroman): Consider explaining box reflect to the compositor,
        // instead of calling this a "reference filter".
        const auto& reflection = ToBoxReflectFilterOperation(*op).Reflection();
        filters.AppendReferenceFilter(
            paint_filter_builder::BuildBoxReflectFilter(reflection, nullptr));
        break;
      }
      case FilterOperation::NONE:
        break;
    }
  }
  if (current_interpolation_space != kInterpolationSpaceSRGB) {
    // Transform to device color space at the end of processing, if required.
    sk_sp<PaintFilter> filter =
        paint_filter_builder::TransformInterpolationSpace(
            nullptr, current_interpolation_space, kInterpolationSpaceSRGB);
    filters.AppendReferenceFilter(std::move(filter));
  }

  if (!filters.IsEmpty())
    filters.SetReferenceBox(reference_box_);

  return filters;
}

Filter* FilterEffectBuilder::BuildReferenceFilter(
    const ReferenceFilterOperation& reference_operation,
    FilterEffect* previous_effect) const {
  SVGResource* resource = reference_operation.Resource();
  if (auto* filter =
          ToSVGFilterElementOrNull(resource ? resource->Target() : nullptr))
    return BuildReferenceFilter(*filter, previous_effect);
  return nullptr;
}

Filter* FilterEffectBuilder::BuildReferenceFilter(
    SVGFilterElement& filter_element,
    FilterEffect* previous_effect,
    SVGFilterGraphNodeMap* node_map) const {
  FloatRect filter_region =
      SVGLengthContext::ResolveRectangle<SVGFilterElement>(
          &filter_element,
          filter_element.filterUnits()->CurrentValue()->EnumValue(),
          reference_box_);
  // TODO(fs): We rely on the presence of a node map here to opt-in to the
  // check for an empty filter region. The reason for this is that we lack a
  // viewport to resolve against for HTML content. This is crbug.com/512453.
  if (node_map && filter_region.IsEmpty())
    return nullptr;

  bool primitive_bounding_box_mode =
      filter_element.primitiveUnits()->CurrentValue()->EnumValue() ==
      SVGUnitTypes::kSvgUnitTypeObjectboundingbox;
  Filter::UnitScaling unit_scaling =
      primitive_bounding_box_mode ? Filter::kBoundingBox : Filter::kUserSpace;
  Filter* result =
      Filter::Create(reference_box_, filter_region, zoom_, unit_scaling);
  if (!previous_effect)
    previous_effect = result->GetSourceGraphic();
  SVGFilterBuilder builder(previous_effect, node_map, fill_flags_,
                           stroke_flags_);
  builder.BuildGraph(result, filter_element, reference_box_);
  result->SetLastEffect(builder.LastEffect());
  return result;
}

}  // namespace blink
