blob: 20d62a1ffe531bf46f5fadb806f3029e6444764a [file] [log] [blame]
// 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/rrect_f.h"
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace gfx {
TEST(RRectFTest, IsEmpty) {
EXPECT_TRUE(RRectF().IsEmpty());
EXPECT_TRUE(RRectF(0, 0, 0, 0, 0).IsEmpty());
EXPECT_TRUE(RRectF(0, 0, 10, 0, 0).IsEmpty());
EXPECT_TRUE(RRectF(0, 0, 0, 10, 0).IsEmpty());
EXPECT_TRUE(RRectF(0, 0, 0, 10, 10).IsEmpty());
EXPECT_FALSE(RRectF(0, 0, 10, 10, 0).IsEmpty());
}
TEST(RRectFTest, Equals) {
ASSERT_TRUE(RRectF(0, 0, 0, 0, 0, 0) == RRectF(0, 0, 0, 0, 0, 0));
ASSERT_TRUE(RRectF(1, 2, 3, 4, 5, 6) == RRectF(1, 2, 3, 4, 5, 6));
ASSERT_TRUE(RRectF(1, 2, 3, 4, 5, 5) == RRectF(1, 2, 3, 4, 5));
ASSERT_TRUE(RRectF(0, 0, 2, 3, 0, 0) == RRectF(0, 0, 2, 3, 0, 1));
ASSERT_TRUE(RRectF(0, 0, 2, 3, 0, 0) == RRectF(0, 0, 2, 3, 1, 0));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(1, 20, 30, 40, 7, 8));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(10, 2, 30, 40, 7, 8));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(10, 20, 3, 40, 7, 8));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(10, 20, 30, 4, 7, 8));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(10, 20, 30, 40, 5, 8));
ASSERT_TRUE(RRectF(10, 20, 30, 40, 7, 8) != RRectF(10, 20, 30, 40, 7, 6));
}
TEST(RRectFTest, PlusMinusOffset) {
const RRectF a(40, 50, 60, 70, 5);
gfx::Vector2d offset(23, 34);
RRectF correct(63, 84, 60, 70, 5);
RRectF b = a + offset;
ASSERT_EQ(b, correct);
b = a;
b.Offset(offset);
ASSERT_EQ(b, correct);
correct = RRectF(17, 16, 60, 70, 5);
b = a - offset;
ASSERT_EQ(b, correct);
b = a;
b.Offset(-offset);
ASSERT_EQ(b, correct);
}
TEST(RRectFTest, RRectTypes) {
RRectF a(40, 50, 0, 70, 0);
EXPECT_EQ(a.GetType(), RRectF::Type::kEmpty);
EXPECT_TRUE(a.IsEmpty());
a = RRectF(40, 50, 60, 70, 0);
EXPECT_EQ(a.GetType(), RRectF::Type::kRect);
a = RRectF(40, 50, 60, 70, 5);
EXPECT_EQ(a.GetType(), RRectF::Type::kSingle);
a = RRectF(40, 50, 60, 70, 5, 5);
EXPECT_EQ(a.GetType(), RRectF::Type::kSingle);
a = RRectF(40, 50, 60, 70, 6, 3);
EXPECT_EQ(a.GetType(), RRectF::Type::kSimple);
a = RRectF(40, 50, 60, 70, 30, 3);
EXPECT_EQ(a.GetType(), RRectF::Type::kSimple);
a = RRectF(40, 50, 60, 70, 30, 35);
EXPECT_EQ(a.GetType(), RRectF::Type::kOval);
a.SetCornerRadii(RRectF::Corner::kLowerRight, gfx::Vector2dF(7, 8));
EXPECT_EQ(a.GetType(), RRectF::Type::kComplex);
// When one radius is larger than half its dimension, both radii are scaled
// down proportionately.
a = RRectF(40, 50, 60, 70, 30, 70);
EXPECT_EQ(a.GetType(), RRectF::Type::kSimple);
EXPECT_EQ(a, RRectF(40, 50, 60, 70, 15, 35));
// If they stay equal to half the radius, it stays oval.
a = RRectF(40, 50, 60, 70, 120, 140);
EXPECT_EQ(a.GetType(), RRectF::Type::kOval);
}
void CheckRadii(RRectF val,
float ulx,
float uly,
float urx,
float ury,
float lrx,
float lry,
float llx,
float lly) {
EXPECT_EQ(val.GetCornerRadii(RRectF::Corner::kUpperLeft),
gfx::Vector2dF(ulx, uly));
EXPECT_EQ(val.GetCornerRadii(RRectF::Corner::kUpperRight),
gfx::Vector2dF(urx, ury));
EXPECT_EQ(val.GetCornerRadii(RRectF::Corner::kLowerRight),
gfx::Vector2dF(lrx, lry));
EXPECT_EQ(val.GetCornerRadii(RRectF::Corner::kLowerLeft),
gfx::Vector2dF(llx, lly));
}
TEST(RRectFTest, RRectRadii) {
RRectF a(40, 50, 60, 70, 0);
CheckRadii(a, 0, 0, 0, 0, 0, 0, 0, 0);
a.SetCornerRadii(RRectF::Corner::kUpperLeft, 1, 2);
CheckRadii(a, 1, 2, 0, 0, 0, 0, 0, 0);
a.SetCornerRadii(RRectF::Corner::kUpperRight, 3, 4);
CheckRadii(a, 1, 2, 3, 4, 0, 0, 0, 0);
a.SetCornerRadii(RRectF::Corner::kLowerRight, 5, 6);
CheckRadii(a, 1, 2, 3, 4, 5, 6, 0, 0);
a.SetCornerRadii(RRectF::Corner::kLowerLeft, 7, 8);
CheckRadii(a, 1, 2, 3, 4, 5, 6, 7, 8);
RRectF b(40, 50, 60, 70, 1, 2, 3, 4, 5, 6, 7, 8);
EXPECT_EQ(a, b);
}
TEST(RRectFTest, FromRectF) {
// Check that explicit conversion from float rect works.
RectF a(40, 50, 60, 70);
RRectF b(40, 50, 60, 70, 0);
RRectF c = RRectF(a);
EXPECT_EQ(b, c);
}
TEST(RRectFTest, FromSkRRect) {
// Check that explicit conversion from SkRRect works.
SkRRect a = SkRRect::MakeRectXY(SkRect::MakeXYWH(40, 50, 60, 70), 15, 25);
RRectF b(40, 50, 60, 70, 15, 25);
RRectF c = RRectF(a);
EXPECT_EQ(b, c);
// Try with single radius constructor.
a = SkRRect::MakeRectXY(SkRect::MakeXYWH(40, 50, 60, 70), 15, 15);
b = RRectF(40, 50, 60, 70, 15);
c = RRectF(a);
EXPECT_EQ(b, c);
}
TEST(RRectFTest, ToString) {
RRectF a(40, 50, 60, 70, 0);
EXPECT_EQ(a.ToString(), "40.000,50.000 60.000x70.000, rectangular");
a = RRectF(40, 50, 60, 70, 15);
EXPECT_EQ(a.ToString(), "40.000,50.000 60.000x70.000, radius 15.000");
a = RRectF(40, 50, 60, 70, 15, 25);
EXPECT_EQ(a.ToString(),
"40.000,50.000 60.000x70.000, x_rad 15.000, y_rad 25.000");
a.SetCornerRadii(RRectF::Corner::kLowerRight, gfx::Vector2dF(7, 8));
EXPECT_EQ(a.ToString(),
"40.000,50.000 60.000x70.000, [15.000 25.000] "
"[15.000 25.000] [7.000 8.000] [15.000 25.000]");
}
TEST(RRectFTest, Sizes) {
RRectF a(40, 50, 60, 70, 5, 6);
EXPECT_EQ(a.rect().x(), 40);
EXPECT_EQ(a.rect().y(), 50);
EXPECT_EQ(a.rect().width(), 60);
EXPECT_EQ(a.rect().height(), 70);
EXPECT_EQ(a.GetSimpleRadii().x(), 5);
EXPECT_EQ(a.GetSimpleRadii().y(), 6);
a = RRectF(40, 50, 60, 70, 5, 5);
EXPECT_EQ(a.GetSimpleRadius(), 5);
a.Clear();
EXPECT_TRUE(a.IsEmpty());
// Make sure ovals can still get simple radii
a = RRectF(40, 50, 60, 70, 30, 35);
EXPECT_EQ(a.GetType(), RRectF::Type::kOval);
EXPECT_EQ(a.GetSimpleRadii().x(), 30);
EXPECT_EQ(a.GetSimpleRadii().y(), 35);
}
TEST(RRectFTest, Contains) {
RRectF a(40, 50, 60, 70, 5, 6);
RectF b(50, 60, 5, 6);
EXPECT_TRUE(a.Contains(b));
b = RectF(40, 50, 5, 6); // Right on the border
EXPECT_FALSE(a.Contains(b));
b = RectF(95, 114, 5, 6); // Right on the border
EXPECT_FALSE(a.Contains(b));
b = RectF(40, 50, 60, 70);
EXPECT_FALSE(a.Contains(b));
}
TEST(RRectFTest, Scale) {
// Note that SKRRect (the backing for RRectF) does not support scaling by NaN,
// scaling out of numerical bounds, or scaling to zero. So this test doesn't
// exercise those.
static const struct Test {
float x1; // source
float y1;
float w1;
float h1;
float r1;
float scale;
float x2; // target
float y2;
float w2;
float h2;
float r2;
} tests[] = {
{3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 1.5f, 4.5f, 6.0f, 7.5f, 9.0f, 1.5f},
{3.0f, 4.0f, 5.0f, 6.0f, 0.0f, 1.5f, 4.5f, 6.0f, 7.5f, 9.0f, 0.0f},
};
for (size_t i = 0; i < base::size(tests); ++i) {
RRectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1, tests[i].r1);
RRectF r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2, tests[i].r2);
r1.Scale(tests[i].scale);
EXPECT_TRUE((r1.GetType() == RRectF::Type::kRect) ||
(r1.GetType() == RRectF::Type::kSingle));
EXPECT_EQ(r1.rect().x(), r2.rect().x());
EXPECT_EQ(r1.rect().y(), r2.rect().y());
EXPECT_EQ(r1.rect().width(), r2.rect().width());
EXPECT_EQ(r1.rect().height(), r2.rect().height());
EXPECT_EQ(r1.GetSimpleRadius(), r2.GetSimpleRadius());
}
}
TEST(RRectFTest, InsetOutset) {
RRectF a(40, 50, 60, 70, 5);
RRectF b = a;
b.Inset(3);
ASSERT_EQ(b, RRectF(43, 53, 54, 64, 2));
b = a;
b.Outset(3);
ASSERT_EQ(b, RRectF(37, 47, 66, 76, 8));
}
} // namespace gfx