// 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 <limits.h>

#include "core/include/fxcrt/fx_coordinates.h"
#include "core/include/fxcrt/fx_ext.h"

void FX_RECT::Normalize() {
  if (left > right) {
    int temp = left;
    left = right;
    right = temp;
  }
  if (top > bottom) {
    int temp = top;
    top = bottom;
    bottom = temp;
  }
}
void FX_RECT::Intersect(const FX_RECT& src) {
  FX_RECT src_n = src;
  src_n.Normalize();
  Normalize();
  left = left > src_n.left ? left : src_n.left;
  top = top > src_n.top ? top : src_n.top;
  right = right < src_n.right ? right : src_n.right;
  bottom = bottom < src_n.bottom ? bottom : src_n.bottom;
  if (left > right || top > bottom) {
    left = top = right = bottom = 0;
  }
}
void FX_RECT::Union(const FX_RECT& other_rect) {
  Normalize();
  FX_RECT other = other_rect;
  other.Normalize();
  left = left < other.left ? left : other.left;
  right = right > other.right ? right : other.right;
  bottom = bottom > other.bottom ? bottom : other.bottom;
  top = top < other.top ? top : other.top;
}
FX_BOOL GetIntersection(FX_FLOAT low1,
                        FX_FLOAT high1,
                        FX_FLOAT low2,
                        FX_FLOAT high2,
                        FX_FLOAT& interlow,
                        FX_FLOAT& interhigh) {
  if (low1 >= high2 || low2 >= high1) {
    return FALSE;
  }
  interlow = low1 > low2 ? low1 : low2;
  interhigh = high1 > high2 ? high2 : high1;
  return TRUE;
}
extern "C" int FXSYS_round(FX_FLOAT d) {
  if (d < (FX_FLOAT)INT_MIN) {
    return INT_MIN;
  }
  if (d > (FX_FLOAT)INT_MAX) {
    return INT_MAX;
  }

  return (int)round(d);
}
CFX_FloatRect::CFX_FloatRect(const FX_RECT& rect) {
  left = (FX_FLOAT)(rect.left);
  right = (FX_FLOAT)(rect.right);
  bottom = (FX_FLOAT)(rect.top);
  top = (FX_FLOAT)(rect.bottom);
}
void CFX_FloatRect::Normalize() {
  FX_FLOAT temp;
  if (left > right) {
    temp = left;
    left = right;
    right = temp;
  }
  if (bottom > top) {
    temp = top;
    top = bottom;
    bottom = temp;
  }
}
void CFX_FloatRect::Intersect(const CFX_FloatRect& other_rect) {
  Normalize();
  CFX_FloatRect other = other_rect;
  other.Normalize();
  left = left > other.left ? left : other.left;
  right = right < other.right ? right : other.right;
  bottom = bottom > other.bottom ? bottom : other.bottom;
  top = top < other.top ? top : other.top;
  if (left > right || bottom > top) {
    left = right = bottom = top = 0;
  }
}
void CFX_FloatRect::Union(const CFX_FloatRect& other_rect) {
  Normalize();
  CFX_FloatRect other = other_rect;
  other.Normalize();
  left = left < other.left ? left : other.left;
  right = right > other.right ? right : other.right;
  bottom = bottom < other.bottom ? bottom : other.bottom;
  top = top > other.top ? top : other.top;
}
void CFX_FloatRect::Transform(const CFX_Matrix* pMatrix) {
  pMatrix->TransformRect(left, right, top, bottom);
}
int CFX_FloatRect::Substract4(CFX_FloatRect& s, CFX_FloatRect* pRects) {
  Normalize();
  s.Normalize();
  int nRects = 0;
  CFX_FloatRect rects[4];
  if (left < s.left) {
    rects[nRects].left = left;
    rects[nRects].right = s.left;
    rects[nRects].bottom = bottom;
    rects[nRects].top = top;
    nRects++;
  }
  if (s.left < right && s.top < top) {
    rects[nRects].left = s.left;
    rects[nRects].right = right;
    rects[nRects].bottom = s.top;
    rects[nRects].top = top;
    nRects++;
  }
  if (s.top > bottom && s.right < right) {
    rects[nRects].left = s.right;
    rects[nRects].right = right;
    rects[nRects].bottom = bottom;
    rects[nRects].top = s.top;
    nRects++;
  }
  if (s.bottom > bottom) {
    rects[nRects].left = s.left;
    rects[nRects].right = s.right;
    rects[nRects].bottom = bottom;
    rects[nRects].top = s.bottom;
    nRects++;
  }
  if (nRects == 0) {
    return 0;
  }
  for (int i = 0; i < nRects; i++) {
    pRects[i] = rects[i];
    pRects[i].Intersect(*this);
  }
  return nRects;
}
FX_RECT CFX_FloatRect::GetOutterRect() const {
  CFX_FloatRect rect1 = *this;
  FX_RECT rect;
  rect.left = (int)FXSYS_floor(rect1.left);
  rect.right = (int)FXSYS_ceil(rect1.right);
  rect.top = (int)FXSYS_floor(rect1.bottom);
  rect.bottom = (int)FXSYS_ceil(rect1.top);
  rect.Normalize();
  return rect;
}
FX_RECT CFX_FloatRect::GetInnerRect() const {
  CFX_FloatRect rect1 = *this;
  FX_RECT rect;
  rect.left = (int)FXSYS_ceil(rect1.left);
  rect.right = (int)FXSYS_floor(rect1.right);
  rect.top = (int)FXSYS_ceil(rect1.bottom);
  rect.bottom = (int)FXSYS_floor(rect1.top);
  rect.Normalize();
  return rect;
}
static void _MatchFloatRange(FX_FLOAT f1, FX_FLOAT f2, int& i1, int& i2) {
  int length = (int)FXSYS_ceil(f2 - f1);
  int i1_1 = (int)FXSYS_floor(f1);
  int i1_2 = (int)FXSYS_ceil(f1);
  FX_FLOAT error1 = f1 - i1_1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_1 - length);
  FX_FLOAT error2 = i1_2 - f1 + (FX_FLOAT)FXSYS_fabs(f2 - i1_2 - length);
  i1 = (error1 > error2) ? i1_2 : i1_1;
  i2 = i1 + length;
}
FX_RECT CFX_FloatRect::GetClosestRect() const {
  CFX_FloatRect rect1 = *this;
  FX_RECT rect;
  _MatchFloatRange(rect1.left, rect1.right, rect.left, rect.right);
  _MatchFloatRange(rect1.bottom, rect1.top, rect.top, rect.bottom);
  rect.Normalize();
  return rect;
}
FX_BOOL CFX_FloatRect::Contains(const CFX_FloatRect& other_rect) const {
  CFX_FloatRect n1 = *this;
  n1.Normalize();
  CFX_FloatRect n2 = other_rect;
  n2.Normalize();
  if (n2.left >= n1.left && n2.right <= n1.right && n2.bottom >= n1.bottom &&
      n2.top <= n1.top) {
    return TRUE;
  }
  return FALSE;
}
FX_BOOL CFX_FloatRect::Contains(FX_FLOAT x, FX_FLOAT y) const {
  CFX_FloatRect n1 = *this;
  n1.Normalize();
  return x <= n1.right && x >= n1.left && y <= n1.top && y >= n1.bottom;
}
void CFX_FloatRect::UpdateRect(FX_FLOAT x, FX_FLOAT y) {
  if (left > x) {
    left = x;
  }
  if (right < x) {
    right = x;
  }
  if (bottom > y) {
    bottom = y;
  }
  if (top < y) {
    top = y;
  }
}
CFX_FloatRect CFX_FloatRect::GetBBox(const CFX_FloatPoint* pPoints,
                                     int nPoints) {
  if (nPoints == 0) {
    return CFX_FloatRect();
  }
  FX_FLOAT min_x = pPoints->x, max_x = pPoints->x, min_y = pPoints->y,
           max_y = pPoints->y;
  for (int i = 1; i < nPoints; i++) {
    if (min_x > pPoints[i].x) {
      min_x = pPoints[i].x;
    }
    if (max_x < pPoints[i].x) {
      max_x = pPoints[i].x;
    }
    if (min_y > pPoints[i].y) {
      min_y = pPoints[i].y;
    }
    if (max_y < pPoints[i].y) {
      max_y = pPoints[i].y;
    }
  }
  return CFX_FloatRect(min_x, min_y, max_x, max_y);
}
void CFX_Matrix::Set(FX_FLOAT other_a,
                     FX_FLOAT other_b,
                     FX_FLOAT other_c,
                     FX_FLOAT other_d,
                     FX_FLOAT other_e,
                     FX_FLOAT other_f) {
  a = other_a;
  b = other_b;
  c = other_c;
  d = other_d;
  e = other_e;
  f = other_f;
}
void CFX_Matrix::Set(const FX_FLOAT n[6]) {
  a = n[0];
  b = n[1];
  c = n[2];
  d = n[3];
  e = n[4];
  f = n[5];
}
void CFX_Matrix::SetReverse(const CFX_Matrix& m) {
  FX_FLOAT i = m.a * m.d - m.b * m.c;
  if (FXSYS_fabs(i) == 0) {
    return;
  }
  FX_FLOAT j = -i;
  a = m.d / i;
  b = m.b / j;
  c = m.c / j;
  d = m.a / i;
  e = (m.c * m.f - m.d * m.e) / i;
  f = (m.a * m.f - m.b * m.e) / j;
}
static void FXCRT_Matrix_Concat(CFX_Matrix& m,
                                const CFX_Matrix& m1,
                                const CFX_Matrix& m2) {
  FX_FLOAT aa = m1.a * m2.a + m1.b * m2.c;
  FX_FLOAT bb = m1.a * m2.b + m1.b * m2.d;
  FX_FLOAT cc = m1.c * m2.a + m1.d * m2.c;
  FX_FLOAT dd = m1.c * m2.b + m1.d * m2.d;
  FX_FLOAT ee = m1.e * m2.a + m1.f * m2.c + m2.e;
  FX_FLOAT ff = m1.e * m2.b + m1.f * m2.d + m2.f;
  m.a = aa, m.b = bb, m.c = cc, m.d = dd, m.e = ee, m.f = ff;
}
void CFX_Matrix::Concat(FX_FLOAT a,
                        FX_FLOAT b,
                        FX_FLOAT c,
                        FX_FLOAT d,
                        FX_FLOAT e,
                        FX_FLOAT f,
                        FX_BOOL bPrepended) {
  CFX_Matrix m;
  m.Set(a, b, c, d, e, f);
  Concat(m, bPrepended);
}
void CFX_Matrix::Concat(const CFX_Matrix& m, FX_BOOL bPrepended) {
  if (bPrepended) {
    FXCRT_Matrix_Concat(*this, m, *this);
  } else {
    FXCRT_Matrix_Concat(*this, *this, m);
  }
}
void CFX_Matrix::ConcatInverse(const CFX_Matrix& src, FX_BOOL bPrepended) {
  CFX_Matrix m;
  m.SetReverse(src);
  Concat(m, bPrepended);
}
FX_BOOL CFX_Matrix::IsInvertible() const {
  return FXSYS_fabs(a * d - b * c) >= 0.0001f;
}
FX_BOOL CFX_Matrix::Is90Rotated() const {
  return FXSYS_fabs(a * 1000) < FXSYS_fabs(b) &&
         FXSYS_fabs(d * 1000) < FXSYS_fabs(c);
}
FX_BOOL CFX_Matrix::IsScaled() const {
  return FXSYS_fabs(b * 1000) < FXSYS_fabs(a) &&
         FXSYS_fabs(c * 1000) < FXSYS_fabs(d);
}
void CFX_Matrix::Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended) {
  if (bPrepended) {
    e += x * a + y * c;
    f += y * d + x * b;
  } else {
    e += x, f += y;
  }
}
void CFX_Matrix::Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended) {
  a *= sx, d *= sy;
  if (bPrepended) {
    b *= sx;
    c *= sy;
  } else {
    b *= sy;
    c *= sx;
    e *= sx;
    f *= sy;
  }
}
void CFX_Matrix::Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended) {
  FX_FLOAT cosValue = FXSYS_cos(fRadian);
  FX_FLOAT sinValue = FXSYS_sin(fRadian);
  CFX_Matrix m;
  m.Set(cosValue, sinValue, -sinValue, cosValue, 0, 0);
  if (bPrepended) {
    FXCRT_Matrix_Concat(*this, m, *this);
  } else {
    FXCRT_Matrix_Concat(*this, *this, m);
  }
}
void CFX_Matrix::RotateAt(FX_FLOAT fRadian,
                          FX_FLOAT dx,
                          FX_FLOAT dy,
                          FX_BOOL bPrepended) {
  Translate(dx, dy, bPrepended);
  Rotate(fRadian, bPrepended);
  Translate(-dx, -dy, bPrepended);
}
void CFX_Matrix::Shear(FX_FLOAT fAlphaRadian,
                       FX_FLOAT fBetaRadian,
                       FX_BOOL bPrepended) {
  CFX_Matrix m;
  m.Set(1, FXSYS_tan(fAlphaRadian), FXSYS_tan(fBetaRadian), 1, 0, 0);
  if (bPrepended) {
    FXCRT_Matrix_Concat(*this, m, *this);
  } else {
    FXCRT_Matrix_Concat(*this, *this, m);
  }
}
void CFX_Matrix::MatchRect(const CFX_FloatRect& dest,
                           const CFX_FloatRect& src) {
  FX_FLOAT fDiff = src.left - src.right;
  a = FXSYS_fabs(fDiff) < 0.001f ? 1 : (dest.left - dest.right) / fDiff;
  fDiff = src.bottom - src.top;
  d = FXSYS_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;
}
FX_FLOAT CFX_Matrix::GetXUnit() const {
  if (b == 0) {
    return (a > 0 ? a : -a);
  }
  if (a == 0) {
    return (b > 0 ? b : -b);
  }
  return FXSYS_sqrt(a * a + b * b);
}
FX_FLOAT CFX_Matrix::GetYUnit() const {
  if (c == 0) {
    return (d > 0 ? d : -d);
  }
  if (d == 0) {
    return (c > 0 ? c : -c);
  }
  return FXSYS_sqrt(c * c + d * d);
}
void CFX_Matrix::GetUnitRect(CFX_RectF& rect) const {
  rect.left = rect.top = 0;
  rect.width = rect.height = 1;
  TransformRect(rect);
}
CFX_FloatRect CFX_Matrix::GetUnitRect() const {
  CFX_FloatRect rect(0, 0, 1, 1);
  rect.Transform((const CFX_Matrix*)this);
  return rect;
}
FX_FLOAT CFX_Matrix::GetUnitArea() const {
  FX_FLOAT A = FXSYS_sqrt(a * a + b * b);
  FX_FLOAT B = FXSYS_sqrt(c * c + d * d);
  FX_FLOAT ac = a + c, bd = b + d;
  FX_FLOAT C = FXSYS_sqrt(ac * ac + bd * bd);
  FX_FLOAT P = (A + B + C) / 2;
  return FXSYS_sqrt(P * (P - A) * (P - B) * (P - C)) * 2;
}
FX_FLOAT CFX_Matrix::TransformXDistance(FX_FLOAT dx) const {
  FX_FLOAT fx = a * dx, fy = b * dx;
  return FXSYS_sqrt(fx * fx + fy * fy);
}
int32_t CFX_Matrix::TransformXDistance(int32_t dx) const {
  FX_FLOAT fx = a * dx, fy = b * dx;
  return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
}
FX_FLOAT CFX_Matrix::TransformYDistance(FX_FLOAT dy) const {
  FX_FLOAT fx = c * dy, fy = d * dy;
  return FXSYS_sqrt(fx * fx + fy * fy);
}
int32_t CFX_Matrix::TransformYDistance(int32_t dy) const {
  FX_FLOAT fx = c * dy, fy = d * dy;
  return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
}
FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const {
  FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
  return FXSYS_sqrt(fx * fx + fy * fy);
}
int32_t CFX_Matrix::TransformDistance(int32_t dx, int32_t dy) const {
  FX_FLOAT fx = a * dx + c * dy, fy = b * dx + d * dy;
  return FXSYS_round(FXSYS_sqrt(fx * fx + fy * fy));
}
FX_FLOAT CFX_Matrix::TransformDistance(FX_FLOAT distance) const {
  return distance * (GetXUnit() + GetYUnit()) / 2;
}
void CFX_Matrix::TransformVector(CFX_VectorF& v) const {
  FX_FLOAT fx = a * v.x + c * v.y;
  FX_FLOAT fy = b * v.x + d * v.y;
  v.x = fx, v.y = fy;
}
void CFX_Matrix::TransformVector(CFX_Vector& v) const {
  FX_FLOAT fx = a * v.x + c * v.y;
  FX_FLOAT fy = b * v.x + d * v.y;
  v.x = FXSYS_round(fx);
  v.y = FXSYS_round(fy);
}
void CFX_Matrix::TransformPoints(CFX_Point* points, int32_t iCount) const {
  FXSYS_assert(iCount > 0);
  FX_FLOAT fx, fy;
  for (int32_t i = 0; i < iCount; i++) {
    fx = a * points->x + c * points->y + e;
    fy = b * points->x + d * points->y + f;
    points->x = FXSYS_round(fx);
    points->y = FXSYS_round(fy);
    points++;
  }
}
void CFX_Matrix::TransformPoints(CFX_PointF* points, int32_t iCount) const {
  FXSYS_assert(iCount > 0);
  FX_FLOAT fx, fy;
  for (int32_t i = 0; i < iCount; i++) {
    fx = a * points->x + c * points->y + e;
    fy = b * points->x + d * points->y + f;
    points->x = fx, points->y = fy;
    points++;
  }
}
void CFX_Matrix::TransformPoint(FX_FLOAT& x, FX_FLOAT& y) const {
  FX_FLOAT fx = a * x + c * y + e;
  FX_FLOAT fy = b * x + d * y + f;
  x = fx, y = fy;
}
void CFX_Matrix::TransformPoint(int32_t& x, int32_t& y) const {
  FX_FLOAT fx = a * x + c * y + e;
  FX_FLOAT fy = b * x + d * y + f;
  x = FXSYS_round(fx);
  y = FXSYS_round(fy);
}
void CFX_Matrix::TransformRect(CFX_RectF& rect) const {
  FX_FLOAT right = rect.right(), bottom = rect.bottom();
  TransformRect(rect.left, right, bottom, rect.top);
  rect.width = right - rect.left;
  rect.height = bottom - rect.top;
}
void CFX_Matrix::TransformRect(CFX_Rect& rect) const {
  FX_FLOAT left = (FX_FLOAT)rect.left;
  FX_FLOAT top = (FX_FLOAT)rect.bottom();
  FX_FLOAT right = (FX_FLOAT)rect.right();
  FX_FLOAT bottom = (FX_FLOAT)rect.top;
  TransformRect(left, right, top, bottom);
  rect.left = FXSYS_round(left);
  rect.top = FXSYS_round(bottom);
  rect.width = FXSYS_round(right - left);
  rect.height = FXSYS_round(top - bottom);
}
void CFX_Matrix::TransformRect(FX_FLOAT& left,
                               FX_FLOAT& right,
                               FX_FLOAT& top,
                               FX_FLOAT& bottom) const {
  FX_FLOAT x[4], y[4];
  x[0] = left;
  y[0] = top;
  x[1] = left;
  y[1] = bottom;
  x[2] = right;
  y[2] = top;
  x[3] = right;
  y[3] = bottom;
  int i;
  for (i = 0; i < 4; i++) {
    Transform(x[i], y[i], x[i], y[i]);
  }
  right = left = x[0];
  top = bottom = y[0];
  for (i = 1; i < 4; i++) {
    if (right < x[i]) {
      right = x[i];
    }
    if (left > x[i]) {
      left = x[i];
    }
    if (top < y[i]) {
      top = y[i];
    }
    if (bottom > y[i]) {
      bottom = y[i];
    }
  }
}
