// 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() = default;

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);
}
