// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/ui/lib/escher/shape/rounded_rect.h"

#include <lib/syslog/cpp/macros.h>

#include "src/ui/lib/escher/geometry/types.h"
#include "src/ui/lib/escher/shape/mesh_spec.h"
#include "src/ui/lib/escher/util/trace_macros.h"

namespace escher {

namespace {

// Number of times that the quarter-circle that makes up each corner is
// sub-divided.  For example, if this is zero, then the corner consists of
// a single right-angled triangle.
constexpr uint32_t kCornerDivisions = 8;

// The central "square" consists of 4 vertices connected to their neighbors, and
// to a central vertex.  The 4 arms of the "cross" each share 2 vertices with
// the central square, and add 2 more.  Each corner adds kCornerDivisions more.
constexpr uint32_t kVertexCount = 1 + 4 + (4 * 2) + 4 * kCornerDivisions;

// The central "square" consists of 4 triangles, and the 4 arms of the "cross"
// each have 2.
constexpr uint32_t kTriangleCount = 4 + (4 * 2) + 4 * (kCornerDivisions + 1);

// Triangles have 3 indices.
constexpr uint32_t kIndexCount = kTriangleCount * 3;

// Vertex format used when tessellating a RoundedRectSpec (for now, only a
// single format is supported).
struct PosUvVertex {
  vec2 pos;
  vec2 uv;
};

struct PosVertex {
  vec2 pos;
};

struct UvVertex {
  vec2 uv;
};

}  // anonymous namespace

RoundedRectSpec::RoundedRectSpec(float width, float height, float top_left_radius,
                                 float top_right_radius, float bottom_right_radius,
                                 float bottom_left_radius)
    : width(width),
      height(height),
      top_left_radius(top_left_radius),
      top_right_radius(top_right_radius),
      bottom_right_radius(bottom_right_radius),
      bottom_left_radius(bottom_left_radius) {}

RoundedRectSpec::RoundedRectSpec()
    : width(0.f),
      height(0.f),
      top_left_radius(0.f),
      top_right_radius(0.f),
      bottom_right_radius(0.f),
      bottom_left_radius(0.f) {}

// Return the number of vertices and indices that are required to tessellate the
// specified rounded-rect.
std::pair<uint32_t, uint32_t> GetRoundedRectMeshVertexAndIndexCounts(const RoundedRectSpec& spec) {
  return std::make_pair(kVertexCount, kIndexCount);
}

// See escher/shape/doc/RoundedRectTessellation.JPG.
void GenerateRoundedRectIndices(const RoundedRectSpec& spec, const MeshSpec& mesh_spec,
                                void* indices_out, uint32_t max_bytes) {
  TRACE_DURATION("gfx", "escher::GenerateRoundedRectIndices");

  FX_DCHECK(max_bytes >= kIndexCount * sizeof(MeshSpec::IndexType));
  uint32_t* indices = static_cast<uint32_t*>(indices_out);

  // Central square triangles.
  indices[0] = 0;
  indices[1] = 4;
  indices[2] = 1;
  indices[3] = 0;
  indices[4] = 1;
  indices[5] = 2;
  indices[6] = 0;
  indices[7] = 2;
  indices[8] = 3;
  indices[9] = 0;
  indices[10] = 3;
  indices[11] = 4;

  // "Cross arm 1"  triangles.
  indices[12] = 1;
  indices[13] = 7;
  indices[14] = 2;
  indices[15] = 1;
  indices[16] = 6;
  indices[17] = 7;

  // "Cross arm 2"  triangles.
  indices[18] = 2;
  indices[19] = 9;
  indices[20] = 3;
  indices[21] = 2;
  indices[22] = 8;
  indices[23] = 9;

  // "Cross arm 3"  triangles.
  indices[24] = 3;
  indices[25] = 11;
  indices[26] = 4;
  indices[27] = 3;
  indices[28] = 10;
  indices[29] = 11;

  // "Cross arm 4"  triangles.
  indices[30] = 4;
  indices[31] = 5;
  indices[32] = 1;
  indices[33] = 4;
  indices[34] = 12;
  indices[35] = 5;

  // WARNING: here's where it gets confusing; the number of indices generated is
  // dependent on kCornerDivisions.

  // We've already generated output indices for the "cross triangles".
  constexpr uint32_t kCrossTriangles = 12;
  // Holds the position of the next index to output.
  uint32_t out = kCrossTriangles * 3;
  // Holds the highest index of any vertex used thus far (the central "cross"
  // consists of 13 vertices, whose indices are 0-12).
  uint32_t highest_index = 12;

  // These are the indices of the 4 triangles that would be output if
  // kCornerDivisions were zero.
  const uint32_t corner_tris[] = {1, 6, 5, 2, 8, 7, 3, 10, 9, 4, 12, 11};

  // For each corner, generate wedges in clockwise order.
  for (uint32_t corner = 0; corner < 4; ++corner) {
    // Index of the vertex at the center of the current corner.
    const uint32_t center = corner_tris[corner * 3];
    // As we move clockwise around the corner, this holds the index of the
    // previous perimeter vertex.
    uint32_t prev = corner_tris[corner * 3 + 2];

    for (uint32_t i = 0; i < kCornerDivisions; ++i) {
      indices[out++] = center;
      indices[out++] = prev;
      indices[out++] = prev = ++highest_index;
    }
    // One last triangle (or the only one, if kCornerDivisions == 0).
    indices[out++] = center;
    indices[out++] = prev;
    indices[out++] = corner_tris[corner * 3 + 1];
  }

  FX_DCHECK(out == kIndexCount);
}

namespace {

// Helper for GenerateRoundedRectVertices().
template <typename VertT>
void GenerateRoundedRectVertexUVs(const RoundedRectSpec& spec, VertT* verts) {
  TRACE_DURATION("gfx", "escher::GenerateRoundedRectVertexUVs");

  const float width = spec.width;
  const float height = spec.height;

  // First compute UV coordinates of the four "corner centers".
  verts[1].uv = vec2(spec.top_left_radius / width, spec.top_left_radius / height);
  verts[2].uv = vec2(1.f - spec.top_right_radius / width, spec.top_right_radius / height);
  verts[3].uv =
      vec2(1.f - spec.bottom_right_radius / width, 1.f - spec.bottom_right_radius / height);
  verts[4].uv = vec2(spec.bottom_left_radius / width, 1.f - spec.bottom_left_radius / height);

  // The "center" vertex is the average of the four "corner centers".
  verts[0].uv = 0.25f * ((verts[1].uv + verts[2].uv + verts[3].uv + verts[4].uv));

  // Next, compute UV coords for the 8 vertices where the rounded corners meet
  // the straight side sections.
  verts[6].uv = vec2(verts[1].uv.x, 0.f);
  verts[7].uv = vec2(verts[2].uv.x, 0.f);
  verts[8].uv = vec2(1.f, verts[2].uv.y);
  verts[9].uv = vec2(1.f, verts[3].uv.y);
  verts[10].uv = vec2(verts[3].uv.x, 1.f);
  verts[11].uv = vec2(verts[4].uv.x, 1.f);
  verts[12].uv = vec2(0.f, verts[4].uv.y);
  verts[5].uv = vec2(0.f, verts[1].uv.y);

  // Next, compute UV coords for the vertices that make up the rounded corners.
  // We start at index 13; indices 0-12 were computed above.
  uint32_t out = 13;

  constexpr float kPI = 3.14159265f;
  constexpr float kAngleStep = kPI / 2 / (kCornerDivisions + 1);

  // Generate UV coordinates for top-left corner.
  float angle = kPI + kAngleStep;
  vec2 scale = vec2(spec.top_left_radius / width, spec.top_left_radius / height);
  for (size_t i = 0; i < kCornerDivisions; ++i) {
    verts[out++].uv = verts[1].uv + vec2(cos(angle), sin(angle)) * scale;
    angle += kAngleStep;
  }

  // Generate UV coordinates for top-right corner.
  angle = 1.5f * kPI + kAngleStep;
  scale = vec2(spec.top_right_radius / width, spec.top_right_radius / height);
  for (size_t i = 0; i < kCornerDivisions; ++i) {
    verts[out++].uv = verts[2].uv + vec2(cos(angle), sin(angle)) * scale;
    angle += kAngleStep;
  }

  // Generate UV coordinates for bottom-right corner.
  angle = kAngleStep;
  scale = vec2(spec.bottom_right_radius / width, spec.bottom_right_radius / height);
  for (size_t i = 0; i < kCornerDivisions; ++i) {
    verts[out++].uv = verts[3].uv + vec2(cos(angle), sin(angle)) * scale;
    angle += kAngleStep;
  }

  // Generate UV coordinates for bottom-right corner.
  angle = 0.5f * kPI + kAngleStep;
  scale = vec2(spec.bottom_left_radius / width, spec.bottom_left_radius / height);
  for (size_t i = 0; i < kCornerDivisions; ++i) {
    verts[out++].uv = verts[4].uv + vec2(cos(angle), sin(angle)) * scale;
    angle += kAngleStep;
  }
}

// Helper for GenerateRoundedRectVertices().
template <typename UvVertT, typename PosVertT>
void GenerateRoundedRectVertexPositionsFromUVs(const RoundedRectSpec& spec, UvVertT* uv_verts,
                                               PosVertT* pos_verts) {
  TRACE_DURATION("gfx", "escher::GenerateRoundedRectVertexPositionsFromUVs");

  const vec2 extent(spec.width, spec.height);
  const vec2 offset = -0.5f * extent;
  for (size_t i = 0; i < kVertexCount; ++i) {
    pos_verts[i].pos = uv_verts[i].uv * extent + offset;
  }
}

}  // namespace

void GenerateRoundedRectVertices(const RoundedRectSpec& spec, const MeshSpec& mesh_spec,
                                 void* vertices_out, uint32_t max_bytes) {
  TRACE_DURATION("gfx", "escher::GenerateRoundedRectVertices");

  const float width = spec.width;
  const float height = spec.height;
  FX_DCHECK(width >= spec.top_left_radius + spec.top_right_radius);
  FX_DCHECK(width >= spec.bottom_left_radius + spec.bottom_right_radius);
  FX_DCHECK(height >= spec.top_left_radius + spec.bottom_left_radius);
  FX_DCHECK(height >= spec.top_right_radius + spec.bottom_right_radius);
  FX_DCHECK(mesh_spec.total_attribute_count() == 2);
  FX_DCHECK(mesh_spec.attributes[0] == (MeshAttribute::kPosition2D | MeshAttribute::kUV));
  FX_DCHECK(max_bytes >= kVertexCount * mesh_spec.stride(0));
  FX_DCHECK(sizeof(PosUvVertex) == mesh_spec.stride(0));
  FX_DCHECK(0U == mesh_spec.attribute_offset(0, MeshAttribute::kPosition2D));
  FX_DCHECK(sizeof(vec2) == mesh_spec.attribute_offset(0, MeshAttribute::kUV));

  // We first generate the UV-coordinates for each vertex, then make a second
  // pass where we use these UV-coords to generate the vertex positions.
  PosUvVertex* const verts = static_cast<PosUvVertex*>(vertices_out);
  GenerateRoundedRectVertexUVs(spec, verts);
  GenerateRoundedRectVertexPositionsFromUVs(spec, verts, verts);
}

void GenerateRoundedRectVertices(const RoundedRectSpec& spec, const MeshSpec& mesh_spec,
                                 void* primary_attributes_out, uint32_t max_primary_attribute_bytes,
                                 void* secondary_attributes_out,
                                 uint32_t max_secondary_attribute_bytes) {
  TRACE_DURATION("gfx", "escher::GenerateRoundedRectVertices");

  const float width = spec.width;
  const float height = spec.height;
  FX_DCHECK(width >= spec.top_left_radius + spec.top_right_radius);
  FX_DCHECK(width >= spec.bottom_left_radius + spec.bottom_right_radius);
  FX_DCHECK(height >= spec.top_left_radius + spec.bottom_left_radius);
  FX_DCHECK(height >= spec.top_right_radius + spec.bottom_right_radius);
  FX_DCHECK(mesh_spec.total_attribute_count() == 2);
  FX_DCHECK(mesh_spec.attributes[0] == MeshAttribute::kPosition2D);
  FX_DCHECK(mesh_spec.attributes[1] == MeshAttribute::kUV);
  FX_DCHECK(max_primary_attribute_bytes == kVertexCount * (mesh_spec.stride(0)));
  FX_DCHECK(max_secondary_attribute_bytes == kVertexCount * (mesh_spec.stride(1)));
  FX_DCHECK(sizeof(PosVertex) == mesh_spec.stride(0));
  FX_DCHECK(sizeof(UvVertex) == mesh_spec.stride(1));

  // We first generate the UV-coordinates for each vertex, then make a second
  // pass where we use these UV-coords to generate the vertex positions.
  PosVertex* const positions = static_cast<PosVertex*>(primary_attributes_out);
  UvVertex* const uvs = reinterpret_cast<UvVertex*>(secondary_attributes_out);
  GenerateRoundedRectVertexUVs(spec, uvs);
  GenerateRoundedRectVertexPositionsFromUVs(spec, uvs, positions);
}

bool RoundedRectSpec::ContainsPoint(vec2 point) const {
  // Adjust point so that we can test against a rect with bounds (0,0),(w,h).
  // This is saves some multiplications, but mostly makes the code below more
  // concise.
  point += vec2(0.5f * width, 0.5f * height);

  // Check if point is outside of the bounding rectangle; if so, we don't need
  // to test the corner cases.
  if (point.x < 0 || point.y < 0 || point.x > width || point.y > height) {
    return false;
  }
  // Now we know that the point is would be contained, if all corner radii were
  // zero.  But, since the radii are not zero, it is possible that the point is
  // outside one of the four quarter-circles that comprise the rounded corners.

  // Check if point is inside the top-left corner.
  {
    // Start by computing the vector from the corner-center to the test-point,
    // and checking whether the direction of the vector is within the corner's
    // quarter-circle arc.  If so, we can immediately determine whether or not
    // the point is contained; otherwise, we need to test against the other
    // corners.
    float rad = top_left_radius;
    vec2 diff = point - vec2(rad, rad);
    if (diff.x < 0.f && diff.y < 0.f) {
      // The direction is within the corner's arc.  Compare squared-distances to
      // determine whether the point is beyond the arc.
      return diff.x * diff.x + diff.y * diff.y <= rad * rad;
    } else {
      // The direction is not within the corner's quarter circle, so we proceed
      // on to the other corners.
    }
  }

  // Check if point is inside the top-right corner.
  //
  // For this corner, and subsequent ones, we follow the same approach as above,
  // with slight adjustments to the computation of the difference-vector, and
  // how we test the direction of that vector.
  {
    float rad = top_right_radius;
    vec2 diff = point - vec2(width - rad, rad);
    if (diff.x > 0.f && diff.y < 0.f) {
      return diff.x * diff.x + diff.y * diff.y <= rad * rad;
    }
  }

  // Check if point is inside the bottom-right corner.
  {
    float rad = bottom_right_radius;
    vec2 diff = point - vec2(width - rad, height - rad);
    if (diff.x > 0.f && diff.y > 0.f) {
      return diff.x * diff.x + diff.y * diff.y <= rad * rad;
    }
  }

  // Check if point is inside the bottom-left corner.
  {
    float rad = bottom_left_radius;
    vec2 diff = point - vec2(rad, height - rad);
    if (diff.x < 0.f && diff.y > 0.f) {
      return diff.x * diff.x + diff.y * diff.y <= rad * rad;
    }
  }

  // Point isn't in the corner areas, so it is definitely contained.
  return true;
}

RoundedRectSpec RoundedRectSpec::operator*(float t) const {
  return RoundedRectSpec(width * t, height * t, top_left_radius * t, top_right_radius * t,
                         bottom_right_radius * t, bottom_left_radius * t);
}

RoundedRectSpec RoundedRectSpec::operator+(const RoundedRectSpec& other) const {
  return RoundedRectSpec(
      width + other.width, height + other.height, top_left_radius + other.top_left_radius,
      top_right_radius + other.top_right_radius, bottom_right_radius + other.bottom_right_radius,
      bottom_left_radius + other.bottom_left_radius);
}

}  // namespace escher
