// 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/fgas/graphics/cfgas_gepath.h"

#include "core/fxge/cfx_path.h"

CFGAS_GEPath::CFGAS_GEPath() = default;

CFGAS_GEPath::~CFGAS_GEPath() = default;

void CFGAS_GEPath::Clear() {
  path_.Clear();
}

void CFGAS_GEPath::Close() {
  path_.ClosePath();
}

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

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

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

void CFGAS_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 CFGAS_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)));
  path_.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)));
  path_.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));
  path_.AppendPoint(bezier, FXPT_TYPE::BezierTo);
}

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

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

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

void CFGAS_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);
  path_.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 CFGAS_GEPath::AddSubpath(const CFGAS_GEPath& path) {
  path_.Append(path.path_, nullptr);
}

void CFGAS_GEPath::TransformBy(const CFX_Matrix& mt) {
  path_.Transform(mt);
}
