// Copyright (c) 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.

#ifndef UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
#define UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_

#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/gfx_export.h"

namespace gfx {

// This class implements the subset of 2D linear transforms that only
// translation and uniform scaling are allowed.
// Internally this is stored as a scalar pre-scale factor, and a vector
// for post-translation. The class constructor and member accessor follows
// the same convention.
class GFX_EXPORT AxisTransform2d {
 public:
  constexpr AxisTransform2d() = default;
  constexpr AxisTransform2d(float scale, const Vector2dF& translation)
      : scale_(scale), translation_(translation) {}

  bool operator==(const AxisTransform2d& other) const {
    return scale_ == other.scale_ && translation_ == other.translation_;
  }
  bool operator!=(const AxisTransform2d& other) const {
    return !(*this == other);
  }

  void PreScale(float scale) { scale_ *= scale; }
  void PostScale(float scale) {
    scale_ *= scale;
    translation_.Scale(scale);
  }
  void PreTranslate(const Vector2dF& translation) {
    translation_ += ScaleVector2d(translation, scale_);
  }
  void PostTranslate(const Vector2dF& translation) {
    translation_ += translation;
  }

  void PreConcat(const AxisTransform2d& pre) {
    PreTranslate(pre.translation_);
    PreScale(pre.scale_);
  }
  void PostConcat(const AxisTransform2d& post) {
    PostScale(post.scale_);
    PostTranslate(post.translation_);
  }

  void Invert() {
    DCHECK(scale_);
    scale_ = 1.f / scale_;
    translation_.Scale(-scale_);
  }

  PointF MapPoint(const PointF& p) const {
    return ScalePoint(p, scale_) + translation_;
  }
  PointF InverseMapPoint(const PointF& p) const {
    return ScalePoint(p - translation_, 1.f / scale_);
  }

  RectF MapRect(const RectF& r) const {
    DCHECK(scale_ >= 0.f);
    return ScaleRect(r, scale_) + translation_;
  }
  RectF InverseMapRect(const RectF& r) const {
    DCHECK(scale_ > 0.f);
    return ScaleRect(r - translation_, 1.f / scale_);
  }

  float scale() const { return scale_; }
  const Vector2dF& translation() const { return translation_; }

  std::string ToString() const;

 private:
  // Scale is applied before translation, i.e.
  // this->Transform(p) == scale_ * p + translation_
  float scale_ = 1.f;
  Vector2dF translation_;
};

static inline AxisTransform2d PreScaleAxisTransform2d(const AxisTransform2d& t,
                                                      float scale) {
  AxisTransform2d result(t);
  result.PreScale(scale);
  return result;
}

static inline AxisTransform2d PostScaleAxisTransform2d(const AxisTransform2d& t,
                                                       float scale) {
  AxisTransform2d result(t);
  result.PostScale(scale);
  return result;
}

static inline AxisTransform2d PreTranslateAxisTransform2d(
    const AxisTransform2d& t,
    const Vector2dF& translation) {
  AxisTransform2d result(t);
  result.PreTranslate(translation);
  return result;
}

static inline AxisTransform2d PostTranslateAxisTransform2d(
    const AxisTransform2d& t,
    const Vector2dF& translation) {
  AxisTransform2d result(t);
  result.PostTranslate(translation);
  return result;
}

static inline AxisTransform2d ConcatAxisTransform2d(
    const AxisTransform2d& post,
    const AxisTransform2d& pre) {
  AxisTransform2d result(post);
  result.PreConcat(pre);
  return result;
}

static inline AxisTransform2d InvertAxisTransform2d(const AxisTransform2d& t) {
  AxisTransform2d result = t;
  result.Invert();
  return result;
}

// This is declared here for use in gtest-based unit tests but is defined in
// the //ui/gfx:test_support target. Depend on that to use this in your unit
// test. This should not be used in production code - call ToString() instead.
void PrintTo(const AxisTransform2d&, ::std::ostream* os);

}  // namespace gfx

#endif  // UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
