// Copyright 2017 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 "cc/paint/paint_shader.h"

#include "base/atomic_sequence_num.h"
#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_op_writer.h"
#include "cc/paint/paint_record.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/effects/SkGradientShader.h"

namespace cc {
namespace {
base::AtomicSequenceNumber g_next_shader_id;

sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record,
                             const SkRect& bounds,
                             const gfx::SizeF* raster_scale,
                             ImageProvider* image_provider) {
  SkPictureRecorder recorder;
  SkCanvas* canvas =
      recorder.beginRecording(SkRect::MakeWH(bounds.width(), bounds.height()));
  canvas->translate(-bounds.fLeft, -bounds.fTop);
  if (raster_scale)
    canvas->scale(raster_scale->width(), raster_scale->height());
  record->Playback(canvas, PlaybackParams(image_provider));
  return recorder.finishRecordingAsPicture();
}

bool CompareMatrices(const SkMatrix& a,
                     const SkMatrix& b,
                     bool ignore_scaling_differences) {
  if (!ignore_scaling_differences)
    return PaintOp::AreSkMatricesEqual(a, b);

  SkSize scale;
  SkMatrix a_without_scale;
  SkMatrix b_without_scale;

  const bool decomposes = a.decomposeScale(&scale, &a_without_scale);
  if (decomposes != b.decomposeScale(&scale, &b_without_scale))
    return false;

  if (!decomposes)
    return true;
  return PaintOp::AreSkMatricesEqual(a_without_scale, b_without_scale);
}

}  // namespace

const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1;

sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kColor));

  // Just one color. Store it in the fallback color. Easy.
  shader->fallback_color_ = color;

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakeLinearGradient(const SkPoint points[],
                                                   const SkColor colors[],
                                                   const SkScalar pos[],
                                                   int count,
                                                   SkShader::TileMode mode,
                                                   uint32_t flags,
                                                   const SkMatrix* local_matrix,
                                                   SkColor fallback_color) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kLinearGradient));

  // There are always two points, the start and the end.
  shader->start_point_ = points[0];
  shader->end_point_ = points[1];
  shader->SetColorsAndPositions(colors, pos, count);
  shader->SetMatrixAndTiling(local_matrix, mode, mode);
  shader->SetFlagsAndFallback(flags, fallback_color);

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakeRadialGradient(const SkPoint& center,
                                                   SkScalar radius,
                                                   const SkColor colors[],
                                                   const SkScalar pos[],
                                                   int count,
                                                   SkShader::TileMode mode,
                                                   uint32_t flags,
                                                   const SkMatrix* local_matrix,
                                                   SkColor fallback_color) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kRadialGradient));

  shader->center_ = center;
  shader->start_radius_ = shader->end_radius_ = radius;
  shader->SetColorsAndPositions(colors, pos, count);
  shader->SetMatrixAndTiling(local_matrix, mode, mode);
  shader->SetFlagsAndFallback(flags, fallback_color);

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakeTwoPointConicalGradient(
    const SkPoint& start,
    SkScalar start_radius,
    const SkPoint& end,
    SkScalar end_radius,
    const SkColor colors[],
    const SkScalar pos[],
    int count,
    SkShader::TileMode mode,
    uint32_t flags,
    const SkMatrix* local_matrix,
    SkColor fallback_color) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kTwoPointConicalGradient));

  shader->start_point_ = start;
  shader->end_point_ = end;
  shader->start_radius_ = start_radius;
  shader->end_radius_ = end_radius;
  shader->SetColorsAndPositions(colors, pos, count);
  shader->SetMatrixAndTiling(local_matrix, mode, mode);
  shader->SetFlagsAndFallback(flags, fallback_color);

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx,
                                                  SkScalar cy,
                                                  const SkColor colors[],
                                                  const SkScalar pos[],
                                                  int color_count,
                                                  SkShader::TileMode mode,
                                                  SkScalar start_degrees,
                                                  SkScalar end_degrees,
                                                  uint32_t flags,
                                                  const SkMatrix* local_matrix,
                                                  SkColor fallback_color) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kSweepGradient));

  shader->center_ = SkPoint::Make(cx, cy);
  shader->start_degrees_ = start_degrees;
  shader->end_degrees_ = end_degrees;
  shader->SetColorsAndPositions(colors, pos, color_count);
  shader->SetMatrixAndTiling(local_matrix, mode, mode);
  shader->SetFlagsAndFallback(flags, fallback_color);

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakeImage(const PaintImage& image,
                                          SkShader::TileMode tx,
                                          SkShader::TileMode ty,
                                          const SkMatrix* local_matrix) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kImage));

  shader->image_ = image;
  shader->SetMatrixAndTiling(local_matrix, tx, ty);

  shader->CreateSkShader();
  return shader;
}

sk_sp<PaintShader> PaintShader::MakePaintRecord(
    sk_sp<PaintRecord> record,
    const SkRect& tile,
    SkShader::TileMode tx,
    SkShader::TileMode ty,
    const SkMatrix* local_matrix,
    ScalingBehavior scaling_behavior) {
  sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord));

  shader->record_ = std::move(record);
  shader->id_ = g_next_shader_id.GetNext();
  shader->tile_ = tile;
  shader->scaling_behavior_ = scaling_behavior;
  shader->SetMatrixAndTiling(local_matrix, tx, ty);

  shader->CreateSkShader();
  return shader;
}

// static
size_t PaintShader::GetSerializedSize(const PaintShader* shader) {
  size_t bool_size = sizeof(bool);
  if (!shader)
    return bool_size;

  return bool_size + sizeof(shader->shader_type_) + sizeof(shader->flags_) +
         sizeof(shader->end_radius_) + sizeof(shader->start_radius_) +
         sizeof(shader->tx_) + sizeof(shader->ty_) +
         sizeof(shader->fallback_color_) + sizeof(shader->scaling_behavior_) +
         bool_size + sizeof(*shader->local_matrix_) + sizeof(shader->center_) +
         sizeof(shader->tile_) + sizeof(shader->start_point_) +
         sizeof(shader->end_point_) + sizeof(shader->start_degrees_) +
         sizeof(shader->end_degrees_) +
         PaintOpWriter::GetImageSize(shader->image_) +
         PaintOpWriter::GetImageSize(shader->image_) + bool_size +
         sizeof(shader->id_) +
         PaintOpWriter::GetRecordSize(shader->record_.get()) +
         sizeof(shader->colors_.size()) +
         shader->colors_.size() * sizeof(SkColor) +
         sizeof(shader->positions_.size()) +
         shader->positions_.size() * sizeof(SkScalar);
}

PaintShader::PaintShader(Type type) : shader_type_(type) {}
PaintShader::~PaintShader() = default;

bool PaintShader::has_discardable_images() const {
  return (image_ && image_.IsLazyGenerated()) ||
         (record_ && record_->HasDiscardableImages());
}

bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm,
                                           SkRect* tile_rect) const {
  DCHECK_EQ(shader_type_, Type::kPaintRecord);

  // If we are using a fixed scale, the record is rasterized with the original
  // tile size and scaling is applied to the generated output.
  if (scaling_behavior_ == ScalingBehavior::kFixedScale) {
    *tile_rect = tile_;
    return true;
  }

  SkMatrix matrix = ctm;
  if (local_matrix_.has_value())
    matrix.preConcat(local_matrix_.value());

  SkSize scale;
  if (!matrix.decomposeScale(&scale)) {
    // Decomposition failed, use an approximation.
    scale.set(SkScalarSqrt(matrix.getScaleX() * matrix.getScaleX() +
                           matrix.getSkewX() * matrix.getSkewX()),
              SkScalarSqrt(matrix.getScaleY() * matrix.getScaleY() +
                           matrix.getSkewY() * matrix.getSkewY()));
  }

  SkScalar tile_area =
      tile_.width() * tile_.height() * scale.width() * scale.height();

  // Clamp the tile size to about 4M pixels.
  // TODO(khushalsagar): We need to consider the max texture size as well.
  static const SkScalar kMaxTileArea = 2048 * 2048;
  if (tile_area > kMaxTileArea) {
    SkScalar clamp_scale = SkScalarSqrt(kMaxTileArea / tile_area);
    scale.set(clamp_scale, clamp_scale);
  }

  *tile_rect = SkRect::MakeXYWH(
      tile_.fLeft * scale.width(), tile_.fTop * scale.height(),
      SkScalarCeilToInt(SkScalarAbs(scale.width() * tile_.width())),
      SkScalarCeilToInt(SkScalarAbs(scale.height() * tile_.height())));

  if (tile_rect->isEmpty())
    return false;

  return true;
}

sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord(
    const SkMatrix& ctm,
    gfx::SizeF* raster_scale) const {
  DCHECK_EQ(shader_type_, Type::kPaintRecord);

  // For creating a decoded PaintRecord shader, we need to do the following:
  // 1) Figure out the scale at which the record should be rasterization given
  //    the ctm and local_matrix on the shader.
  // 2) Transform this record to an SkPicture with this scale and replace
  //    encoded images in this record with decodes from the ImageProvider. This
  //    is done by setting the raster_matrix_ for this shader to be used
  //    in GetSkShader.
  // 3) Since the SkShader will use a scaled SkPicture, we use a kFixedScale for
  //    the decoded shader which creates an SkPicture backed SkImage for
  //    creating the decoded SkShader.
  // Note that the scaling logic here is replicated from
  // SkPictureShader::refBitmapShader.
  SkRect tile_rect;
  if (!GetRasterizationTileRect(ctm, &tile_rect))
    return nullptr;

  sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord));
  shader->record_ = record_;
  shader->id_ = id_;
  shader->tile_ = tile_rect;
  // Use a fixed scale since we have already scaled the tile rect and fixed the
  // raster scale.
  shader->scaling_behavior_ = ScalingBehavior::kFixedScale;
  shader->tx_ = tx_;
  shader->ty_ = ty_;

  *raster_scale =
      gfx::SizeF(SkIntToScalar(tile_rect.width()) / tile_.width(),
                 SkIntToScalar(tile_rect.height()) / tile_.height());
  shader->local_matrix_ = GetLocalMatrix();
  shader->local_matrix_->preScale(1 / raster_scale->width(),
                                  1 / raster_scale->height());

  return shader;
}

sk_sp<PaintShader> PaintShader::CreateDecodedImage(
    const SkMatrix& ctm,
    SkFilterQuality quality,
    ImageProvider* image_provider,
    uint32_t* transfer_cache_entry_id,
    SkFilterQuality* raster_quality,
    bool* needs_mips) const {
  DCHECK_EQ(shader_type_, Type::kImage);
  if (!image_)
    return nullptr;

  SkMatrix total_image_matrix = GetLocalMatrix();
  total_image_matrix.preConcat(ctm);
  SkRect src_rect = SkRect::MakeIWH(image_.width(), image_.height());
  SkIRect int_src_rect;
  src_rect.roundOut(&int_src_rect);
  DrawImage draw_image(image_, int_src_rect, quality, total_image_matrix);
  auto decoded_draw_image = image_provider->GetDecodedDrawImage(draw_image);
  if (!decoded_draw_image)
    return nullptr;

  auto decoded_image = decoded_draw_image.decoded_image();
  SkMatrix final_matrix = GetLocalMatrix();
  bool need_scale = !decoded_image.is_scale_adjustment_identity();
  if (need_scale) {
    final_matrix.preScale(1.f / decoded_image.scale_adjustment().width(),
                          1.f / decoded_image.scale_adjustment().height());
  }

  PaintImage decoded_paint_image;
  if (decoded_image.transfer_cache_entry_id()) {
    decoded_paint_image = image_;
    *transfer_cache_entry_id = *decoded_image.transfer_cache_entry_id();
  } else {
    DCHECK(decoded_image.image());

    sk_sp<SkImage> sk_image =
        sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get()));
    decoded_paint_image =
        PaintImageBuilder::WithDefault()
            .set_id(image_.stable_id())
            .set_image(std::move(sk_image), image_.content_id())
            .TakePaintImage();
  }

  // TODO(khushalsagar): Remove filter quality from DecodedDrawImage. All we
  // want to do is cap the filter quality used, but Gpu and Sw cache have
  // different behaviour. D:
  *raster_quality = decoded_image.filter_quality();
  *needs_mips = decoded_image.transfer_cache_entry_needs_mips();
  return PaintShader::MakeImage(decoded_paint_image, tx_, ty_, &final_matrix);
}

sk_sp<SkShader> PaintShader::GetSkShader() const {
  return cached_shader_;
}

void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale,
                                 ImageProvider* image_provider) {
  DCHECK(!cached_shader_);

  switch (shader_type_) {
    case Type::kColor:
      // This will be handled by the fallback check below.
      break;
    case Type::kLinearGradient: {
      SkPoint points[2] = {start_point_, end_point_};
      cached_shader_ = SkGradientShader::MakeLinear(
          points, colors_.data(),
          positions_.empty() ? nullptr : positions_.data(),
          static_cast<int>(colors_.size()), tx_, flags_,
          base::OptionalOrNullptr(local_matrix_));
      break;
    }
    case Type::kRadialGradient:
      cached_shader_ = SkGradientShader::MakeRadial(
          center_, start_radius_, colors_.data(),
          positions_.empty() ? nullptr : positions_.data(),
          static_cast<int>(colors_.size()), tx_, flags_,
          base::OptionalOrNullptr(local_matrix_));
      break;
    case Type::kTwoPointConicalGradient:
      cached_shader_ = SkGradientShader::MakeTwoPointConical(
          start_point_, start_radius_, end_point_, end_radius_, colors_.data(),
          positions_.empty() ? nullptr : positions_.data(),
          static_cast<int>(colors_.size()), tx_, flags_,
          base::OptionalOrNullptr(local_matrix_));
      break;
    case Type::kSweepGradient:
      cached_shader_ = SkGradientShader::MakeSweep(
          center_.x(), center_.y(), colors_.data(),
          positions_.empty() ? nullptr : positions_.data(),
          static_cast<int>(colors_.size()), tx_, start_degrees_, end_degrees_,
          flags_, base::OptionalOrNullptr(local_matrix_));
      break;
    case Type::kImage:
      if (image_) {
        cached_shader_ = image_.GetSkImage()->makeShader(
            tx_, ty_, base::OptionalOrNullptr(local_matrix_));
      }
      break;
    case Type::kPaintRecord: {
      // Create a recording at the desired scale if this record has images which
      // have been decoded before raster.
      auto picture = ToSkPicture(record_, tile_, raster_scale, image_provider);

      switch (scaling_behavior_) {
        // For raster scale, we create a picture shader directly.
        case ScalingBehavior::kRasterAtScale:
          cached_shader_ = SkShader::MakePictureShader(
              std::move(picture), tx_, ty_,
              base::OptionalOrNullptr(local_matrix_), nullptr);
          break;
        // For fixed scale, we create an image shader with an image backed by
        // the picture.
        case ScalingBehavior::kFixedScale: {
          auto image = SkImage::MakeFromPicture(
              std::move(picture), SkISize::Make(tile_.width(), tile_.height()),
              nullptr, nullptr, SkImage::BitDepth::kU8,
              SkColorSpace::MakeSRGB());
          cached_shader_ = image->makeShader(
              tx_, ty_, base::OptionalOrNullptr(local_matrix_));
          break;
        }
      }
      break;
    }
    case Type::kShaderCount:
      NOTREACHED();
      break;
  }

  // If we didn't create a shader for whatever reason, create a fallback color
  // one.
  if (!cached_shader_)
    cached_shader_ = SkShader::MakeColorShader(fallback_color_);
}

void PaintShader::SetColorsAndPositions(const SkColor* colors,
                                        const SkScalar* positions,
                                        int count) {
#if DCHECK_IS_ON()
  static const int kMaxShaderColorsSupported = 10000;
  DCHECK_GE(count, 2);
  DCHECK_LE(count, kMaxShaderColorsSupported);
#endif
  colors_.assign(colors, colors + count);
  if (positions)
    positions_.assign(positions, positions + count);
}

void PaintShader::SetMatrixAndTiling(const SkMatrix* matrix,
                                     SkShader::TileMode tx,
                                     SkShader::TileMode ty) {
  if (matrix)
    local_matrix_ = *matrix;
  tx_ = tx;
  ty_ = ty;
}

void PaintShader::SetFlagsAndFallback(uint32_t flags, SkColor fallback_color) {
  flags_ = flags;
  fallback_color_ = fallback_color;
}

bool PaintShader::IsOpaque() const {
  // TODO(enne): don't create a shader to answer this.
  return GetSkShader()->isOpaque();
}

bool PaintShader::IsValid() const {
  // If we managed to create a shader already, then we should be valid.
  if (cached_shader_)
    return true;

  switch (shader_type_) {
    case Type::kColor:
      return true;
    case Type::kSweepGradient:
      if (!std::isfinite(start_degrees_) || !std::isfinite(end_degrees_) ||
          start_degrees_ >= end_degrees_) {
        return false;
      }
      FALLTHROUGH;
    case Type::kLinearGradient:
    case Type::kRadialGradient:
    case Type::kTwoPointConicalGradient:
      return colors_.size() >= 2 &&
             (positions_.empty() || positions_.size() == colors_.size());
    case Type::kImage:
      // We may not be able to decode the image, in which case it would be
      // false, but that would still make a valid shader.
      return true;
    case Type::kPaintRecord:
      return !!record_;
    case Type::kShaderCount:
      return false;
  }
  return false;
}

bool PaintShader::operator==(const PaintShader& other) const {
  if (shader_type_ != other.shader_type_)
    return false;

  // Record and image shaders are scaled during serialization.
  const bool ignore_scaling_differences =
      shader_type_ == PaintShader::Type::kPaintRecord ||
      shader_type_ == PaintShader::Type::kImage;

  // Variables that all shaders use.
  const SkMatrix& local_matrix = local_matrix_ ? *local_matrix_ : SkMatrix::I();
  const SkMatrix& other_local_matrix =
      other.local_matrix_ ? *other.local_matrix_ : SkMatrix::I();
  if (!CompareMatrices(local_matrix, other_local_matrix,
                       ignore_scaling_differences)) {
    return false;
  }

  if (fallback_color_ != other.fallback_color_)
    return false;
  if (flags_ != other.flags_)
    return false;
  if (tx_ != other.tx_)
    return false;
  if (ty_ != other.ty_)
    return false;

  if (!ignore_scaling_differences &&
      scaling_behavior_ != other.scaling_behavior_)
    return false;

  // Variables that only some shaders use.
  switch (shader_type_) {
    case Type::kColor:
      break;
    case Type::kSweepGradient:
      if (!PaintOp::AreEqualEvenIfNaN(start_degrees_, other.start_degrees_))
        return false;
      if (!PaintOp::AreEqualEvenIfNaN(end_degrees_, other.end_degrees_))
        return false;
      FALLTHROUGH;
    case Type::kLinearGradient:
    case Type::kRadialGradient:
    case Type::kTwoPointConicalGradient:
      if (!PaintOp::AreEqualEvenIfNaN(start_radius_, other.start_radius_))
        return false;
      if (!PaintOp::AreEqualEvenIfNaN(end_radius_, other.end_radius_))
        return false;
      if (!PaintOp::AreSkPointsEqual(center_, other.center_))
        return false;
      if (!PaintOp::AreSkPointsEqual(start_point_, other.start_point_))
        return false;
      if (!PaintOp::AreSkPointsEqual(end_point_, other.end_point_))
        return false;
      if (colors_ != other.colors_)
        return false;
      if (positions_.size() != other.positions_.size())
        return false;
      for (size_t i = 0; i < positions_.size(); ++i) {
        if (!PaintOp::AreEqualEvenIfNaN(positions_[i], other.positions_[i]))
          return false;
      }
      break;
    case Type::kImage:
      // TODO(enne): add comparison of images once those are serialized.
      break;
    case Type::kPaintRecord:
      // If we have a record but not other.record, or vice versa, then shaders
      // aren't the same.
      if (!record_ != !other.record_)
        return false;
      // tile_ and record_ intentionally omitted since they are modified on the
      // serialized shader based on the ctm.
      break;
    case Type::kShaderCount:
      break;
  }

  return true;
}

}  // namespace cc
