// Copyright 2016 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 "xfa/fxgraphics/cxfa_gepath.h"

#include "core/fxge/cfx_pathdata.h"

CXFA_GEPath::CXFA_GEPath() {}

CXFA_GEPath::~CXFA_GEPath() = default;

void CXFA_GEPath::Clear() {
  data_.Clear();
}

void CXFA_GEPath::Close() {
  data_.ClosePath();
}

void CXFA_GEPath::MoveTo(const CFX_PointF& point) {
  data_.AppendPoint(point, FXPT_TYPE::MoveTo);
}

void CXFA_GEPath::LineTo(const CFX_PointF& point) {
  data_.AppendPoint(point, FXPT_TYPE::LineTo);
}

void CXFA_GEPath::BezierTo(const CFX_PointF& c1,
                           const CFX_PointF& c2,
                           const CFX_PointF& to) {
  data_.AppendPoint(c1, FXPT_TYPE::BezierTo);
  data_.AppendPoint(c2, FXPT_TYPE::BezierTo);
  data_.AppendPoint(to, FXPT_TYPE::BezierTo);
}

void CXFA_GEPath::ArcTo(const CFX_PointF& pos,
                        const CFX_SizeF& size,
                        float start_angle,
                        float sweep_angle) {
  CFX_SizeF new_size = size / 2.0f;
  ArcToInternal(CFX_PointF(pos.x + new_size.width, pos.y + new_size.height),
                new_size, start_angle, sweep_angle);
}

void CXFA_GEPath::ArcToInternal(const CFX_PointF& pos,
                                const CFX_SizeF& size,
                                float start_angle,
                                float sweep_angle) {
  float x0 = cos(sweep_angle / 2);
  float y0 = sin(sweep_angle / 2);
  float tx = ((1.0f - x0) * 4) / (3 * 1.0f);
  float ty = y0 - ((tx * x0) / y0);

  CFX_PointF points[] = {CFX_PointF(x0 + tx, -ty), CFX_PointF(x0 + tx, ty)};
  float sn = sin(start_angle + sweep_angle / 2);
  float cs = cos(start_angle + sweep_angle / 2);

  CFX_PointF bezier;
  bezier.x = pos.x + (size.width * ((points[0].x * cs) - (points[0].y * sn)));
  bezier.y = pos.y + (size.height * ((points[0].x * sn) + (points[0].y * cs)));
  data_.AppendPoint(bezier, FXPT_TYPE::BezierTo);

  bezier.x = pos.x + (size.width * ((points[1].x * cs) - (points[1].y * sn)));
  bezier.y = pos.y + (size.height * ((points[1].x * sn) + (points[1].y * cs)));
  data_.AppendPoint(bezier, FXPT_TYPE::BezierTo);

  bezier.x = pos.x + (size.width * cos(start_angle + sweep_angle));
  bezier.y = pos.y + (size.height * sin(start_angle + sweep_angle));
  data_.AppendPoint(bezier, FXPT_TYPE::BezierTo);
}

void CXFA_GEPath::AddLine(const CFX_PointF& p1, const CFX_PointF& p2) {
  data_.AppendPoint(p1, FXPT_TYPE::MoveTo);
  data_.AppendPoint(p2, FXPT_TYPE::LineTo);
}

void CXFA_GEPath::AddRectangle(float left,
                               float top,
                               float width,
                               float height) {
  data_.AppendRect(left, top, left + width, top + height);
}

void CXFA_GEPath::AddEllipse(const CFX_RectF& rect) {
  AddArc(rect.TopLeft(), rect.Size(), 0, FX_PI * 2);
}

void CXFA_GEPath::AddArc(const CFX_PointF& original_pos,
                         const CFX_SizeF& original_size,
                         float start_angle,
                         float sweep_angle) {
  if (sweep_angle == 0)
    return;

  const float bezier_arc_angle_epsilon = 0.01f;
  while (start_angle > FX_PI * 2)
    start_angle -= FX_PI * 2;
  while (start_angle < 0)
    start_angle += FX_PI * 2;
  if (sweep_angle >= FX_PI * 2)
    sweep_angle = FX_PI * 2;
  if (sweep_angle <= -FX_PI * 2)
    sweep_angle = -FX_PI * 2;

  CFX_SizeF size = original_size / 2;
  CFX_PointF pos(original_pos.x + size.width, original_pos.y + size.height);
  data_.AppendPoint(pos + CFX_PointF(size.width * cos(start_angle),
                                     size.height * sin(start_angle)),
                    FXPT_TYPE::MoveTo);

  float total_sweep = 0;
  float local_sweep = 0;
  float prev_sweep = 0;
  bool done = false;
  do {
    if (sweep_angle < 0) {
      prev_sweep = total_sweep;
      local_sweep = -FX_PI / 2;
      total_sweep -= FX_PI / 2;
      if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) {
        local_sweep = sweep_angle - prev_sweep;
        done = true;
      }
    } else {
      prev_sweep = total_sweep;
      local_sweep = FX_PI / 2;
      total_sweep += FX_PI / 2;
      if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) {
        local_sweep = sweep_angle - prev_sweep;
        done = true;
      }
    }

    ArcToInternal(pos, size, start_angle, local_sweep);
    start_angle += local_sweep;
  } while (!done);
}

void CXFA_GEPath::AddSubpath(CXFA_GEPath* path) {
  if (!path)
    return;
  data_.Append(&path->data_, nullptr);
}

void CXFA_GEPath::TransformBy(const CFX_Matrix& mt) {
  data_.Transform(mt);
}
