/*
 * Copyright © 2022 Behdad Esfahbod
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */
#ifndef HB_GEOMETRY_HH
#define HB_GEOMETRY_HH

#include "hb.hh"


struct hb_extents_t
{
  hb_extents_t () {}
  hb_extents_t (const hb_glyph_extents_t &extents) :
                xmin (hb_min (extents.x_bearing, extents.x_bearing + extents.width)),
                ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
                xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
                ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
  hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
    xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}

  bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
  bool is_void () const { return xmin > xmax; }

  void union_ (const hb_extents_t &o)
  {
    if (o.is_empty ()) return;
    if (is_empty ())
    {
      *this = o;
      return;
    }
    xmin = hb_min (xmin, o.xmin);
    ymin = hb_min (ymin, o.ymin);
    xmax = hb_max (xmax, o.xmax);
    ymax = hb_max (ymax, o.ymax);
  }

  void intersect (const hb_extents_t &o)
  {
    if (o.is_empty () || is_empty ())
    {
      *this = hb_extents_t {};
      return;
    }
    xmin = hb_max (xmin, o.xmin);
    ymin = hb_max (ymin, o.ymin);
    xmax = hb_min (xmax, o.xmax);
    ymax = hb_min (ymax, o.ymax);
  }

  void
  add_point (float x, float y)
  {
    if (unlikely (is_void ()))
    {
      xmin = xmax = x;
      ymin = ymax = y;
    }
    else
    {
      xmin = hb_min (xmin, x);
      ymin = hb_min (ymin, y);
      xmax = hb_max (xmax, x);
      ymax = hb_max (ymax, y);
    }
  }

  hb_glyph_extents_t to_glyph_extents (bool xneg = false, bool yneg = false) const
  {
    hb_position_t x0 = (hb_position_t) roundf (xmin);
    hb_position_t y0 = (hb_position_t) roundf (ymin);
    hb_position_t x1 = (hb_position_t) roundf (xmax);
    hb_position_t y1 = (hb_position_t) roundf (ymax);
    return hb_glyph_extents_t {xneg ? x1 : x0,
                               yneg ? y0 : y1,
                               xneg ? x0 - x1 : x1 - x0,
                               yneg ? y1 - y0 : y0 - y1};
  }

  float xmin = 0.f;
  float ymin = 0.f;
  float xmax = -1.f;
  float ymax = -1.f;
};

struct hb_transform_t
{
  hb_transform_t () {}
  hb_transform_t (float xx, float yx,
                  float xy, float yy,
                  float x0, float y0) :
    xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}

  bool is_identity () const
  {
    return xx == 1.f && yx == 0.f &&
           xy == 0.f && yy == 1.f &&
           x0 == 0.f && y0 == 0.f;
  }

  void multiply (const hb_transform_t &o)
  {
    /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
    hb_transform_t r;

    r.xx = o.xx * xx + o.yx * xy;
    r.yx = o.xx * yx + o.yx * yy;

    r.xy = o.xy * xx + o.yy * xy;
    r.yy = o.xy * yx + o.yy * yy;

    r.x0 = o.x0 * xx + o.y0 * xy + x0;
    r.y0 = o.x0 * yx + o.y0 * yy + y0;

    *this = r;
  }

  void transform_distance (float &dx, float &dy) const
  {
    float new_x = xx * dx + xy * dy;
    float new_y = yx * dx + yy * dy;
    dx = new_x;
    dy = new_y;
  }

  void transform_point (float &x, float &y) const
  {
    transform_distance (x, y);
    x += x0;
    y += y0;
  }

  void transform_extents (hb_extents_t &extents) const
  {
    float quad_x[4], quad_y[4];

    quad_x[0] = extents.xmin;
    quad_y[0] = extents.ymin;
    quad_x[1] = extents.xmin;
    quad_y[1] = extents.ymax;
    quad_x[2] = extents.xmax;
    quad_y[2] = extents.ymin;
    quad_x[3] = extents.xmax;
    quad_y[3] = extents.ymax;

    extents = hb_extents_t {};
    for (unsigned i = 0; i < 4; i++)
    {
      transform_point (quad_x[i], quad_y[i]);
      extents.add_point (quad_x[i], quad_y[i]);
    }
  }

  void transform (const hb_transform_t &o) { multiply (o); }

  void translate (float x, float y)
  {
    if (x == 0.f && y == 0.f)
      return;

    x0 += xx * x + xy * y;
    y0 += yx * x + yy * y;
  }

  void scale (float scaleX, float scaleY)
  {
    if (scaleX == 1.f && scaleY == 1.f)
      return;

    xx *= scaleX;
    yx *= scaleX;
    xy *= scaleY;
    yy *= scaleY;
  }

  void rotate (float rotation)
  {
    if (rotation == 0.f)
      return;

    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
    rotation = rotation * HB_PI;
    float c;
    float s;
#ifdef HAVE_SINCOSF
    sincosf (rotation, &s, &c);
#else
    c = cosf (rotation);
    s = sinf (rotation);
#endif
    auto other = hb_transform_t{c, s, -s, c, 0.f, 0.f};
    transform (other);
  }

  void skew (float skewX, float skewY)
  {
    if (skewX == 0.f && skewY == 0.f)
      return;

    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
    skewX = skewX * HB_PI;
    skewY = skewY * HB_PI;
    auto other = hb_transform_t{1.f,
                                skewY ? tanf (skewY) : 0.f,
                                skewX ? tanf (skewX) : 0.f,
                                1.f,
                                0.f, 0.f};
    transform (other);
  }

  float xx = 1.f;
  float yx = 0.f;
  float xy = 0.f;
  float yy = 1.f;
  float x0 = 0.f;
  float y0 = 0.f;
};

#define HB_TRANSFORM_IDENTITY hb_transform_t{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}

struct hb_bounds_t
{
  enum status_t {
    UNBOUNDED,
    BOUNDED,
    EMPTY,
  };

  hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
  hb_bounds_t (const hb_extents_t &extents) :
    status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}

  void union_ (const hb_bounds_t &o)
  {
    if (o.status == UNBOUNDED)
      status = UNBOUNDED;
    else if (o.status == BOUNDED)
    {
      if (status == EMPTY)
        *this = o;
      else if (status == BOUNDED)
        extents.union_ (o.extents);
    }
  }

  void intersect (const hb_bounds_t &o)
  {
    if (o.status == EMPTY)
      status = EMPTY;
    else if (o.status == BOUNDED)
    {
      if (status == UNBOUNDED)
        *this = o;
      else if (status == BOUNDED)
      {
        extents.intersect (o.extents);
        if (extents.is_empty ())
          status = EMPTY;
      }
    }
  }

  status_t status;
  hb_extents_t extents;
};

struct hb_transform_decomposed_t
{
  float translateX = 0;
  float translateY = 0;
  float rotation = 0;  // in degrees, counter-clockwise
  float scaleX = 1;
  float scaleY = 1;
  float skewX = 0;  // in degrees, counter-clockwise
  float skewY = 0;  // in degrees, counter-clockwise
  float tCenterX = 0;
  float tCenterY = 0;

  operator bool () const
  {
    return translateX || translateY ||
           rotation ||
           scaleX != 1 || scaleY != 1 ||
           skewX || skewY ||
           tCenterX || tCenterY;
  }

  hb_transform_t to_transform () const
  {
    hb_transform_t t;
    t.translate (translateX + tCenterX, translateY + tCenterY);
    t.rotate (rotation);
    t.scale (scaleX, scaleY);
    t.skew (-skewX, skewY);
    t.translate (-tCenterX, -tCenterY);
    return t;
  }
};


#endif /* HB_GEOMETRY_HH */
