/*
 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"

#include <algorithm>
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

FloatRoundedRect::FloatRoundedRect(float x, float y, float width, float height)
    : rect_(x, y, width, height) {}

FloatRoundedRect::FloatRoundedRect(const FloatRect& rect, const Radii& radii)
    : rect_(rect), radii_(radii) {}

FloatRoundedRect::FloatRoundedRect(const IntRect& rect, const Radii& radii)
    : rect_(FloatRect(rect)), radii_(radii) {}

FloatRoundedRect::FloatRoundedRect(const FloatRect& rect,
                                   const FloatSize& top_left,
                                   const FloatSize& top_right,
                                   const FloatSize& bottom_left,
                                   const FloatSize& bottom_right)
    : rect_(rect), radii_(top_left, top_right, bottom_left, bottom_right) {}

void FloatRoundedRect::Radii::Scale(float factor) {
  if (factor == 1)
    return;

  // If either radius on a corner becomes zero, reset both radii on that corner.
  top_left_.Scale(factor);
  if (!top_left_.Width() || !top_left_.Height())
    top_left_ = FloatSize();
  top_right_.Scale(factor);
  if (!top_right_.Width() || !top_right_.Height())
    top_right_ = FloatSize();
  bottom_left_.Scale(factor);
  if (!bottom_left_.Width() || !bottom_left_.Height())
    bottom_left_ = FloatSize();
  bottom_right_.Scale(factor);
  if (!bottom_right_.Width() || !bottom_right_.Height())
    bottom_right_ = FloatSize();
}

void FloatRoundedRect::Radii::ScaleAndFloor(float factor) {
  if (factor == 1)
    return;

  // If either radius on a corner becomes zero, reset both radii on that corner.
  top_left_.ScaleAndFloor(factor);
  if (!top_left_.Width() || !top_left_.Height())
    top_left_ = FloatSize();
  top_right_.ScaleAndFloor(factor);
  if (!top_right_.Width() || !top_right_.Height())
    top_right_ = FloatSize();
  bottom_left_.ScaleAndFloor(factor);
  if (!bottom_left_.Width() || !bottom_left_.Height())
    bottom_left_ = FloatSize();
  bottom_right_.ScaleAndFloor(factor);
  if (!bottom_right_.Width() || !bottom_right_.Height())
    bottom_right_ = FloatSize();
}

void FloatRoundedRect::Radii::Shrink(float top_width,
                                     float bottom_width,
                                     float left_width,
                                     float right_width) {
  DCHECK_GE(top_width, 0);
  DCHECK_GE(bottom_width, 0);
  DCHECK_GE(left_width, 0);
  DCHECK_GE(right_width, 0);

  top_left_.SetWidth(std::max<float>(0, top_left_.Width() - left_width));
  top_left_.SetHeight(std::max<float>(0, top_left_.Height() - top_width));

  top_right_.SetWidth(std::max<float>(0, top_right_.Width() - right_width));
  top_right_.SetHeight(std::max<float>(0, top_right_.Height() - top_width));

  bottom_left_.SetWidth(std::max<float>(0, bottom_left_.Width() - left_width));
  bottom_left_.SetHeight(
      std::max<float>(0, bottom_left_.Height() - bottom_width));

  bottom_right_.SetWidth(
      std::max<float>(0, bottom_right_.Width() - right_width));
  bottom_right_.SetHeight(
      std::max<float>(0, bottom_right_.Height() - bottom_width));
}

void FloatRoundedRect::Radii::Expand(float top_width,
                                     float bottom_width,
                                     float left_width,
                                     float right_width) {
  DCHECK_GE(top_width, 0);
  DCHECK_GE(bottom_width, 0);
  DCHECK_GE(left_width, 0);
  DCHECK_GE(right_width, 0);
  if (top_left_.Width() > 0 && top_left_.Height() > 0) {
    top_left_.SetWidth(top_left_.Width() + left_width);
    top_left_.SetHeight(top_left_.Height() + top_width);
  }
  if (top_right_.Width() > 0 && top_right_.Height() > 0) {
    top_right_.SetWidth(top_right_.Width() + right_width);
    top_right_.SetHeight(top_right_.Height() + top_width);
  }
  if (bottom_left_.Width() > 0 && bottom_left_.Height() > 0) {
    bottom_left_.SetWidth(bottom_left_.Width() + left_width);
    bottom_left_.SetHeight(bottom_left_.Height() + bottom_width);
  }
  if (bottom_right_.Width() > 0 && bottom_right_.Height() > 0) {
    bottom_right_.SetWidth(bottom_right_.Width() + right_width);
    bottom_right_.SetHeight(bottom_right_.Height() + bottom_width);
  }
}

static inline float CornerRectIntercept(float y, const FloatRect& corner_rect) {
  DCHECK_GT(corner_rect.Height(), 0);
  return corner_rect.Width() *
         sqrt(1 - (y * y) / (corner_rect.Height() * corner_rect.Height()));
}

FloatRect FloatRoundedRect::RadiusCenterRect() const {
  FloatRectOutsets maximum_radius_insets(
      -std::max(radii_.TopLeft().Height(), radii_.TopRight().Height()),
      -std::max(radii_.TopRight().Width(), radii_.BottomRight().Width()),
      -std::max(radii_.BottomLeft().Height(), radii_.BottomRight().Height()),
      -std::max(radii_.TopLeft().Width(), radii_.BottomLeft().Width()));
  FloatRect center_rect(rect_);
  center_rect.Expand(maximum_radius_insets);
  return center_rect;
}

bool FloatRoundedRect::XInterceptsAtY(float y,
                                      float& min_x_intercept,
                                      float& max_x_intercept) const {
  if (y < Rect().Y() || y > Rect().MaxY())
    return false;

  if (!IsRounded()) {
    min_x_intercept = Rect().X();
    max_x_intercept = Rect().MaxX();
    return true;
  }

  const FloatRect& top_left_rect = TopLeftCorner();
  const FloatRect& bottom_left_rect = BottomLeftCorner();

  if (!top_left_rect.IsEmpty() && y >= top_left_rect.Y() &&
      y < top_left_rect.MaxY())
    min_x_intercept =
        top_left_rect.MaxX() -
        CornerRectIntercept(top_left_rect.MaxY() - y, top_left_rect);
  else if (!bottom_left_rect.IsEmpty() && y >= bottom_left_rect.Y() &&
           y <= bottom_left_rect.MaxY())
    min_x_intercept =
        bottom_left_rect.MaxX() -
        CornerRectIntercept(y - bottom_left_rect.Y(), bottom_left_rect);
  else
    min_x_intercept = rect_.X();

  const FloatRect& top_right_rect = TopRightCorner();
  const FloatRect& bottom_right_rect = BottomRightCorner();

  if (!top_right_rect.IsEmpty() && y >= top_right_rect.Y() &&
      y <= top_right_rect.MaxY())
    max_x_intercept =
        top_right_rect.X() +
        CornerRectIntercept(top_right_rect.MaxY() - y, top_right_rect);
  else if (!bottom_right_rect.IsEmpty() && y >= bottom_right_rect.Y() &&
           y <= bottom_right_rect.MaxY())
    max_x_intercept =
        bottom_right_rect.X() +
        CornerRectIntercept(y - bottom_right_rect.Y(), bottom_right_rect);
  else
    max_x_intercept = rect_.MaxX();

  return true;
}

void FloatRoundedRect::InflateWithRadii(int size) {
  FloatRect old = rect_;

  rect_.Inflate(size);
  // Considering the inflation factor of shorter size to scale the radii seems
  // appropriate here
  float factor;
  if (rect_.Width() < rect_.Height())
    factor = old.Width() ? (float)rect_.Width() / old.Width() : int(0);
  else
    factor = old.Height() ? (float)rect_.Height() / old.Height() : int(0);

  radii_.Scale(factor);
}

bool FloatRoundedRect::IntersectsQuad(const FloatQuad& quad) const {
  if (!quad.IntersectsRect(rect_))
    return false;

  const FloatSize& top_left = radii_.TopLeft();
  if (!top_left.IsEmpty()) {
    FloatRect rect(rect_.X(), rect_.Y(), top_left.Width(), top_left.Height());
    if (quad.IntersectsRect(rect)) {
      FloatPoint center(rect_.X() + top_left.Width(),
                        rect_.Y() + top_left.Height());
      FloatSize size(top_left.Width(), top_left.Height());
      if (!quad.IntersectsEllipse(center, size))
        return false;
    }
  }

  const FloatSize& top_right = radii_.TopRight();
  if (!top_right.IsEmpty()) {
    FloatRect rect(rect_.MaxX() - top_right.Width(), rect_.Y(),
                   top_right.Width(), top_right.Height());
    if (quad.IntersectsRect(rect)) {
      FloatPoint center(rect_.MaxX() - top_right.Width(),
                        rect_.Y() + top_right.Height());
      FloatSize size(top_right.Width(), top_right.Height());
      if (!quad.IntersectsEllipse(center, size))
        return false;
    }
  }

  const FloatSize& bottom_left = radii_.BottomLeft();
  if (!bottom_left.IsEmpty()) {
    FloatRect rect(rect_.X(), rect_.MaxY() - bottom_left.Height(),
                   bottom_left.Width(), bottom_left.Height());
    if (quad.IntersectsRect(rect)) {
      FloatPoint center(rect_.X() + bottom_left.Width(),
                        rect_.MaxY() - bottom_left.Height());
      FloatSize size(bottom_left.Width(), bottom_left.Height());
      if (!quad.IntersectsEllipse(center, size))
        return false;
    }
  }

  const FloatSize& bottom_right = radii_.BottomRight();
  if (!bottom_right.IsEmpty()) {
    FloatRect rect(rect_.MaxX() - bottom_right.Width(),
                   rect_.MaxY() - bottom_right.Height(), bottom_right.Width(),
                   bottom_right.Height());
    if (quad.IntersectsRect(rect)) {
      FloatPoint center(rect_.MaxX() - bottom_right.Width(),
                        rect_.MaxY() - bottom_right.Height());
      FloatSize size(bottom_right.Width(), bottom_right.Height());
      if (!quad.IntersectsEllipse(center, size))
        return false;
    }
  }

  return true;
}

void FloatRoundedRect::Radii::IncludeLogicalEdges(
    const FloatRoundedRect::Radii& edges,
    bool is_horizontal,
    bool include_logical_left_edge,
    bool include_logical_right_edge) {
  if (include_logical_left_edge) {
    if (is_horizontal)
      bottom_left_ = edges.BottomLeft();
    else
      top_right_ = edges.TopRight();
    top_left_ = edges.TopLeft();
  }

  if (include_logical_right_edge) {
    if (is_horizontal)
      top_right_ = edges.TopRight();
    else
      bottom_left_ = edges.BottomLeft();
    bottom_right_ = edges.BottomRight();
  }
}

float CalcBorderRadiiConstraintScaleFor(const FloatRect& rect,
                                        const FloatRoundedRect::Radii& radii) {
  float factor = 1;
  float radii_sum;

  // top
  radii_sum = radii.TopLeft().Width() +
              radii.TopRight().Width();  // Casts to avoid integer overflow.
  if (radii_sum > rect.Width())
    factor = std::min(rect.Width() / radii_sum, factor);

  // bottom
  radii_sum = radii.BottomLeft().Width() + radii.BottomRight().Width();
  if (radii_sum > rect.Width())
    factor = std::min(rect.Width() / radii_sum, factor);

  // left
  radii_sum = radii.TopLeft().Height() + radii.BottomLeft().Height();
  if (radii_sum > rect.Height())
    factor = std::min(rect.Height() / radii_sum, factor);

  // right
  radii_sum = radii.TopRight().Height() + radii.BottomRight().Height();
  if (radii_sum > rect.Height())
    factor = std::min(rect.Height() / radii_sum, factor);

  DCHECK_LE(factor, 1);
  return factor;
}

void FloatRoundedRect::ConstrainRadii() {
  radii_.ScaleAndFloor(CalcBorderRadiiConstraintScaleFor(Rect(), GetRadii()));
}

void FloatRoundedRect::IncludeLogicalEdges(const Radii& edges,
                                           bool is_horizontal,
                                           bool include_logical_left_edge,
                                           bool include_logical_right_edge) {
  radii_.IncludeLogicalEdges(edges, is_horizontal, include_logical_left_edge,
                             include_logical_right_edge);
}

bool FloatRoundedRect::IsRenderable() const {
  // FIXME: remove the 0.0001 slop once this class is converted to layout units.
  return radii_.TopLeft().Width() + radii_.TopRight().Width() <=
             rect_.Width() + 0.0001 &&
         radii_.BottomLeft().Width() + radii_.BottomRight().Width() <=
             rect_.Width() + 0.0001 &&
         radii_.TopLeft().Height() + radii_.BottomLeft().Height() <=
             rect_.Height() + 0.0001 &&
         radii_.TopRight().Height() + radii_.BottomRight().Height() <=
             rect_.Height() + 0.0001;
}

void FloatRoundedRect::AdjustRadii() {
  float max_radius_width =
      std::max(radii_.TopLeft().Width() + radii_.TopRight().Width(),
               radii_.BottomLeft().Width() + radii_.BottomRight().Width());
  float max_radius_height =
      std::max(radii_.TopLeft().Height() + radii_.BottomLeft().Height(),
               radii_.TopRight().Height() + radii_.BottomRight().Height());

  if (max_radius_width <= 0 || max_radius_height <= 0) {
    radii_.Scale(0.0f);
    return;
  }
  float width_ratio = static_cast<float>(rect_.Width()) / max_radius_width;
  float height_ratio = static_cast<float>(rect_.Height()) / max_radius_height;
  radii_.Scale(width_ratio < height_ratio ? width_ratio : height_ratio);
}

std::ostream& operator<<(std::ostream& ostream, const FloatRoundedRect& rect) {
  return ostream << rect.ToString();
}

std::ostream& operator<<(std::ostream& ostream,
                         const FloatRoundedRect::Radii& radii) {
  return ostream << radii.ToString();
}

String FloatRoundedRect::Radii::ToString() const {
  return "tl:" + TopLeft().ToString() + "; tr:" + TopRight().ToString() +
         "; bl:" + BottomLeft().ToString() + "; br:" + BottomRight().ToString();
}

String FloatRoundedRect::ToString() const {
  if (Rect() == FloatRect(LayoutRect::InfiniteIntRect()))
    return "InfiniteIntRect";
  if (GetRadii().IsZero())
    return Rect().ToString();
  return Rect().ToString() + " radii:(" + GetRadii().ToString() + ")";
}

}  // namespace blink
