/*
 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "platform/graphics/filters/FEDisplacementMap.h"

#include "SkDisplacementMapEffect.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/graphics/filters/PaintFilterBuilder.h"
#include "platform/text/TextStream.h"

namespace blink {

FEDisplacementMap::FEDisplacementMap(Filter* filter,
                                     ChannelSelectorType x_channel_selector,
                                     ChannelSelectorType y_channel_selector,
                                     float scale)
    : FilterEffect(filter),
      x_channel_selector_(x_channel_selector),
      y_channel_selector_(y_channel_selector),
      scale_(scale) {}

FEDisplacementMap* FEDisplacementMap::Create(
    Filter* filter,
    ChannelSelectorType x_channel_selector,
    ChannelSelectorType y_channel_selector,
    float scale) {
  return new FEDisplacementMap(filter, x_channel_selector, y_channel_selector,
                               scale);
}

FloatRect FEDisplacementMap::MapEffect(const FloatRect& rect) const {
  FloatRect result = rect;
  result.InflateX(GetFilter()->ApplyHorizontalScale(std::abs(scale_) / 2));
  result.InflateY(GetFilter()->ApplyVerticalScale(std::abs(scale_) / 2));
  return result;
}

FloatRect FEDisplacementMap::MapInputs(const FloatRect& rect) const {
  return InputEffect(0)->MapRect(rect);
}

ChannelSelectorType FEDisplacementMap::XChannelSelector() const {
  return x_channel_selector_;
}

bool FEDisplacementMap::SetXChannelSelector(
    const ChannelSelectorType x_channel_selector) {
  if (x_channel_selector_ == x_channel_selector)
    return false;
  x_channel_selector_ = x_channel_selector;
  return true;
}

ChannelSelectorType FEDisplacementMap::YChannelSelector() const {
  return y_channel_selector_;
}

bool FEDisplacementMap::SetYChannelSelector(
    const ChannelSelectorType y_channel_selector) {
  if (y_channel_selector_ == y_channel_selector)
    return false;
  y_channel_selector_ = y_channel_selector;
  return true;
}

float FEDisplacementMap::Scale() const {
  return scale_;
}

bool FEDisplacementMap::SetScale(float scale) {
  if (scale_ == scale)
    return false;
  scale_ = scale;
  return true;
}

static SkDisplacementMapEffect::ChannelSelectorType ToSkiaMode(
    ChannelSelectorType type) {
  switch (type) {
    case CHANNEL_R:
      return SkDisplacementMapEffect::kR_ChannelSelectorType;
    case CHANNEL_G:
      return SkDisplacementMapEffect::kG_ChannelSelectorType;
    case CHANNEL_B:
      return SkDisplacementMapEffect::kB_ChannelSelectorType;
    case CHANNEL_A:
      return SkDisplacementMapEffect::kA_ChannelSelectorType;
    case CHANNEL_UNKNOWN:
    default:
      return SkDisplacementMapEffect::kUnknown_ChannelSelectorType;
  }
}

sk_sp<PaintFilter> FEDisplacementMap::CreateImageFilter() {
  sk_sp<PaintFilter> color =
      PaintFilterBuilder::Build(InputEffect(0), OperatingInterpolationSpace());
  // FEDisplacementMap must be a pass-through filter if
  // the origin is tainted. See:
  // https://drafts.fxtf.org/filter-effects/#fedisplacemnentmap-restrictions.
  if (InputEffect(1)->OriginTainted())
    return color;

  sk_sp<PaintFilter> displ =
      PaintFilterBuilder::Build(InputEffect(1), OperatingInterpolationSpace());
  SkDisplacementMapEffect::ChannelSelectorType type_x =
      ToSkiaMode(x_channel_selector_);
  SkDisplacementMapEffect::ChannelSelectorType type_y =
      ToSkiaMode(y_channel_selector_);
  PaintFilter::CropRect crop_rect = GetCropRect();
  // FIXME : Only applyHorizontalScale is used and applyVerticalScale is ignored
  // This can be fixed by adding a 2nd scale parameter to
  // DisplacementMapEffectPaintFilter.
  return sk_make_sp<DisplacementMapEffectPaintFilter>(
      type_x, type_y,
      SkFloatToScalar(GetFilter()->ApplyHorizontalScale(scale_)),
      std::move(displ), std::move(color), &crop_rect);
}

static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) {
  switch (type) {
    case CHANNEL_UNKNOWN:
      ts << "UNKNOWN";
      break;
    case CHANNEL_R:
      ts << "RED";
      break;
    case CHANNEL_G:
      ts << "GREEN";
      break;
    case CHANNEL_B:
      ts << "BLUE";
      break;
    case CHANNEL_A:
      ts << "ALPHA";
      break;
  }
  return ts;
}

TextStream& FEDisplacementMap::ExternalRepresentation(TextStream& ts,
                                                      int indent) const {
  WriteIndent(ts, indent);
  ts << "[feDisplacementMap";
  FilterEffect::ExternalRepresentation(ts);
  ts << " scale=\"" << scale_ << "\" "
     << "xChannelSelector=\"" << x_channel_selector_ << "\" "
     << "yChannelSelector=\"" << y_channel_selector_ << "\"]\n";
  InputEffect(0)->ExternalRepresentation(ts, indent + 1);
  InputEffect(1)->ExternalRepresentation(ts, indent + 1);
  return ts;
}

}  // namespace blink
