// 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 "lib/escher/shape/rounded_rect.h"

#include "lib/escher/geometry/types.h"
#include "lib/escher/shape/mesh_spec.h"
#include "lib/escher/util/trace_macros.h"
#include "lib/fxl/logging.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) {}

// 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");

  FXL_DCHECK(max_bytes >= kIndexCount * sizeof(uint32_t));
  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];
  }

  FXL_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;
  FXL_DCHECK(width >= spec.top_left_radius + spec.top_right_radius);
  FXL_DCHECK(width >= spec.bottom_left_radius + spec.bottom_right_radius);
  FXL_DCHECK(height >= spec.top_left_radius + spec.bottom_left_radius);
  FXL_DCHECK(height >= spec.top_right_radius + spec.bottom_right_radius);
  FXL_DCHECK(mesh_spec.total_attribute_count() == 2);
  FXL_DCHECK(mesh_spec.attributes[0] ==
             (MeshAttribute::kPosition2D | MeshAttribute::kUV));
  FXL_DCHECK(max_bytes >= kVertexCount * mesh_spec.stride(0));
  FXL_DCHECK(sizeof(PosUvVertex) == mesh_spec.stride(0));
  FXL_DCHECK(0U == mesh_spec.attribute_offset(0, MeshAttribute::kPosition2D));
  FXL_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;
  FXL_DCHECK(width >= spec.top_left_radius + spec.top_right_radius);
  FXL_DCHECK(width >= spec.bottom_left_radius + spec.bottom_right_radius);
  FXL_DCHECK(height >= spec.top_left_radius + spec.bottom_left_radius);
  FXL_DCHECK(height >= spec.top_right_radius + spec.bottom_right_radius);
  FXL_DCHECK(mesh_spec.total_attribute_count() == 2);
  FXL_DCHECK(mesh_spec.attributes[0] == MeshAttribute::kPosition2D);
  FXL_DCHECK(mesh_spec.attributes[1] == MeshAttribute::kUV);
  FXL_DCHECK(max_primary_attribute_bytes ==
             kVertexCount * (mesh_spec.stride(0)));
  FXL_DCHECK(max_secondary_attribute_bytes ==
             kVertexCount * (mesh_spec.stride(1)));
  FXL_DCHECK(sizeof(PosVertex) == mesh_spec.stride(0));
  FXL_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
