// Copyright (c) 2016 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 "ui/gfx/color_transform.h"

#include <algorithm>
#include <cmath>
#include <list>
#include <memory>
#include <sstream>

#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/third_party/skcms/skcms.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/icc_profile.h"
#include "ui/gfx/skia_color_space_util.h"
#include "ui/gfx/transform.h"

using std::abs;
using std::copysign;
using std::exp;
using std::log;
using std::max;
using std::min;
using std::pow;
using std::sqrt;
using std::endl;

namespace gfx {

namespace {

void InitStringStream(std::stringstream* ss) {
  ss->imbue(std::locale::classic());
  ss->precision(8);
  *ss << std::scientific;
}

std::string Str(float f) {
  std::stringstream ss;
  InitStringStream(&ss);
  ss << f;
  return ss.str();
}

Transform Invert(const Transform& t) {
  Transform ret = t;
  if (!t.GetInverse(&ret)) {
    LOG(ERROR) << "Inverse should always be possible.";
  }
  return ret;
}

float FromLinear(ColorSpace::TransferID id, float v) {
  switch (id) {
    case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
      // Should already be handled.
      break;

    case ColorSpace::TransferID::LOG:
      if (v < 0.01f)
        return 0.0f;
      return 1.0f + log(v) / log(10.0f) / 2.0f;

    case ColorSpace::TransferID::LOG_SQRT:
      if (v < sqrt(10.0f) / 1000.0f)
        return 0.0f;
      return 1.0f + log(v) / log(10.0f) / 2.5f;

    case ColorSpace::TransferID::IEC61966_2_4: {
      float a = 1.099296826809442f;
      float b = 0.018053968510807f;
      if (v < -b)
        return -a * pow(-v, 0.45f) + (a - 1.0f);
      else if (v <= b)
        return 4.5f * v;
      return a * pow(v, 0.45f) - (a - 1.0f);
    }

    case ColorSpace::TransferID::BT1361_ECG: {
      float a = 1.099f;
      float b = 0.018f;
      float l = 0.0045f;
      if (v < -l)
        return -(a * pow(-4.0f * v, 0.45f) + (a - 1.0f)) / 4.0f;
      else if (v <= b)
        return 4.5f * v;
      else
        return a * pow(v, 0.45f) - (a - 1.0f);
    }

    case ColorSpace::TransferID::SMPTEST2084: {
      // Go from scRGB levels to 0-1.
      v *= 80.0f / 10000.0f;
      v = max(0.0f, v);
      float m1 = (2610.0f / 4096.0f) / 4.0f;
      float m2 = (2523.0f / 4096.0f) * 128.0f;
      float c1 = 3424.0f / 4096.0f;
      float c2 = (2413.0f / 4096.0f) * 32.0f;
      float c3 = (2392.0f / 4096.0f) * 32.0f;
      float p = powf(v, m1);
      return powf((c1 + c2 * p) / (1.0f + c3 * p), m2);
    }

    // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
    case ColorSpace::TransferID::ARIB_STD_B67: {
      const float a = 0.17883277f;
      const float b = 0.28466892f;
      const float c = 0.55991073f;
      v = max(0.0f, v);
      if (v <= 1)
        return 0.5f * sqrt(v);
      return a * log(v - b) + c;
    }

    default:
      // Handled by SkColorSpaceTransferFn.
      break;
  }
  NOTREACHED();
  return 0;
}

float ToLinear(ColorSpace::TransferID id, float v) {
  switch (id) {
    case ColorSpace::TransferID::LOG:
      if (v < 0.0f)
        return 0.0f;
      return pow(10.0f, (v - 1.0f) * 2.0f);

    case ColorSpace::TransferID::LOG_SQRT:
      if (v < 0.0f)
        return 0.0f;
      return pow(10.0f, (v - 1.0f) * 2.5f);

    case ColorSpace::TransferID::IEC61966_2_4: {
      float a = 1.099296826809442f;
      // Equal to FromLinear(ColorSpace::TransferID::IEC61966_2_4, -a).
      float from_linear_neg_a = -1.047844f;
      // Equal to FromLinear(ColorSpace::TransferID::IEC61966_2_4, b).
      float from_linear_b = 0.081243f;
      if (v < from_linear_neg_a)
        return -pow((a - 1.0f - v) / a, 1.0f / 0.45f);
      else if (v <= from_linear_b)
        return v / 4.5f;
      return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
    }

    case ColorSpace::TransferID::BT1361_ECG: {
      float a = 1.099f;
      // Equal to FromLinear(ColorSpace::TransferID::BT1361_ECG, -l).
      float from_linear_neg_l = -0.020250f;
      // Equal to FromLinear(ColorSpace::TransferID::BT1361_ECG, b).
      float from_linear_b = 0.081000f;
      if (v < from_linear_neg_l)
        return -pow((1.0f - a - v * 4.0f) / a, 1.0f / 0.45f) / 4.0f;
      else if (v <= from_linear_b)
        return v / 4.5f;
      return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
    }

    case ColorSpace::TransferID::SMPTEST2084: {
      v = max(0.0f, v);
      float m1 = (2610.0f / 4096.0f) / 4.0f;
      float m2 = (2523.0f / 4096.0f) * 128.0f;
      float c1 = 3424.0f / 4096.0f;
      float c2 = (2413.0f / 4096.0f) * 32.0f;
      float c3 = (2392.0f / 4096.0f) * 32.0f;
      float p = pow(v, 1.0f / m2);
      v = powf(max(p - c1, 0.0f) / (c2 - c3 * p), 1.0f / m1);
      // This matches the scRGB definition that 1.0 means 80 nits.
      // TODO(hubbe): It would be *nice* if 1.0 meant more than that, but
      // that might be difficult to do right now.
      v *= 10000.0f / 80.0f;
      return v;
    }

    case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
      v = max(0.0f, v);
      return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f);

    // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
    case ColorSpace::TransferID::ARIB_STD_B67: {
      v = max(0.0f, v);
      const float a = 0.17883277f;
      const float b = 0.28466892f;
      const float c = 0.55991073f;
      if (v <= 0.5f)
        return (v * 2.0f) * (v * 2.0f);
      return exp((v - c) / a) + b;
    }

    default:
      // Handled by SkColorSpaceTransferFn.
      break;
  }
  NOTREACHED();
  return 0;
}

Transform GetTransferMatrix(const gfx::ColorSpace& color_space) {
  SkMatrix44 transfer_matrix;
  color_space.GetTransferMatrix(&transfer_matrix);
  return Transform(transfer_matrix);
}

Transform GetRangeAdjustMatrix(const gfx::ColorSpace& color_space) {
  SkMatrix44 range_adjust_matrix;
  color_space.GetRangeAdjustMatrix(&range_adjust_matrix);
  return Transform(range_adjust_matrix);
}

Transform GetPrimaryTransform(const gfx::ColorSpace& color_space) {
  SkMatrix44 primary_matrix;
  color_space.GetPrimaryMatrix(&primary_matrix);
  return Transform(primary_matrix);
}

}  // namespace

class ColorTransformMatrix;
class ColorTransformSkTransferFn;
class ColorTransformFromLinear;
class ColorTransformToBT2020CL;
class ColorTransformFromBT2020CL;
class ColorTransformNull;
class SkiaColorTransform;

class ColorTransformStep {
 public:
  ColorTransformStep() {}
  virtual ~ColorTransformStep() {}
  virtual ColorTransformFromLinear* GetFromLinear() { return nullptr; }
  virtual ColorTransformToBT2020CL* GetToBT2020CL() { return nullptr; }
  virtual ColorTransformFromBT2020CL* GetFromBT2020CL() { return nullptr; }
  virtual ColorTransformSkTransferFn* GetSkTransferFn() { return nullptr; }
  virtual ColorTransformMatrix* GetMatrix() { return nullptr; }
  virtual ColorTransformNull* GetNull() { return nullptr; }
  virtual SkiaColorTransform* GetSkia() { return nullptr; }

  // Join methods, returns true if the |next| transform was successfully
  // assimilated into |this|.
  // If Join() returns true, |next| is no longer needed and can be deleted.
  virtual bool Join(ColorTransformStep* next) { return false; }

  // Return true if this is a null transform.
  virtual bool IsNull() { return false; }
  virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0;
  virtual bool CanAppendShaderSource() { return false; }
  // In the shader, |hdr| will appear before |src|, so any helper functions that
  // are created should be put in |hdr|. Any helper functions should have
  // |step_index| included in the function name, to ensure that there are no
  // naming conflicts.
  virtual void AppendShaderSource(std::stringstream* hdr,
                                  std::stringstream* src,
                                  size_t step_index) const {
    NOTREACHED();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ColorTransformStep);
};

class ColorTransformInternal : public ColorTransform {
 public:
  ColorTransformInternal(const ColorSpace& src,
                         const ColorSpace& dst,
                         Intent intent);
  ~ColorTransformInternal() override;

  gfx::ColorSpace GetSrcColorSpace() const override { return src_; };
  gfx::ColorSpace GetDstColorSpace() const override { return dst_; };

  void Transform(TriStim* colors, size_t num) const override {
    for (const auto& step : steps_) {
      step->Transform(colors, num);
    }
  }
  bool CanGetShaderSource() const override;
  std::string GetShaderSource() const override;
  bool IsIdentity() const override { return steps_.empty(); }
  size_t NumberOfStepsForTesting() const override { return steps_.size(); }

 private:
  void AppendColorSpaceToColorSpaceTransform(ColorSpace src,
                                             const ColorSpace& dst,
                                             ColorTransform::Intent intent);
  void Simplify();

  // Retrieve the SkColorSpace for the ICC profile from which |color_space| was
  // created, only if that is a more precise than the parametric representation.
  sk_sp<SkColorSpace> GetSkColorSpaceIfNecessary(const ColorSpace& color_space);

  std::list<std::unique_ptr<ColorTransformStep>> steps_;
  gfx::ColorSpace src_;
  gfx::ColorSpace dst_;
};

class ColorTransformNull : public ColorTransformStep {
 public:
  ColorTransformNull* GetNull() override { return this; }
  bool IsNull() override { return true; }
  void Transform(ColorTransform::TriStim* color, size_t num) const override {}
  bool CanAppendShaderSource() override { return true; }
  void AppendShaderSource(std::stringstream* hdr,
                          std::stringstream* src,
                          size_t step_index) const override {}
};

class ColorTransformMatrix : public ColorTransformStep {
 public:
  explicit ColorTransformMatrix(const class Transform& matrix)
      : matrix_(matrix) {}
  ColorTransformMatrix* GetMatrix() override { return this; }
  bool Join(ColorTransformStep* next_untyped) override {
    ColorTransformMatrix* next = next_untyped->GetMatrix();
    if (!next)
      return false;
    class Transform tmp = next->matrix_;
    tmp *= matrix_;
    matrix_ = tmp;
    return true;
  }

  bool IsNull() override {
    return SkMatrixIsApproximatelyIdentity(matrix_.matrix());
  }

  void Transform(ColorTransform::TriStim* colors, size_t num) const override {
    for (size_t i = 0; i < num; i++)
      matrix_.TransformPoint(colors + i);
  }

  bool CanAppendShaderSource() override { return true; }

  void AppendShaderSource(std::stringstream* hdr,
                          std::stringstream* src,
                          size_t step_index) const override {
    const SkMatrix44& m = matrix_.matrix();
    *src << "  color = mat3(";
    *src << m.get(0, 0) << ", " << m.get(1, 0) << ", " << m.get(2, 0) << ",";
    *src << endl;
    *src << "               ";
    *src << m.get(0, 1) << ", " << m.get(1, 1) << ", " << m.get(2, 1) << ",";
    *src << endl;
    *src << "               ";
    *src << m.get(0, 2) << ", " << m.get(1, 2) << ", " << m.get(2, 2) << ")";
    *src << " * color;" << endl;

    // Only print the translational component if it isn't the identity.
    if (m.get(0, 3) != 0.f || m.get(1, 3) != 0.f || m.get(2, 3) != 0.f) {
      *src << "  color += vec3(";
      *src << m.get(0, 3) << ", " << m.get(1, 3) << ", " << m.get(2, 3);
      *src << ");" << endl;
    }
  }

 private:
  class Transform matrix_;
};

class ColorTransformPerChannelTransferFn : public ColorTransformStep {
 public:
  explicit ColorTransformPerChannelTransferFn(bool extended)
      : extended_(extended) {}

  void Transform(ColorTransform::TriStim* colors, size_t num) const override {
    for (size_t i = 0; i < num; i++) {
      ColorTransform::TriStim& c = colors[i];
      if (extended_) {
        c.set_x(copysign(Evaluate(abs(c.x())), c.x()));
        c.set_y(copysign(Evaluate(abs(c.y())), c.y()));
        c.set_z(copysign(Evaluate(abs(c.z())), c.z()));
      } else {
        c.set_x(Evaluate(c.x()));
        c.set_y(Evaluate(c.y()));
        c.set_z(Evaluate(c.z()));
      }
    }
  }

  void AppendShaderSource(std::stringstream* hdr,
                          std::stringstream* src,
                          size_t step_index) const override {
    *hdr << "float TransferFn" << step_index << "(float v) {" << endl;
    AppendTransferShaderSource(hdr);
    *hdr << "}" << endl;
    if (extended_) {
      *src << "  color.r = sign(color.r) * TransferFn" << step_index
           << "(abs(color.r));" << endl;
      *src << "  color.g = sign(color.g) * TransferFn" << step_index
           << "(abs(color.g));" << endl;
      *src << "  color.b = sign(color.b) * TransferFn" << step_index
           << "(abs(color.b));" << endl;
    } else {
      *src << "  color.r = TransferFn" << step_index << "(color.r);" << endl;
      *src << "  color.g = TransferFn" << step_index << "(color.g);" << endl;
      *src << "  color.b = TransferFn" << step_index << "(color.b);" << endl;
    }
  }

  virtual float Evaluate(float x) const = 0;
  // Populate the body of a shader function that takes a float v and returns
  // Evaluate(v).
  virtual void AppendTransferShaderSource(std::stringstream* src) const = 0;

 protected:
  // True if the transfer function is extended to be defined for all real
  // values by point symmetry.
  bool extended_ = false;
};

class ColorTransformSkTransferFn : public ColorTransformPerChannelTransferFn {
 public:
  explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn,
                                      bool extended)
      : ColorTransformPerChannelTransferFn(extended), fn_(fn) {}
  // ColorTransformStep implementation.
  ColorTransformSkTransferFn* GetSkTransferFn() override { return this; }
  bool Join(ColorTransformStep* next_untyped) override {
    ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn();
    if (!next)
      return false;
    if (!extended_ && !next->extended_ &&
        SkTransferFnsApproximatelyCancel(fn_, next->fn_)) {
      // Set to be the identity.
      fn_.fA = 1;
      fn_.fB = 0;
      fn_.fC = 1;
      fn_.fD = 0;
      fn_.fE = 0;
      fn_.fF = 0;
      fn_.fG = 1;
      return true;
    }
    return false;
  }
  bool CanAppendShaderSource() override { return true; }
  bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); }

  // ColorTransformPerChannelTransferFn implementation:
  float Evaluate(float v) const override {
    // Note that the sign-extension is performed by the caller.
    return SkTransferFnEvalUnclamped(fn_, v);
  }
  void AppendTransferShaderSource(std::stringstream* result) const override {
    const float kEpsilon = 1.f / 1024.f;

    // Construct the linear segment
    //   linear = C * x + F
    // Elide operations that will be close to the identity.
    std::string linear = "v";
    if (std::abs(fn_.fC - 1.f) > kEpsilon)
      linear = Str(fn_.fC) + " * " + linear;
    if (std::abs(fn_.fF) > kEpsilon)
      linear = linear + " + " + Str(fn_.fF);

    // Construct the nonlinear segment.
    //   nonlinear = pow(A * x + B, G) + E
    // Elide operations (especially the pow) that will be close to the
    // identity.
    std::string nonlinear = "v";
    if (std::abs(fn_.fA - 1.f) > kEpsilon)
      nonlinear = Str(fn_.fA) + " * " + nonlinear;
    if (std::abs(fn_.fB) > kEpsilon)
      nonlinear = nonlinear + " + " + Str(fn_.fB);
    if (std::abs(fn_.fG - 1.f) > kEpsilon)
      nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")";
    if (std::abs(fn_.fE) > kEpsilon)
      nonlinear = nonlinear + " + " + Str(fn_.fE);

    *result << "  if (v < " << Str(fn_.fD) << ")" << endl;
    *result << "    return " << linear << ";" << endl;
    *result << "  return " << nonlinear << ";" << endl;
  }

 private:
  SkColorSpaceTransferFn fn_;
};

class ColorTransformFromLinear : public ColorTransformPerChannelTransferFn {
 public:
  // ColorTransformStep implementation.
  explicit ColorTransformFromLinear(ColorSpace::TransferID transfer)
      : ColorTransformPerChannelTransferFn(false), transfer_(transfer) {}
  ColorTransformFromLinear* GetFromLinear() override { return this; }
  bool CanAppendShaderSource() override { return true; }
  bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }

  // ColorTransformPerChannelTransferFn implementation:
  float Evaluate(float v) const override { return FromLinear(transfer_, v); }
  void AppendTransferShaderSource(std::stringstream* src) const override {
    // This is a string-ized copy-paste from FromLinear.
    switch (transfer_) {
      case ColorSpace::TransferID::LOG:
        *src << "  if (v < 0.01)\n"
                "    return 0.0;\n"
                "  return 1.0 + log(v) / log(10.0) / 2.0;\n";
        return;
      case ColorSpace::TransferID::LOG_SQRT:
        *src << "  if (v < sqrt(10.0) / 1000.0)\n"
                "    return 0.0;\n"
                "  return 1.0 + log(v) / log(10.0) / 2.5;\n";
        return;
      case ColorSpace::TransferID::IEC61966_2_4:
        *src << "  float a = 1.099296826809442;\n"
                "  float b = 0.018053968510807;\n"
                "  if (v < -b)\n"
                "    return -a * pow(-v, 0.45) + (a - 1.0);\n"
                "  else if (v <= b)\n"
                "    return 4.5 * v;\n"
                "  return a * pow(v, 0.45) - (a - 1.0);\n";
        return;
      case ColorSpace::TransferID::BT1361_ECG:
        *src << "  float a = 1.099;\n"
                "  float b = 0.018;\n"
                "  float l = 0.0045;\n"
                "  if (v < -l)\n"
                "    return -(a * pow(-4.0 * v, 0.45) + (a - 1.0)) / 4.0;\n"
                "  else if (v <= b)\n"
                "    return 4.5 * v;\n"
                "  return a * pow(v, 0.45) - (a - 1.0);\n";
        return;
      case ColorSpace::TransferID::SMPTEST2084:
        *src << "  v *= 80.0 / 10000.0;\n"
                "  v = max(0.0, v);\n"
                "  float m1 = (2610.0 / 4096.0) / 4.0;\n"
                "  float m2 = (2523.0 / 4096.0) * 128.0;\n"
                "  float c1 = 3424.0 / 4096.0;\n"
                "  float c2 = (2413.0 / 4096.0) * 32.0;\n"
                "  float c3 = (2392.0 / 4096.0) * 32.0;\n"
                "  return pow((c1 + c2 * pow(v, m1)) / \n"
                "                 (1.0 + c3 * pow(v, m1)), m2);\n";
        return;
      case ColorSpace::TransferID::ARIB_STD_B67:
        *src << "  const float a = 0.17883277;\n"
                "  const float b = 0.28466892;\n"
                "  const float c = 0.55991073;\n"
                "  v = max(0.0, v);\n"
                "  if (v <= 1.0)\n"
                "    return 0.5 * sqrt(v);\n"
                "  return a * log(v - b) + c;\n";
        return;
      default:
        break;
    }
    NOTREACHED();
  }

 private:
  friend class ColorTransformToLinear;
  ColorSpace::TransferID transfer_;
};

class ColorTransformToLinear : public ColorTransformPerChannelTransferFn {
 public:
  explicit ColorTransformToLinear(ColorSpace::TransferID transfer)
      : ColorTransformPerChannelTransferFn(false), transfer_(transfer) {}
  // ColorTransformStep implementation:
  bool Join(ColorTransformStep* next_untyped) override {
    ColorTransformFromLinear* next = next_untyped->GetFromLinear();
    if (!next)
      return false;
    if (transfer_ == next->transfer_) {
      transfer_ = ColorSpace::TransferID::LINEAR;
      return true;
    }
    return false;
  }
  bool CanAppendShaderSource() override { return true; }
  bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }

  // ColorTransformPerChannelTransferFn implementation:
  float Evaluate(float v) const override { return ToLinear(transfer_, v); }
  void AppendTransferShaderSource(std::stringstream* src) const override {
    // This is a string-ized copy-paste from ToLinear.
    switch (transfer_) {
      case ColorSpace::TransferID::LOG:
        *src << "  if (v < 0.0)\n"
                "    return 0.0;\n"
                "  return pow(10.0, (v - 1.0) * 2.0);\n";
        return;
      case ColorSpace::TransferID::LOG_SQRT:
        *src << "  if (v < 0.0)\n"
                "    return 0.0;\n"
                "  return pow(10.0, (v - 1.0) * 2.5);\n";
        return;
      case ColorSpace::TransferID::IEC61966_2_4:
        *src << "  float a = 1.099296826809442;\n"
                "  float from_linear_neg_a = -1.047844;\n"
                "  float from_linear_b = 0.081243;\n"
                "  if (v < from_linear_neg_a)\n"
                "    return -pow((a - 1.0 - v) / a, 1.0 / 0.45);\n"
                "  else if (v <= from_linear_b)\n"
                "    return v / 4.5;\n"
                "  return pow((v + a - 1.0) / a, 1.0 / 0.45);\n";
        return;
      case ColorSpace::TransferID::BT1361_ECG:
        *src << "  float a = 1.099;\n"
                "  float from_linear_neg_l = -0.020250;\n"
                "  float from_linear_b = 0.081000;\n"
                "  if (v < from_linear_neg_l)\n"
                "    return -pow((1.0 - a - v * 4.0) / a, 1.0 / 0.45) / 4.0;\n"
                "  else if (v <= from_linear_b)\n"
                "    return v / 4.5;\n"
                "  return pow((v + a - 1.0) / a, 1.0 / 0.45);\n";
        return;
      case ColorSpace::TransferID::SMPTEST2084:
        *src << "  v = max(0.0, v);\n"
                "  float m1 = (2610.0 / 4096.0) / 4.0;\n"
                "  float m2 = (2523.0 / 4096.0) * 128.0;\n"
                "  float c1 = 3424.0 / 4096.0;\n"
                "  float c2 = (2413.0 / 4096.0) * 32.0;\n"
                "  float c3 = (2392.0 / 4096.0) * 32.0;\n"
                "  #ifdef GL_FRAGMENT_PRECISION_HIGH\n"
                "  highp float v2 = v;\n"
                "  #else\n"
                "  float v2 = v;\n"
                "  #endif\n"
                "  v2 = pow(max(pow(v2, 1.0 / m2) - c1, 0.0) /\n"
                "              (c2 - c3 * pow(v2, 1.0 / m2)), 1.0 / m1);\n"
                "  v = v2 * 10000.0 / 80.0;\n"
                "  return v;\n";
        return;
      case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
        *src << "  v = max(0.0, v);\n"
                "  return min(2.3 * pow(v, 2.8), v / 5.0 + 0.8);\n";
        return;
      case ColorSpace::TransferID::ARIB_STD_B67:
        *src << "  v = max(0.0, v);\n"
                "  float a = 0.17883277;\n"
                "  float b = 0.28466892;\n"
                "  float c = 0.55991073;\n"
                "  if (v <= 0.5)\n"
                "    return (v * 2.0) * (v * 2.0);\n"
                "  return exp((v - c) / a) + b;\n";
        return;
      default:
        break;
    }
    NOTREACHED();
  }

 private:
  ColorSpace::TransferID transfer_;
};

class ColorTransformSMPTEST2048NonHdrToLinear : public ColorTransformStep {
 public:
  // Assumes BT2020 primaries.
  static float Luma(const ColorTransform::TriStim& c) {
    return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f;
  }
  static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) {
    float maximum = max(max(c.x(), c.y()), c.z());
    if (maximum > 1.0f) {
      float l = Luma(c);
      c.Scale(1.0f / maximum);
      ColorTransform::TriStim white(1.0f, 1.0f, 1.0f);
      white.Scale((1.0f - 1.0f / maximum) * l / Luma(white));
      ColorTransform::TriStim black(0.0f, 0.0f, 0.0f);
      c += white - black;
    }
    return c;
  }
  void Transform(ColorTransform::TriStim* colors, size_t num) const override {
    for (size_t i = 0; i < num; i++) {
      ColorTransform::TriStim ret(
          ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].x()),
          ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].y()),
          ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].z()));
      if (Luma(ret) > 0.0) {
        ColorTransform::TriStim smpte2084(
            ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()),
            ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()),
            ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z()));
        smpte2084.Scale(Luma(ret) / Luma(smpte2084));
        ret = ClipToWhite(smpte2084);
      }
      colors[i] = ret;
    }
  }
};

// BT2020 Constant Luminance is different than most other
// ways to encode RGB values as YUV. The basic idea is that
// transfer functions are applied on the Y value instead of
// on the RGB values. However, running the transfer function
// on the U and V values doesn't make any sense since they
// are centered at 0.5. To work around this, the transfer function
// is applied to the Y, R and B values, and then the U and V
// values are calculated from that.
// In our implementation, the YUV->RGB matrix is used to
// convert YUV to RYB (the G value is replaced with an Y value.)
// Then we run the transfer function like normal, and finally
// this class is inserted as an extra step which takes calculates
// the U and V values.
class ColorTransformToBT2020CL : public ColorTransformStep {
 public:
  bool Join(ColorTransformStep* next_untyped) override {
    ColorTransformFromBT2020CL* next = next_untyped->GetFromBT2020CL();
    if (!next)
      return false;
    if (null_)
      return false;
    null_ = true;
    return true;
  }

  bool IsNull() override { return null_; }

  void Transform(ColorTransform::TriStim* RYB, size_t num) const override {
    for (size_t i = 0; i < num; i++) {
      float U, V;
      float B_Y = RYB[i].z() - RYB[i].y();
      if (B_Y <= 0) {
        U = B_Y / (-2.0 * -0.9702);
      } else {
        U = B_Y / (2.0 * 0.7910);
      }
      float R_Y = RYB[i].x() - RYB[i].y();
      if (R_Y <= 0) {
        V = R_Y / (-2.0 * -0.8591);
      } else {
        V = R_Y / (2.0 * 0.4969);
      }
      RYB[i] = ColorTransform::TriStim(RYB[i].y(), U + 0.5, V + 0.5);
    }
  }

 private:
  bool null_ = false;
};

// Inverse of ColorTransformToBT2020CL, see comment above for more info.
class ColorTransformFromBT2020CL : public ColorTransformStep {
 public:
  bool Join(ColorTransformStep* next_untyped) override {
    ColorTransformToBT2020CL* next = next_untyped->GetToBT2020CL();
    if (!next)
      return false;
    if (null_)
      return false;
    null_ = true;
    return true;
  }

  bool IsNull() override { return null_; }

  void Transform(ColorTransform::TriStim* YUV, size_t num) const override {
    if (null_)
      return;
    for (size_t i = 0; i < num; i++) {
      float Y = YUV[i].x();
      float U = YUV[i].y() - 0.5;
      float V = YUV[i].z() - 0.5;
      float B_Y, R_Y;
      if (U <= 0) {
        B_Y = U * (-2.0 * -0.9702);
      } else {
        B_Y = U * (2.0 * 0.7910);
      }
      if (V <= 0) {
        R_Y = V * (-2.0 * -0.8591);
      } else {
        R_Y = V * (2.0 * 0.4969);
      }
      // Return an RYB value, later steps will fix it.
      YUV[i] = ColorTransform::TriStim(R_Y + Y, Y, B_Y + Y);
    }
  }
  bool CanAppendShaderSource() override { return true; }
  void AppendShaderSource(std::stringstream* hdr,
                          std::stringstream* src,
                          size_t step_index) const override {
    *hdr << "vec3 BT2020_YUV_to_RYB_Step" << step_index << "(vec3 color) {"
         << endl;
    *hdr << "  float Y = color.x;" << endl;
    *hdr << "  float U = color.y - 0.5;" << endl;
    *hdr << "  float V = color.z - 0.5;" << endl;
    *hdr << "  float B_Y = 0.0;" << endl;
    *hdr << "  float R_Y = 0.0;" << endl;
    *hdr << "  if (U <= 0.0) {" << endl;
    *hdr << "    B_Y = U * (-2.0 * -0.9702);" << endl;
    *hdr << "  } else {" << endl;
    *hdr << "    B_Y = U * (2.0 * 0.7910);" << endl;
    *hdr << "  }" << endl;
    *hdr << "  if (V <= 0.0) {" << endl;
    *hdr << "    R_Y = V * (-2.0 * -0.8591);" << endl;
    *hdr << "  } else {" << endl;
    *hdr << "    R_Y = V * (2.0 * 0.4969);" << endl;
    *hdr << "  }" << endl;
    *hdr << "  return vec3(R_Y + Y, Y, B_Y + Y);" << endl;
    *hdr << "}" << endl;

    *src << "  color.rgb = BT2020_YUV_to_RYB_Step" << step_index
         << "(color.rgb);" << endl;
  }

 private:
  bool null_ = false;
};

void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform(
    ColorSpace src,
    const ColorSpace& dst,
    ColorTransform::Intent intent) {
  if (intent == ColorTransform::Intent::INTENT_PERCEPTUAL) {
    switch (src.transfer_) {
      case ColorSpace::TransferID::SMPTEST2084:
        if (!dst.IsHDR()) {
          // We don't have an HDR display, so replace SMPTE 2084 with
          // something that returns ranges more or less suitable for a normal
          // display.
          src.transfer_ = ColorSpace::TransferID::SMPTEST2084_NON_HDR;
        }
        break;

      case ColorSpace::TransferID::ARIB_STD_B67:
        if (!dst.IsHDR()) {
          // Interpreting HLG using a gamma 2.4 works reasonably well for SDR
          // displays.
          src.transfer_ = ColorSpace::TransferID::GAMMA24;
        }
        break;

      default:  // Do nothing
        break;
    }

    // TODO(hubbe): shrink gamuts here (never stretch gamuts)
  }

  steps_.push_back(
      std::make_unique<ColorTransformMatrix>(GetRangeAdjustMatrix(src)));

  if (src.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
    // BT2020 CL is a special case.
    steps_.push_back(std::make_unique<ColorTransformFromBT2020CL>());
  } else {
    steps_.push_back(
        std::make_unique<ColorTransformMatrix>(Invert(GetTransferMatrix(src))));
  }

  // If the target color space is not defined, just apply the adjust and
  // tranfer matrices. This path is used by YUV to RGB color conversion
  // when full color conversion is not enabled.
  if (!dst.IsValid())
    return;

  SkColorSpaceTransferFn src_to_linear_fn;
  if (src.GetTransferFunction(&src_to_linear_fn)) {
    steps_.push_back(std::make_unique<ColorTransformSkTransferFn>(
        src_to_linear_fn, src.HasExtendedSkTransferFn()));
  } else if (src.transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) {
    steps_.push_back(
        std::make_unique<ColorTransformSMPTEST2048NonHdrToLinear>());
  } else {
    steps_.push_back(std::make_unique<ColorTransformToLinear>(src.transfer_));
  }

  if (src.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
    // BT2020 CL is a special case.
    steps_.push_back(
        std::make_unique<ColorTransformMatrix>(Invert(GetTransferMatrix(src))));
  }
  steps_.push_back(
      std::make_unique<ColorTransformMatrix>(GetPrimaryTransform(src)));

  steps_.push_back(
      std::make_unique<ColorTransformMatrix>(Invert(GetPrimaryTransform(dst))));
  if (dst.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
    // BT2020 CL is a special case.
    steps_.push_back(
        std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst)));
  }

  SkColorSpaceTransferFn dst_from_linear_fn;
  if (dst.GetInverseTransferFunction(&dst_from_linear_fn)) {
    steps_.push_back(std::make_unique<ColorTransformSkTransferFn>(
        dst_from_linear_fn, dst.HasExtendedSkTransferFn()));
  } else {
    steps_.push_back(std::make_unique<ColorTransformFromLinear>(dst.transfer_));
  }

  if (dst.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
    steps_.push_back(std::make_unique<ColorTransformToBT2020CL>());
  } else {
    steps_.push_back(
        std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst)));
  }

  steps_.push_back(std::make_unique<ColorTransformMatrix>(
      Invert(GetRangeAdjustMatrix(dst))));
}

class SkiaColorTransform : public ColorTransformStep {
 public:
  // Takes ownership of the profiles
  SkiaColorTransform(sk_sp<SkColorSpace> src, sk_sp<SkColorSpace> dst)
      : src_(src), dst_(dst) {}
  ~SkiaColorTransform() override {
    src_ = nullptr;
    dst_ = nullptr;
  }
  SkiaColorTransform* GetSkia() override { return this; }
  bool Join(ColorTransformStep* next_untyped) override {
    SkiaColorTransform* next = next_untyped->GetSkia();
    if (!next)
      return false;
    if (SkColorSpace::Equals(dst_.get(), next->src_.get())) {
      dst_ = next->dst_;
      return true;
    }
    return false;
  }
  bool IsNull() override {
    if (SkColorSpace::Equals(src_.get(), dst_.get()))
      return true;
    return false;
  }
  void Transform(ColorTransform::TriStim* colors, size_t num) const override {
    // We could do this either using Skia or skcms, but since skcms can handle
    // TriStim directly as skcms_PixelFormat_RGB_fff, let's use that.
    skcms_ICCProfile src_profile, dst_profile;
    src_->toProfile(&src_profile);
    dst_->toProfile(&dst_profile);

    const skcms_PixelFormat kFFF = skcms_PixelFormat_RGB_fff;
    const skcms_AlphaFormat kUPM = skcms_AlphaFormat_Unpremul;

    bool xform_result = skcms_Transform(colors, kFFF, kUPM, &src_profile,
                                        colors, kFFF, kUPM, &dst_profile, num);
    DCHECK(xform_result);
  }

 private:
  sk_sp<SkColorSpace> src_;
  sk_sp<SkColorSpace> dst_;
};

sk_sp<SkColorSpace> ColorTransformInternal::GetSkColorSpaceIfNecessary(
    const ColorSpace& color_space) {
  if (!color_space.icc_profile_id_)
    return nullptr;
  return ICCProfile::GetSkColorSpaceFromId(color_space.icc_profile_id_);
}

ColorTransformInternal::ColorTransformInternal(const ColorSpace& src,
                                               const ColorSpace& dst,
                                               Intent intent)
    : src_(src), dst_(dst) {
  // If no source color space is specified, do no transformation.
  // TODO(ccameron): We may want dst assume sRGB at some point in the future.
  if (!src_.IsValid())
    return;

  // SMPTEST2084_NON_HDR is not a valid destination.
  if (dst.transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) {
    DLOG(ERROR) << "Invalid dst transfer function, returning identity.";
    return;
  }

  // If the target color space is not defined, just apply the adjust and
  // tranfer matrices. This path is used by YUV to RGB color conversion
  // when full color conversion is not enabled.
  sk_sp<SkColorSpace> src_sk_color_space;
  sk_sp<SkColorSpace> dst_sk_color_space;

  bool has_src_profile = false;
  bool has_dst_profile = false;
  if (dst.IsValid()) {
    src_sk_color_space = GetSkColorSpaceIfNecessary(src_);
    dst_sk_color_space = GetSkColorSpaceIfNecessary(dst_);
  }
  has_src_profile = !!src_sk_color_space;
  has_dst_profile = !!dst_sk_color_space;

  if (has_src_profile) {
    steps_.push_back(std::make_unique<SkiaColorTransform>(
        std::move(src_sk_color_space),
        ColorSpace::CreateXYZD50().ToSkColorSpace()));
  }
  AppendColorSpaceToColorSpaceTransform(
      has_src_profile ? ColorSpace::CreateXYZD50() : src_,
      has_dst_profile ? ColorSpace::CreateXYZD50() : dst_, intent);
  if (has_dst_profile) {
    steps_.push_back(std::make_unique<SkiaColorTransform>(
        ColorSpace::CreateXYZD50().ToSkColorSpace(),
        std::move(dst_sk_color_space)));
  }

  if (intent != Intent::TEST_NO_OPT)
    Simplify();
}

std::string ColorTransformInternal::GetShaderSource() const {
  std::stringstream hdr;
  std::stringstream src;
  InitStringStream(&hdr);
  InitStringStream(&src);
  src << "vec3 DoColorConversion(vec3 color) {" << endl;
  size_t step_index = 0;
  for (const auto& step : steps_)
    step->AppendShaderSource(&hdr, &src, step_index++);
  src << "  return color;" << endl;
  src << "}" << endl;
  return hdr.str() + src.str();
}

bool ColorTransformInternal::CanGetShaderSource() const {
  for (const auto& step : steps_) {
    if (!step->CanAppendShaderSource())
      return false;
  }
  return true;
}

ColorTransformInternal::~ColorTransformInternal() {}

void ColorTransformInternal::Simplify() {
  for (auto iter = steps_.begin(); iter != steps_.end();) {
    std::unique_ptr<ColorTransformStep>& this_step = *iter;

    // Try to Join |next_step| into |this_step|. If successful, re-visit the
    // step before |this_step|.
    auto iter_next = iter;
    iter_next++;
    if (iter_next != steps_.end()) {
      std::unique_ptr<ColorTransformStep>& next_step = *iter_next;
      if (this_step->Join(next_step.get())) {
        steps_.erase(iter_next);
        if (iter != steps_.begin())
          --iter;
        continue;
      }
    }

    // If |this_step| step is a no-op, remove it, and re-visit the step before
    // |this_step|.
    if (this_step->IsNull()) {
      iter = steps_.erase(iter);
      if (iter != steps_.begin())
        --iter;
      continue;
    }

    ++iter;
  }
}

// static
std::unique_ptr<ColorTransform> ColorTransform::NewColorTransform(
    const ColorSpace& src,
    const ColorSpace& dst,
    Intent intent) {
  return std::unique_ptr<ColorTransform>(
      new ColorTransformInternal(src, dst, intent));
}

ColorTransform::ColorTransform() {}
ColorTransform::~ColorTransform() {}

}  // namespace gfx
