blob: 9b10bd7dee72e12d59f6a5300762d8ea8ad23588 [file] [log] [blame]
/*
* 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 "platform/geometry/FloatRoundedRect.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/text/WTFString.h"
namespace blink {
#define TEST_INTERCEPTS(roundedRect, yCoordinate, expectedMinXIntercept, \
expectedMaxXIntercept) \
{ \
float minXIntercept; \
float maxXIntercept; \
EXPECT_TRUE(roundedRect.xInterceptsAtY(yCoordinate, minXIntercept, \
maxXIntercept)); \
EXPECT_FLOAT_EQ(expectedMinXIntercept, minXIntercept); \
EXPECT_FLOAT_EQ(expectedMaxXIntercept, maxXIntercept); \
}
TEST(FloatRoundedRectTest, zeroRadii) {
FloatRoundedRect r = FloatRoundedRect(1, 2, 3, 4);
EXPECT_EQ(FloatRect(1, 2, 3, 4), r.rect());
EXPECT_EQ(FloatSize(), r.getRadii().topLeft());
EXPECT_EQ(FloatSize(), r.getRadii().topRight());
EXPECT_EQ(FloatSize(), r.getRadii().bottomLeft());
EXPECT_EQ(FloatSize(), r.getRadii().bottomRight());
EXPECT_TRUE(r.getRadii().isZero());
EXPECT_FALSE(r.isRounded());
EXPECT_FALSE(r.isEmpty());
EXPECT_EQ(FloatRect(1, 2, 0, 0), r.topLeftCorner());
EXPECT_EQ(FloatRect(4, 2, 0, 0), r.topRightCorner());
EXPECT_EQ(FloatRect(4, 6, 0, 0), r.bottomRightCorner());
EXPECT_EQ(FloatRect(1, 6, 0, 0), r.bottomLeftCorner());
TEST_INTERCEPTS(r, 2, r.rect().x(), r.rect().maxX());
TEST_INTERCEPTS(r, 4, r.rect().x(), r.rect().maxX());
TEST_INTERCEPTS(r, 6, r.rect().x(), r.rect().maxX());
float minXIntercept;
float maxXIntercept;
EXPECT_FALSE(r.xInterceptsAtY(1, minXIntercept, maxXIntercept));
EXPECT_FALSE(r.xInterceptsAtY(7, minXIntercept, maxXIntercept));
// The FloatRoundedRect::expandRadii() function doesn't change radii
// FloatSizes that are <= zero. Same as RoundedRect::expandRadii().
r.expandRadii(20);
r.shrinkRadii(10);
EXPECT_TRUE(r.getRadii().isZero());
}
TEST(FloatRoundedRectTest, circle) {
FloatSize cornerRadii(50, 50);
FloatRoundedRect r(FloatRect(0, 0, 100, 100), cornerRadii, cornerRadii,
cornerRadii, cornerRadii);
EXPECT_EQ(FloatRect(0, 0, 100, 100), r.rect());
EXPECT_EQ(cornerRadii, r.getRadii().topLeft());
EXPECT_EQ(cornerRadii, r.getRadii().topRight());
EXPECT_EQ(cornerRadii, r.getRadii().bottomLeft());
EXPECT_EQ(cornerRadii, r.getRadii().bottomRight());
EXPECT_FALSE(r.getRadii().isZero());
EXPECT_TRUE(r.isRounded());
EXPECT_FALSE(r.isEmpty());
EXPECT_EQ(FloatRect(0, 0, 50, 50), r.topLeftCorner());
EXPECT_EQ(FloatRect(50, 0, 50, 50), r.topRightCorner());
EXPECT_EQ(FloatRect(0, 50, 50, 50), r.bottomLeftCorner());
EXPECT_EQ(FloatRect(50, 50, 50, 50), r.bottomRightCorner());
TEST_INTERCEPTS(r, 0, 50, 50);
TEST_INTERCEPTS(r, 25, 6.69873, 93.3013);
TEST_INTERCEPTS(r, 50, 0, 100);
TEST_INTERCEPTS(r, 75, 6.69873, 93.3013);
TEST_INTERCEPTS(r, 100, 50, 50);
float minXIntercept;
float maxXIntercept;
EXPECT_FALSE(r.xInterceptsAtY(-1, minXIntercept, maxXIntercept));
EXPECT_FALSE(r.xInterceptsAtY(101, minXIntercept, maxXIntercept));
}
/*
* FloatRoundedRect geometry for this test. Corner radii are in parens, x and y
* intercepts for the elliptical corners are noted. The rectangle itself is at
* 0,0 with width and height 100.
*
* (10, 15) x=10 x=90 (10, 20)
* (--+---------+--)
* y=15 +--| |-+ y=20
* | |
* | |
* y=85 + -| |- + y=70
* (--+---------+--)
* (25, 15) x=25 x=80 (20, 30)
*/
TEST(FloatRoundedRectTest, ellipticalCorners) {
FloatSize cornerSize(10, 20);
FloatRoundedRect::Radii cornerRadii;
cornerRadii.setTopLeft(FloatSize(10, 15));
cornerRadii.setTopRight(FloatSize(10, 20));
cornerRadii.setBottomLeft(FloatSize(25, 15));
cornerRadii.setBottomRight(FloatSize(20, 30));
FloatRoundedRect r(FloatRect(0, 0, 100, 100), cornerRadii);
EXPECT_EQ(r.getRadii(),
FloatRoundedRect::Radii(FloatSize(10, 15), FloatSize(10, 20),
FloatSize(25, 15), FloatSize(20, 30)));
EXPECT_EQ(r, FloatRoundedRect(FloatRect(0, 0, 100, 100), cornerRadii));
EXPECT_EQ(FloatRect(0, 0, 10, 15), r.topLeftCorner());
EXPECT_EQ(FloatRect(90, 0, 10, 20), r.topRightCorner());
EXPECT_EQ(FloatRect(0, 85, 25, 15), r.bottomLeftCorner());
EXPECT_EQ(FloatRect(80, 70, 20, 30), r.bottomRightCorner());
TEST_INTERCEPTS(r, 5, 2.5464401, 96.61438);
TEST_INTERCEPTS(r, 15, 0, 99.682457);
TEST_INTERCEPTS(r, 20, 0, 100);
TEST_INTERCEPTS(r, 50, 0, 100);
TEST_INTERCEPTS(r, 70, 0, 100);
TEST_INTERCEPTS(r, 85, 0, 97.320511);
TEST_INTERCEPTS(r, 95, 6.3661003, 91.05542);
float minXIntercept;
float maxXIntercept;
EXPECT_FALSE(r.xInterceptsAtY(-1, minXIntercept, maxXIntercept));
EXPECT_FALSE(r.xInterceptsAtY(101, minXIntercept, maxXIntercept));
}
TEST(FloatRoundedRectTest, radiusCenterRect) {
FloatSize cornerRect(10, 10);
FloatRoundedRect r0(
FloatRect(0, 0, 100, 50),
FloatRoundedRect::Radii(cornerRect, cornerRect, cornerRect, cornerRect));
EXPECT_EQ(FloatRect(10, 10, 80, 30), r0.radiusCenterRect());
// "Degenerate" cases all return an empty rectangle.
FloatRect collapsedRect(0, 0, 100, 50);
collapsedRect.expand(FloatRectOutsets(-200, -200, -200, -200));
FloatRoundedRect r1(collapsedRect);
EXPECT_TRUE(r1.radiusCenterRect().isEmpty());
FloatRoundedRect::Radii radiiWithTooLargeCorner(
FloatSize(55, 55), FloatSize(), FloatSize(), FloatSize());
FloatRoundedRect r2(FloatRect(0, 0, 100, 50), radiiWithTooLargeCorner);
EXPECT_TRUE(r2.radiusCenterRect().isEmpty());
}
TEST(FloatRoundedRectTest, ToString) {
FloatSize cornerRect(1, 2);
FloatRoundedRect roundedRect(
FloatRect(3, 5, 7, 11),
FloatRoundedRect::Radii(cornerRect, cornerRect, cornerRect, cornerRect));
EXPECT_EQ("3,5 7x11 radii:(tl:1x2; tr:1x2; bl:1x2; br:1x2)",
roundedRect.toString());
}
} // namespace blink