/*
 * Copyright (C) 2012 Google, Inc.
 * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "core/layout/svg/LayoutSVGEllipse.h"

#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
#include <cmath>

namespace blink {

LayoutSVGEllipse::LayoutSVGEllipse(SVGGeometryElement* node)
    : LayoutSVGShape(node), m_usePathFallback(false) {}

LayoutSVGEllipse::~LayoutSVGEllipse() {}

void LayoutSVGEllipse::updateShapeFromElement() {
  // Before creating a new object we need to clear the cached bounding box
  // to avoid using garbage.
  m_fillBoundingBox = FloatRect();
  m_strokeBoundingBox = FloatRect();
  m_center = FloatPoint();
  m_radii = FloatSize();
  m_usePathFallback = false;

  calculateRadiiAndCenter();

  // Spec: "A negative value is an error. A value of zero disables rendering of
  // the element."
  if (m_radii.width() < 0 || m_radii.height() < 0)
    return;

  if (!m_radii.isEmpty()) {
    // Fall back to LayoutSVGShape and path-based hit detection if the ellipse
    // has a non-scaling or discontinuous stroke.
    if (hasNonScalingStroke() || !hasContinuousStroke()) {
      LayoutSVGShape::updateShapeFromElement();
      m_usePathFallback = true;
      return;
    }
  }

  clearPath();

  m_fillBoundingBox =
      FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(),
                2 * m_radii.width(), 2 * m_radii.height());
  m_strokeBoundingBox = m_fillBoundingBox;
  if (style()->svgStyle().hasStroke())
    m_strokeBoundingBox.inflate(strokeWidth() / 2);
  if (element())
    element()->setNeedsResizeObserverUpdate();
}

void LayoutSVGEllipse::calculateRadiiAndCenter() {
  ASSERT(element());
  SVGLengthContext lengthContext(element());
  m_center = FloatPoint(
      lengthContext.valueForLength(style()->svgStyle().cx(), styleRef(),
                                   SVGLengthMode::Width),
      lengthContext.valueForLength(style()->svgStyle().cy(), styleRef(),
                                   SVGLengthMode::Height));

  if (isSVGCircleElement(*element())) {
    float radius = lengthContext.valueForLength(
        style()->svgStyle().r(), styleRef(), SVGLengthMode::Other);
    m_radii = FloatSize(radius, radius);
  } else {
    m_radii = FloatSize(
        lengthContext.valueForLength(style()->svgStyle().rx(), styleRef(),
                                     SVGLengthMode::Width),
        lengthContext.valueForLength(style()->svgStyle().ry(), styleRef(),
                                     SVGLengthMode::Height));
  }
}

bool LayoutSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point) {
  // The optimized check below for circles does not support non-scaling or
  // discontinuous strokes.
  if (m_usePathFallback || !hasContinuousStroke() ||
      m_radii.width() != m_radii.height()) {
    if (!hasPath())
      createPath();
    return LayoutSVGShape::shapeDependentStrokeContains(point);
  }

  const FloatPoint center =
      FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
  const float halfStrokeWidth = strokeWidth() / 2;
  const float r = m_radii.width();
  return std::abs(center.length() - r) <= halfStrokeWidth;
}

bool LayoutSVGEllipse::shapeDependentFillContains(
    const FloatPoint& point,
    const WindRule fillRule) const {
  const FloatPoint center =
      FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());

  // This works by checking if the point satisfies the ellipse equation.
  // (x/rX)^2 + (y/rY)^2 <= 1
  const float xrX = center.x() / m_radii.width();
  const float yrY = center.y() / m_radii.height();
  return xrX * xrX + yrY * yrY <= 1.0;
}

bool LayoutSVGEllipse::hasContinuousStroke() const {
  const SVGComputedStyle& svgStyle = style()->svgStyle();
  return svgStyle.strokeDashArray()->isEmpty();
}

}  // namespace blink
