// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gfx/geometry/transform_util.h"

#include <algorithm>
#include <cmath>
#include <ostream>
#include <string>

#include "base/check.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"

namespace gfx {

namespace {

template <int n>
void Combine(double* out,
             const double* a,
             const double* b,
             double scale_a,
             double scale_b) {
  for (int i = 0; i < n; ++i)
    out[i] = a[i] * scale_a + b[i] * scale_b;
}

}  // namespace

Transform GetScaleTransform(const Point& anchor, float scale) {
  Transform transform;
  transform.Translate(anchor.x() * (1 - scale), anchor.y() * (1 - scale));
  transform.Scale(scale, scale);
  return transform;
}

DecomposedTransform BlendDecomposedTransforms(const DecomposedTransform& to,
                                              const DecomposedTransform& from,
                                              double progress) {
  DecomposedTransform out;
  double scalea = progress;
  double scaleb = 1.0 - progress;
  Combine<3>(out.translate, to.translate, from.translate, scalea, scaleb);
  Combine<3>(out.scale, to.scale, from.scale, scalea, scaleb);
  Combine<3>(out.skew, to.skew, from.skew, scalea, scaleb);
  Combine<4>(out.perspective, to.perspective, from.perspective, scalea, scaleb);
  out.quaternion = from.quaternion.Slerp(to.quaternion, progress);
  return out;
}

DecomposedTransform AccumulateDecomposedTransforms(
    const DecomposedTransform& a,
    const DecomposedTransform& b) {
  DecomposedTransform out;

  // Translate is a simple addition.
  for (size_t i = 0; i < std::size(a.translate); i++)
    out.translate[i] = a.translate[i] + b.translate[i];

  // Scale is accumulated using 1-based addition.
  for (size_t i = 0; i < std::size(a.scale); i++)
    out.scale[i] = a.scale[i] + b.scale[i] - 1;

  // Skew can be added.
  for (size_t i = 0; i < std::size(a.skew); i++)
    out.skew[i] = a.skew[i] + b.skew[i];

  // We sum the perspective components; note that w is 1-based.
  for (size_t i = 0; i < std::size(a.perspective); i++)
    out.perspective[i] = a.perspective[i] + b.perspective[i];
  out.perspective[3] -= 1;

  // To accumulate quaternions, we multiply them. This is equivalent to 'adding'
  // the rotations that they represent.
  out.quaternion = a.quaternion * b.quaternion;

  return out;
}

Transform TransformAboutPivot(const PointF& pivot, const Transform& transform) {
  Transform result;
  result.Translate(pivot.x(), pivot.y());
  result.PreConcat(transform);
  result.Translate(-pivot.x(), -pivot.y());
  return result;
}

Transform TransformBetweenRects(const RectF& src, const RectF& dst) {
  DCHECK(!src.IsEmpty());
  Transform result;
  result.Translate(dst.origin() - src.origin());
  result.Scale(dst.width() / src.width(), dst.height() / src.height());
  return result;
}

AxisTransform2d OrthoProjectionTransform(float left,
                                         float right,
                                         float bottom,
                                         float top) {
  // Use the standard formula to map the clipping frustum to the square from
  // [-1, -1] to [1, 1].
  float delta_x = right - left;
  float delta_y = top - bottom;
  if (!delta_x || !delta_y)
    return AxisTransform2d();

  return AxisTransform2d::FromScaleAndTranslation(
      Vector2dF(2.0f / delta_x, 2.0f / delta_y),
      Vector2dF(-(right + left) / delta_x, -(top + bottom) / delta_y));
}

AxisTransform2d WindowTransform(int x, int y, int width, int height) {
  // Map from ([-1, -1] to [1, 1]) -> ([x, y] to [x + width, y + height]).
  return AxisTransform2d::FromScaleAndTranslation(
      Vector2dF(width * 0.5f, height * 0.5f),
      Vector2dF(x + width * 0.5f, y + height * 0.5f));
}

static inline bool NearlyZero(double value) {
  return std::abs(value) < std::numeric_limits<double>::epsilon();
}

static inline float ScaleOnAxis(double a, double b, double c) {
  if (NearlyZero(b) && NearlyZero(c))
    return std::abs(a);
  if (NearlyZero(a) && NearlyZero(c))
    return std::abs(b);
  if (NearlyZero(a) && NearlyZero(b))
    return std::abs(c);

  // Do the sqrt as a double to not lose precision.
  return static_cast<float>(std::sqrt(a * a + b * b + c * c));
}

absl::optional<Vector2dF> TryComputeTransform2dScaleComponents(
    const Transform& transform) {
  if (transform.rc(3, 0) != 0.0f || transform.rc(3, 1) != 0.0f) {
    return absl::nullopt;
  }

  float w = transform.rc(3, 3);
  if (!std::isnormal(w)) {
    return absl::nullopt;
  }
  float w_scale = 1.0f / w;

  // In theory, this shouldn't be using the matrix.getDouble(2, 0) and
  // .getDouble(1, 0) values; creating a large transfer from input x or
  // y (in the layer) to output z has no visible difference when the
  // transform being considered is a transform to device space, since
  // the resulting z values are ignored.  However, ignoring them here
  // might be risky because it would mean that we would have more
  // variation in the results under animation of rotateX() or rotateY(),
  // and we'd be relying more heavily on code to compute correct scales
  // during animation.  Currently some such code only considers the
  // endpoints, which would become problematic for cases like animation
  // from rotateY(-60deg) to rotateY(60deg).
  float x_scale =
      ScaleOnAxis(transform.rc(0, 0), transform.rc(1, 0), transform.rc(2, 0));
  float y_scale =
      ScaleOnAxis(transform.rc(0, 1), transform.rc(1, 1), transform.rc(2, 1));
  return Vector2dF(x_scale * w_scale, y_scale * w_scale);
}

Vector2dF ComputeTransform2dScaleComponents(const Transform& transform,
                                            float fallback_value) {
  absl::optional<Vector2dF> scale =
      TryComputeTransform2dScaleComponents(transform);
  if (scale) {
    return *scale;
  }
  return Vector2dF(fallback_value, fallback_value);
}

float ComputeApproximateMaxScale(const Transform& transform) {
  gfx::RectF unit = transform.MapRect(RectF(0.f, 0.f, 1.f, 1.f));
  return std::max(unit.width(), unit.height());
}

}  // namespace gfx
