123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- // Copyright 2018 The Chromium 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 "ui/gfx/geometry/rrect_f.h"
- #include <iomanip>
- #include <iostream>
- #include <sstream>
- #include "base/values.h"
- #include "third_party/skia/include/core/SkMatrix.h"
- namespace gfx {
- // Sets all x radii to x_rad, and all y radii to y_rad. If one of x_rad or
- // y_rad are zero, sets ALL radii to zero.
- RRectF::RRectF(float x,
- float y,
- float width,
- float height,
- float x_rad,
- float y_rad)
- : skrrect_(SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, width, height),
- x_rad,
- y_rad)) {
- if (IsEmpty()) {
- // Make sure that empty rects are created fully empty, not with some
- // non-zero dimensions.
- skrrect_ = SkRRect::MakeEmpty();
- }
- }
- // Directly sets all four corners.
- RRectF::RRectF(float x,
- float y,
- float width,
- float height,
- float upper_left_x,
- float upper_left_y,
- float upper_right_x,
- float upper_right_y,
- float lower_right_x,
- float lower_right_y,
- float lower_left_x,
- float lower_left_y) {
- SkVector radii[4] = {
- {upper_left_x, upper_left_y},
- {upper_right_x, upper_right_y},
- {lower_right_x, lower_right_y},
- {lower_left_x, lower_left_y},
- };
- skrrect_.setRectRadii(SkRect::MakeXYWH(x, y, width, height), radii);
- if (IsEmpty()) {
- // Make sure that empty rects are created fully empty, not with some
- // non-zero dimensions.
- skrrect_ = SkRRect::MakeEmpty();
- }
- }
- gfx::Vector2dF RRectF::GetSimpleRadii() const {
- DCHECK(GetType() <= Type::kOval);
- SkPoint result = skrrect_.getSimpleRadii();
- return gfx::Vector2dF(result.x(), result.y());
- }
- float RRectF::GetSimpleRadius() const {
- DCHECK(GetType() <= Type::kOval);
- SkPoint result = skrrect_.getSimpleRadii();
- DCHECK_EQ(result.x(), result.y());
- return result.x();
- }
- RRectF::Type RRectF::GetType() const {
- SkPoint rad;
- switch (skrrect_.getType()) {
- case SkRRect::kEmpty_Type:
- return Type::kEmpty;
- case SkRRect::kRect_Type:
- return Type::kRect;
- case SkRRect::kSimple_Type:
- rad = skrrect_.getSimpleRadii();
- if (rad.x() == rad.y()) {
- return Type::kSingle;
- }
- return Type::kSimple;
- case SkRRect::kOval_Type:
- rad = skrrect_.getSimpleRadii();
- if (rad.x() == rad.y()) {
- return Type::kSingle;
- }
- return Type::kOval;
- case SkRRect::kNinePatch_Type:
- case SkRRect::kComplex_Type:
- default:
- return Type::kComplex;
- }
- }
- gfx::Vector2dF RRectF::GetCornerRadii(Corner corner) const {
- SkPoint result = skrrect_.radii(SkRRect::Corner(corner));
- return gfx::Vector2dF(result.x(), result.y());
- }
- void RRectF::GetAllRadii(SkVector radii[4]) const {
- // Unfortunately, the only way to get all radii is one at a time.
- radii[SkRRect::kUpperLeft_Corner] =
- skrrect_.radii(SkRRect::kUpperLeft_Corner);
- radii[SkRRect::kUpperRight_Corner] =
- skrrect_.radii(SkRRect::kUpperRight_Corner);
- radii[SkRRect::kLowerRight_Corner] =
- skrrect_.radii(SkRRect::kLowerRight_Corner);
- radii[SkRRect::kLowerLeft_Corner] =
- skrrect_.radii(SkRRect::kLowerLeft_Corner);
- }
- void RRectF::SetCornerRadii(Corner corner, float x_rad, float y_rad) {
- // Unfortunately, the only way to set this is to create a new SkRRect.
- SkVector radii[4];
- GetAllRadii(radii);
- radii[SkRRect::Corner(corner)] = SkPoint::Make(x_rad, y_rad);
- skrrect_.setRectRadii(skrrect_.rect(), radii);
- }
- void RRectF::Scale(float x_scale, float y_scale) {
- if (IsEmpty()) {
- // SkRRect doesn't support scaling of empty rects.
- return;
- }
- if (!x_scale || !y_scale) {
- // SkRRect doesn't support scaling TO an empty rect.
- skrrect_ = SkRRect::MakeEmpty();
- return;
- }
- SkMatrix scale = SkMatrix::Scale(x_scale, y_scale);
- SkRRect result;
- bool success = skrrect_.transform(scale, &result);
- DCHECK(success);
- skrrect_ = result;
- }
- void RRectF::Offset(float horizontal, float vertical) {
- skrrect_.offset(horizontal, vertical);
- }
- const RRectF& RRectF::operator+=(const gfx::Vector2dF& offset) {
- Offset(offset.x(), offset.y());
- return *this;
- }
- const RRectF& RRectF::operator-=(const gfx::Vector2dF& offset) {
- Offset(-offset.x(), -offset.y());
- return *this;
- }
- std::string RRectF::ToString() const {
- std::stringstream ss;
- ss << std::fixed << std::setprecision(3);
- ss << rect().origin().x() << "," << rect().origin().y() << " "
- << rect().size().width() << "x" << rect().size().height();
- Type type = this->GetType();
- if (type <= Type::kRect) {
- ss << ", rectangular";
- } else if (type <= Type::kSingle) {
- ss << ", radius " << GetSimpleRadius();
- } else if (type <= Type::kSimple) {
- gfx::Vector2dF radii = GetSimpleRadii();
- ss << ", x_rad " << radii.x() << ", y_rad " << radii.y();
- } else {
- ss << ",";
- const Corner corners[] = {Corner::kUpperLeft, Corner::kUpperRight,
- Corner::kLowerRight, Corner::kLowerLeft};
- for (const auto& c : corners) {
- auto this_corner = GetCornerRadii(c);
- ss << " [" << this_corner.x() << " " << this_corner.y() << "]";
- }
- }
- return ss.str();
- }
- namespace {
- inline bool AboveTol(float val1, float val2, float tolerance) {
- return (std::abs(val1 - val2) > tolerance);
- }
- } // namespace
- bool RRectF::ApproximatelyEqual(const RRectF& rect, float tolerance) const {
- if (AboveTol(skrrect_.rect().x(), rect.skrrect_.rect().x(), tolerance) ||
- AboveTol(skrrect_.rect().y(), rect.skrrect_.rect().y(), tolerance) ||
- AboveTol(skrrect_.width(), rect.skrrect_.width(), tolerance) ||
- AboveTol(skrrect_.height(), rect.skrrect_.height(), tolerance))
- return false;
- for (int i = 0; i < 4; i++) {
- SkVector r1 = skrrect_.radii(SkRRect::Corner(i));
- SkVector r2 = rect.skrrect_.radii(SkRRect::Corner(i));
- if (std::abs(r1.x() - r2.x()) > tolerance ||
- std::abs(r1.y() - r2.y()) > tolerance) {
- return false;
- }
- }
- return true;
- }
- } // namespace gfx
|