// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxcrt/fx_coordinates.h"

#include <math.h>

#include <algorithm>
#include <utility>

#include "build/build_config.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "third_party/base/cxx17_backports.h"

#ifndef NDEBUG
#include <ostream>
#endif

namespace {

void MatchFloatRange(float f1, float f2, int* i1, int* i2) {
  float length = ceilf(f2 - f1);
  float f1_floor = floorf(f1);
  float f1_ceil = ceilf(f1);
  float error1 = f1 - f1_floor + fabsf(f2 - f1_floor - length);
  float error2 = f1_ceil - f1 + fabsf(f2 - f1_ceil - length);
  float start = error1 > error2 ? f1_ceil : f1_floor;
  FX_SAFE_INT32 safe1 = start;
  FX_SAFE_INT32 safe2 = start + length;
  if (safe1.IsValid() && safe2.IsValid()) {
    *i1 = safe1.ValueOrDie();
    *i2 = safe2.ValueOrDie();
  } else {
    *i1 = 0;
    *i2 = 0;
  }
}

#if BUILDFLAG(IS_WIN)
static_assert(sizeof(FX_RECT) == sizeof(RECT), "FX_RECT vs. RECT mismatch");
static_assert(offsetof(FX_RECT, left) == offsetof(RECT, left),
              "FX_RECT vs. RECT mismatch");
static_assert(offsetof(FX_RECT, top) == offsetof(RECT, top),
              "FX_RECT vs. RECT mismatch");
static_assert(offsetof(FX_RECT, right) == offsetof(RECT, right),
              "FX_RECT vs. RECT mismatch");
static_assert(offsetof(FX_RECT, bottom) == offsetof(RECT, bottom),
              "FX_RECT vs. RECT mismatch");
static_assert(sizeof(FX_RECT::left) == sizeof(RECT::left),
              "FX_RECT vs. RECT mismatch");
static_assert(sizeof(FX_RECT::top) == sizeof(RECT::top),
              "FX_RECT vs. RECT mismatch");
static_assert(sizeof(FX_RECT::right) == sizeof(RECT::right),
              "FX_RECT vs. RECT mismatch");
static_assert(sizeof(FX_RECT::bottom) == sizeof(RECT::bottom),
              "FX_RECT vs. RECT mismatch");
#endif

}  // namespace

template <>
float CFX_VTemplate<float>::Length() const {
  return FXSYS_sqrt2(x, y);
}

template <>
void CFX_VTemplate<float>::Normalize() {
  float fLen = Length();
  if (fLen < 0.0001f)
    return;

  x /= fLen;
  y /= fLen;
}

bool FX_RECT::Valid() const {
  FX_SAFE_INT32 w = right;
  FX_SAFE_INT32 h = bottom;
  w -= left;
  h -= top;
  return w.IsValid() && h.IsValid();
}

void FX_RECT::Normalize() {
  if (left > right)
    std::swap(left, right);
  if (top > bottom)
    std::swap(top, bottom);
}

void FX_RECT::Intersect(const FX_RECT& src) {
  FX_RECT src_n = src;
  src_n.Normalize();
  Normalize();
  left = std::max(left, src_n.left);
  top = std::max(top, src_n.top);
  right = std::min(right, src_n.right);
  bottom = std::min(bottom, src_n.bottom);
  if (left > right || top > bottom) {
    left = top = right = bottom = 0;
  }
}

FX_RECT FX_RECT::SwappedClipBox(int width,
                                int height,
                                bool bFlipX,
                                bool bFlipY) const {
  FX_RECT rect;
  if (bFlipY) {
    rect.left = height - top;
    rect.right = height - bottom;
  } else {
    rect.left = top;
    rect.right = bottom;
  }
  if (bFlipX) {
    rect.top = width - left;
    rect.bottom = width - right;
  } else {
    rect.top = left;
    rect.bottom = right;
  }
  rect.Normalize();
  return rect;
}

// Y-axis runs the opposite way in FX_RECT.
CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect)
    : left(rect.left), bottom(rect.top), right(rect.right), top(rect.bottom) {}

CFX_FloatRect::CFX_FloatRect(const CFX_PointF& point)
    : left(point.x), bottom(point.y), right(point.x), top(point.y) {}

// static
CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_PointF* pPoints, int nPoints) {
  if (nPoints == 0)
    return CFX_FloatRect();

  float min_x = pPoints->x;
  float max_x = pPoints->x;
  float min_y = pPoints->y;
  float max_y = pPoints->y;
  for (int i = 1; i < nPoints; i++) {
    min_x = std::min(min_x, pPoints[i].x);
    max_x = std::max(max_x, pPoints[i].x);
    min_y = std::min(min_y, pPoints[i].y);
    max_y = std::max(max_y, pPoints[i].y);
  }
  return CFX_FloatRect(min_x, min_y, max_x, max_y);
}

void CFX_FloatRect::Normalize() {
  if (left > right)
    std::swap(left, right);
  if (bottom > top)
    std::swap(top, bottom);
}

void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) {
  Normalize();
  CFX_FloatRect other = other_rect;
  other.Normalize();
  left = std::max(left, other.left);
  bottom = std::max(bottom, other.bottom);
  right = std::min(right, other.right);
  top = std::min(top, other.top);
  if (left > right || bottom > top)
    *this = CFX_FloatRect();
}

void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) {
  Normalize();
  CFX_FloatRect other = other_rect;
  other.Normalize();
  left = std::min(left, other.left);
  bottom = std::min(bottom, other.bottom);
  right = std::max(right, other.right);
  top = std::max(top, other.top);
}

FX_RECT CFX_FloatRect::GetOuterRect() const {
  FX_RECT rect;
  rect.left = pdfium::base::saturated_cast<int>(floor(left));
  rect.bottom = pdfium::base::saturated_cast<int>(ceil(top));
  rect.right = pdfium::base::saturated_cast<int>(ceil(right));
  rect.top = pdfium::base::saturated_cast<int>(floor(bottom));
  rect.Normalize();
  return rect;
}

FX_RECT CFX_FloatRect::GetInnerRect() const {
  FX_RECT rect;
  rect.left = pdfium::base::saturated_cast<int>(ceil(left));
  rect.bottom = pdfium::base::saturated_cast<int>(floor(top));
  rect.right = pdfium::base::saturated_cast<int>(floor(right));
  rect.top = pdfium::base::saturated_cast<int>(ceil(bottom));
  rect.Normalize();
  return rect;
}

FX_RECT CFX_FloatRect::GetClosestRect() const {
  FX_RECT rect;
  MatchFloatRange(left, right, &rect.left, &rect.right);
  MatchFloatRange(bottom, top, &rect.top, &rect.bottom);
  rect.Normalize();
  return rect;
}

CFX_FloatRect CFX_FloatRect::GetCenterSquare() const {
  float fWidth = Width();
  float fHeight = Height();
  float fHalfWidth = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2;

  float fCenterX = (left + right) / 2.0f;
  float fCenterY = (top + bottom) / 2.0f;
  return CFX_FloatRect(fCenterX - fHalfWidth, fCenterY - fHalfWidth,
                       fCenterX + fHalfWidth, fCenterY + fHalfWidth);
}

bool CFX_FloatRect::Contains(const CFX_PointF& point) const {
  CFX_FloatRect n1(*this);
  n1.Normalize();
  return point.x <= n1.right && point.x >= n1.left && point.y <= n1.top &&
         point.y >= n1.bottom;
}

bool CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const {
  CFX_FloatRect n1(*this);
  CFX_FloatRect n2(other_rect);
  n1.Normalize();
  n2.Normalize();
  return n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom &&
         n2.top <= n1.top;
}

void CFX_FloatRect::UpdateRect(const CFX_PointF& point) {
  left = std::min(left, point.x);
  bottom = std::min(bottom, point.y);
  right = std::max(right, point.x);
  top = std::max(top, point.y);
}

void CFX_FloatRect::Inflate(float x, float y) {
  Inflate(x, y, x, y);
}

void CFX_FloatRect::Inflate(float other_left,
                            float other_bottom,
                            float other_right,
                            float other_top) {
  Normalize();
  left -= other_left;
  bottom -= other_bottom;
  right += other_right;
  top += other_top;
}

void CFX_FloatRect::Inflate(const CFX_FloatRect& rt) {
  Inflate(rt.left, rt.bottom, rt.right, rt.top);
}

void CFX_FloatRect::Deflate(float x, float y) {
  Deflate(x, y, x, y);
}

void CFX_FloatRect::Deflate(float other_left,
                            float other_bottom,
                            float other_right,
                            float other_top) {
  Inflate(-other_left, -other_bottom, -other_right, -other_top);
}

void CFX_FloatRect::Deflate(const CFX_FloatRect& rt) {
  Deflate(rt.left, rt.bottom, rt.right, rt.top);
}

CFX_FloatRect CFX_FloatRect::GetDeflated(float x, float y) const {
  if (IsEmpty())
    return CFX_FloatRect();

  CFX_FloatRect that = *this;
  that.Deflate(x, y);
  that.Normalize();
  return that;
}

void CFX_FloatRect::Translate(float e, float f) {
  left += e;
  right += e;
  top += f;
  bottom += f;
}

void CFX_FloatRect::Scale(float fScale) {
  left *= fScale;
  bottom *= fScale;
  right *= fScale;
  top *= fScale;
}

void CFX_FloatRect::ScaleFromCenterPoint(float fScale) {
  float fHalfWidth = (right - left) / 2.0f;
  float fHalfHeight = (top - bottom) / 2.0f;

  float center_x = (left + right) / 2;
  float center_y = (top + bottom) / 2;

  left = center_x - fHalfWidth * fScale;
  bottom = center_y - fHalfHeight * fScale;
  right = center_x + fHalfWidth * fScale;
  top = center_y + fHalfHeight * fScale;
}

FX_RECT CFX_FloatRect::ToFxRect() const {
  return FX_RECT(static_cast<int>(left), static_cast<int>(top),
                 static_cast<int>(right), static_cast<int>(bottom));
}

FX_RECT CFX_FloatRect::ToRoundedFxRect() const {
  return FX_RECT(FXSYS_roundf(left), FXSYS_roundf(top), FXSYS_roundf(right),
                 FXSYS_roundf(bottom));
}

void CFX_RectF::Union(float x, float y) {
  float r = right();
  float b = bottom();

  left = std::min(left, x);
  top = std::min(top, y);
  r = std::max(r, x);
  b = std::max(b, y);

  width = r - left;
  height = b - top;
}

void CFX_RectF::Union(const CFX_RectF& rt) {
  float r = right();
  float b = bottom();

  left = std::min(left, rt.left);
  top = std::min(top, rt.top);
  r = std::max(r, rt.right());
  b = std::max(b, rt.bottom());

  width = r - left;
  height = b - top;
}

void CFX_RectF::Intersect(const CFX_RectF& rt) {
  float r = right();
  float b = bottom();

  left = std::max(left, rt.left);
  top = std::max(top, rt.top);
  r = std::min(r, rt.right());
  b = std::min(b, rt.bottom());

  width = r - left;
  height = b - top;
}

FX_RECT CFX_RectF::GetOuterRect() const {
  return FX_RECT(static_cast<int32_t>(floor(left)),
                 static_cast<int32_t>(floor(top)),
                 static_cast<int32_t>(ceil(right())),
                 static_cast<int32_t>(ceil(bottom())));
}

#ifndef NDEBUG
std::ostream& operator<<(std::ostream& os, const CFX_FloatRect& rect) {
  os << "rect[w " << rect.Width() << " x h " << rect.Height() << " (left "
     << rect.left << ", bot " << rect.bottom << ")]";
  return os;
}

std::ostream& operator<<(std::ostream& os, const CFX_RectF& rect) {
  os << "rect[w " << rect.Width() << " x h " << rect.Height() << " (left "
     << rect.left << ", top " << rect.top << ")]";
  return os;
}
#endif  // NDEBUG

CFX_Matrix CFX_Matrix::GetInverse() const {
  CFX_Matrix inverse;
  float i = a * d - b * c;
  if (fabs(i) == 0)
    return inverse;

  float j = -i;
  inverse.a = d / i;
  inverse.b = b / j;
  inverse.c = c / j;
  inverse.d = a / i;
  inverse.e = (c * f - d * e) / i;
  inverse.f = (a * f - b * e) / j;
  return inverse;
}

bool CFX_Matrix::Is90Rotated() const {
  return fabs(a * 1000) < fabs(b) && fabs(d * 1000) < fabs(c);
}

bool CFX_Matrix::IsScaled() const {
  return fabs(b * 1000) < fabs(a) && fabs(c * 1000) < fabs(d);
}

void CFX_Matrix::Translate(float x, float y) {
  e += x;
  f += y;
}

void CFX_Matrix::TranslatePrepend(float x, float y) {
  e += x * a + y * c;
  f += y * d + x * b;
}

void CFX_Matrix::Scale(float sx, float sy) {
  a *= sx;
  b *= sy;
  c *= sx;
  d *= sy;
  e *= sx;
  f *= sy;
}

void CFX_Matrix::Rotate(float fRadian) {
  float cosValue = cos(fRadian);
  float sinValue = sin(fRadian);
  Concat(CFX_Matrix(cosValue, sinValue, -sinValue, cosValue, 0, 0));
}

void CFX_Matrix::MatchRect(const CFX_FloatRect& dest,
                           const CFX_FloatRect& src) {
  float fDiff = src.left - src.right;
  a = fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;

  fDiff = src.bottom - src.top;
  d = fabs(fDiff) < 0.001f ? 1 : (dest.bottom - dest.top) / fDiff;
  e = dest.left - src.left * a;
  f = dest.bottom - src.bottom * d;
  b = 0;
  c = 0;
}

float CFX_Matrix::GetXUnit() const {
  if (b == 0)
    return (a > 0 ? a : -a);
  if (a == 0)
    return (b > 0 ? b : -b);
  return FXSYS_sqrt2(a, b);
}

float CFX_Matrix::GetYUnit() const {
  if (c == 0)
    return (d > 0 ? d : -d);
  if (d == 0)
    return (c > 0 ? c : -c);
  return FXSYS_sqrt2(c, d);
}

CFX_FloatRect CFX_Matrix::GetUnitRect() const {
  return TransformRect(CFX_FloatRect(0.f, 0.f, 1.f, 1.f));
}

float CFX_Matrix::TransformXDistance(float dx) const {
  float fx = a * dx;
  float fy = b * dx;
  return FXSYS_sqrt2(fx, fy);
}

float CFX_Matrix::TransformDistance(float distance) const {
  return distance * (GetXUnit() + GetYUnit()) / 2;
}

CFX_PointF CFX_Matrix::Transform(const CFX_PointF& point) const {
  return CFX_PointF(a * point.x + c * point.y + e,
                    b * point.x + d * point.y + f);
}

CFX_RectF CFX_Matrix::TransformRect(const CFX_RectF& rect) const {
  CFX_FloatRect result_rect = TransformRect(rect.ToFloatRect());
  return CFX_RectF(result_rect.left, result_rect.bottom, result_rect.Width(),
                   result_rect.Height());
}

CFX_FloatRect CFX_Matrix::TransformRect(const CFX_FloatRect& rect) const {
  CFX_PointF points[] = {{rect.left, rect.top},
                         {rect.left, rect.bottom},
                         {rect.right, rect.top},
                         {rect.right, rect.bottom}};
  for (CFX_PointF& point : points)
    point = Transform(point);

  float new_right = points[0].x;
  float new_left = points[0].x;
  float new_top = points[0].y;
  float new_bottom = points[0].y;
  for (size_t i = 1; i < pdfium::size(points); i++) {
    new_right = std::max(new_right, points[i].x);
    new_left = std::min(new_left, points[i].x);
    new_top = std::max(new_top, points[i].y);
    new_bottom = std::min(new_bottom, points[i].y);
  }

  return CFX_FloatRect(new_left, new_bottom, new_right, new_top);
}
