blob: a2abd9cb45d1fe432c2d63d036ccb91b4290bf58 [file] [log] [blame]
/*
* Copyright (C) 2012 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 HOLDER "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 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/core/style/basic_shapes.h"
#include "third_party/blink/renderer/core/css/basic_shape_functions.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
namespace blink {
bool BasicShapeCircle::operator==(const BasicShape& o) const {
if (!IsSameType(o))
return false;
const BasicShapeCircle& other = To<BasicShapeCircle>(o);
return center_x_ == other.center_x_ && center_y_ == other.center_y_ &&
radius_ == other.radius_;
}
float BasicShapeCircle::FloatValueForRadiusInBox(FloatSize box_size) const {
if (radius_.GetType() == BasicShapeRadius::kValue)
return FloatValueForLength(
radius_.Value(),
hypotf(box_size.Width(), box_size.Height()) / sqrtf(2));
FloatPoint center =
FloatPointForCenterCoordinate(center_x_, center_y_, box_size);
float width_delta = std::abs(box_size.Width() - center.X());
float height_delta = std::abs(box_size.Height() - center.Y());
if (radius_.GetType() == BasicShapeRadius::kClosestSide)
return std::min(std::min(std::abs(center.X()), width_delta),
std::min(std::abs(center.Y()), height_delta));
// If radius.type() == BasicShapeRadius::kFarthestSide.
return std::max(std::max(center.X(), width_delta),
std::max(center.Y(), height_delta));
}
void BasicShapeCircle::GetPath(Path& path, const FloatRect& bounding_box) {
DCHECK(path.IsEmpty());
FloatPoint center =
FloatPointForCenterCoordinate(center_x_, center_y_, bounding_box.Size());
float radius = FloatValueForRadiusInBox(bounding_box.Size());
path.AddEllipse(FloatRect(center.X() - radius + bounding_box.X(),
center.Y() - radius + bounding_box.Y(), radius * 2,
radius * 2));
}
bool BasicShapeEllipse::operator==(const BasicShape& o) const {
if (!IsSameType(o))
return false;
const BasicShapeEllipse& other = To<BasicShapeEllipse>(o);
return center_x_ == other.center_x_ && center_y_ == other.center_y_ &&
radius_x_ == other.radius_x_ && radius_y_ == other.radius_y_;
}
float BasicShapeEllipse::FloatValueForRadiusInBox(
const BasicShapeRadius& radius,
float center,
float box_width_or_height) const {
if (radius.GetType() == BasicShapeRadius::kValue)
return FloatValueForLength(radius.Value(), box_width_or_height);
float width_or_height_delta = std::abs(box_width_or_height - center);
if (radius.GetType() == BasicShapeRadius::kClosestSide)
return std::min(std::abs(center), width_or_height_delta);
DCHECK_EQ(radius.GetType(), BasicShapeRadius::kFarthestSide);
return std::max(center, width_or_height_delta);
}
void BasicShapeEllipse::GetPath(Path& path, const FloatRect& bounding_box) {
DCHECK(path.IsEmpty());
FloatPoint center =
FloatPointForCenterCoordinate(center_x_, center_y_, bounding_box.Size());
float radius_x =
FloatValueForRadiusInBox(radius_x_, center.X(), bounding_box.Width());
float radius_y =
FloatValueForRadiusInBox(radius_y_, center.Y(), bounding_box.Height());
path.AddEllipse(FloatRect(center.X() - radius_x + bounding_box.X(),
center.Y() - radius_y + bounding_box.Y(),
radius_x * 2, radius_y * 2));
}
void BasicShapePolygon::GetPath(Path& path, const FloatRect& bounding_box) {
DCHECK(path.IsEmpty());
DCHECK(!(values_.size() % 2));
wtf_size_t length = values_.size();
if (!length)
return;
path.MoveTo(
FloatPoint(FloatValueForLength(values_.at(0), bounding_box.Width()) +
bounding_box.X(),
FloatValueForLength(values_.at(1), bounding_box.Height()) +
bounding_box.Y()));
for (wtf_size_t i = 2; i < length; i = i + 2) {
path.AddLineTo(FloatPoint(
FloatValueForLength(values_.at(i), bounding_box.Width()) +
bounding_box.X(),
FloatValueForLength(values_.at(i + 1), bounding_box.Height()) +
bounding_box.Y()));
}
path.CloseSubpath();
}
bool BasicShapePolygon::operator==(const BasicShape& o) const {
if (!IsSameType(o))
return false;
const BasicShapePolygon& other = To<BasicShapePolygon>(o);
return wind_rule_ == other.wind_rule_ && values_ == other.values_;
}
void BasicShapeInset::GetPath(Path& path, const FloatRect& bounding_box) {
DCHECK(path.IsEmpty());
float left = FloatValueForLength(left_, bounding_box.Width());
float top = FloatValueForLength(top_, bounding_box.Height());
FloatRect rect(
left + bounding_box.X(), top + bounding_box.Y(),
std::max<float>(bounding_box.Width() - left -
FloatValueForLength(right_, bounding_box.Width()),
0),
std::max<float>(bounding_box.Height() - top -
FloatValueForLength(bottom_, bounding_box.Height()),
0));
const FloatSize& box_size = bounding_box.Size();
auto radii = FloatRoundedRect::Radii(
FloatSizeForLengthSize(top_left_radius_, box_size),
FloatSizeForLengthSize(top_right_radius_, box_size),
FloatSizeForLengthSize(bottom_left_radius_, box_size),
FloatSizeForLengthSize(bottom_right_radius_, box_size));
FloatRoundedRect final_rect(rect, radii);
final_rect.ConstrainRadii();
path.AddRoundedRect(final_rect);
}
bool BasicShapeInset::operator==(const BasicShape& o) const {
if (!IsSameType(o))
return false;
const BasicShapeInset& other = To<BasicShapeInset>(o);
return right_ == other.right_ && top_ == other.top_ &&
bottom_ == other.bottom_ && left_ == other.left_ &&
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 blink