Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "Test.h"
      9 #include "SkRRect.h"
     10 
     11 static const SkScalar kWidth = 100.0f;
     12 static const SkScalar kHeight = 100.0f;
     13 
     14 static void test_inset(skiatest::Reporter* reporter) {
     15     SkRRect rr, rr2;
     16     SkRect r = { 0, 0, 100, 100 };
     17 
     18     rr.setRect(r);
     19     rr.inset(-20, -20, &rr2);
     20     REPORTER_ASSERT(reporter, rr2.isRect());
     21 
     22     rr.inset(20, 20, &rr2);
     23     REPORTER_ASSERT(reporter, rr2.isRect());
     24 
     25     rr.inset(r.width()/2, r.height()/2, &rr2);
     26     REPORTER_ASSERT(reporter, rr2.isEmpty());
     27 
     28     rr.setRectXY(r, 20, 20);
     29     rr.inset(19, 19, &rr2);
     30     REPORTER_ASSERT(reporter, rr2.isSimple());
     31     rr.inset(20, 20, &rr2);
     32     REPORTER_ASSERT(reporter, rr2.isRect());
     33 }
     34 
     35 // Test out the basic API entry points
     36 static void test_round_rect_basic(skiatest::Reporter* reporter) {
     37     // Test out initialization methods
     38     SkPoint zeroPt = { 0, 0 };
     39     SkRRect empty;
     40 
     41     empty.setEmpty();
     42 
     43     REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
     44     REPORTER_ASSERT(reporter, empty.rect().isEmpty());
     45 
     46     for (int i = 0; i < 4; ++i) {
     47         REPORTER_ASSERT(reporter, zeroPt == empty.radii((SkRRect::Corner) i));
     48     }
     49 
     50     //----
     51     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
     52 
     53     SkRRect rr1;
     54     rr1.setRect(rect);
     55 
     56     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
     57     REPORTER_ASSERT(reporter, rr1.rect() == rect);
     58 
     59     for (int i = 0; i < 4; ++i) {
     60         REPORTER_ASSERT(reporter, zeroPt == rr1.radii((SkRRect::Corner) i));
     61     }
     62 
     63     //----
     64     SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
     65     SkRRect rr2;
     66     rr2.setOval(rect);
     67 
     68     REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr2.type());
     69     REPORTER_ASSERT(reporter, rr2.rect() == rect);
     70 
     71     for (int i = 0; i < 4; ++i) {
     72         REPORTER_ASSERT(reporter,
     73                         rr2.radii((SkRRect::Corner) i).equalsWithinTolerance(halfPoint));
     74     }
     75 
     76     //----
     77     SkPoint p = { 5, 5 };
     78     SkRRect rr3;
     79     rr3.setRectXY(rect, p.fX, p.fY);
     80 
     81     REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr3.type());
     82     REPORTER_ASSERT(reporter, rr3.rect() == rect);
     83 
     84     for (int i = 0; i < 4; ++i) {
     85         REPORTER_ASSERT(reporter, p == rr3.radii((SkRRect::Corner) i));
     86     }
     87 
     88     //----
     89     SkPoint radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
     90 
     91     SkRRect rr4;
     92     rr4.setRectRadii(rect, radii);
     93 
     94     REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr4.type());
     95     REPORTER_ASSERT(reporter, rr4.rect() == rect);
     96 
     97     for (int i = 0; i < 4; ++i) {
     98         REPORTER_ASSERT(reporter, radii[i] == rr4.radii((SkRRect::Corner) i));
     99     }
    100 
    101     //----
    102     SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
    103 
    104     SkRRect rr5;
    105     rr5.setRectRadii(rect, radii2);
    106 
    107     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr5.type());
    108     REPORTER_ASSERT(reporter, rr5.rect() == rect);
    109 
    110     for (int i = 0; i < 4; ++i) {
    111         REPORTER_ASSERT(reporter, radii2[i] == rr5.radii((SkRRect::Corner) i));
    112     }
    113 
    114     // Test out == & !=
    115     REPORTER_ASSERT(reporter, empty != rr3);
    116     REPORTER_ASSERT(reporter, rr3 == rr4);
    117     REPORTER_ASSERT(reporter, rr4 != rr5);
    118 }
    119 
    120 // Test out the cases when the RR degenerates to a rect
    121 static void test_round_rect_rects(skiatest::Reporter* reporter) {
    122     SkRect r;
    123     static const SkPoint pts[] = {
    124         // Upper Left
    125         { -SK_Scalar1, -SK_Scalar1 },               // out
    126         { SK_Scalar1, SK_Scalar1 },                 // in
    127         // Upper Right
    128         { SkIntToScalar(101), -SK_Scalar1},         // out
    129         { SkIntToScalar(99), SK_Scalar1 },          // in
    130         // Lower Right
    131         { SkIntToScalar(101), SkIntToScalar(101) }, // out
    132         { SkIntToScalar(99), SkIntToScalar(99) },   // in
    133         // Lower Left
    134         { -SK_Scalar1, SkIntToScalar(101) },        // out
    135         { SK_Scalar1, SkIntToScalar(99) },          // in
    136         // Middle
    137         { SkIntToScalar(50), SkIntToScalar(50) }    // in
    138     };
    139     static const bool isIn[] = { false, true, false, true, false, true, false, true, true };
    140 
    141     SkASSERT(SK_ARRAY_COUNT(pts) == SK_ARRAY_COUNT(isIn));
    142 
    143     //----
    144     SkRRect empty;
    145 
    146     empty.setEmpty();
    147 
    148     REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
    149     r = empty.rect();
    150     REPORTER_ASSERT(reporter, 0 == r.fLeft && 0 == r.fTop && 0 == r.fRight && 0 == r.fBottom);
    151 
    152     //----
    153     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    154     SkRRect rr1;
    155     rr1.setRectXY(rect, 0, 0);
    156 
    157     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
    158     r = rr1.rect();
    159     REPORTER_ASSERT(reporter, rect == r);
    160     for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
    161         REPORTER_ASSERT(reporter, isIn[i] == rr1.contains(pts[i].fX, pts[i].fY));
    162     }
    163 
    164     //----
    165     SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
    166 
    167     SkRRect rr2;
    168     rr2.setRectRadii(rect, radii);
    169 
    170     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
    171     r = rr2.rect();
    172     REPORTER_ASSERT(reporter, rect == r);
    173     for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
    174         REPORTER_ASSERT(reporter, isIn[i] == rr2.contains(pts[i].fX, pts[i].fY));
    175     }
    176 
    177     //----
    178     SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
    179 
    180     SkRRect rr3;
    181     rr3.setRectRadii(rect, radii2);
    182     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr3.type());
    183 }
    184 
    185 // Test out the cases when the RR degenerates to an oval
    186 static void test_round_rect_ovals(skiatest::Reporter* reporter) {
    187     static const SkScalar kEps = 0.1f;
    188     static const SkScalar kWidthTol = SkScalarHalf(kWidth) * (SK_Scalar1 - SK_ScalarRoot2Over2);
    189     static const SkScalar kHeightTol = SkScalarHalf(kHeight) * (SK_Scalar1 - SK_ScalarRoot2Over2);
    190     static const SkPoint pts[] = {
    191         // Upper Left
    192         { kWidthTol - kEps, kHeightTol - kEps },       // out
    193         { kWidthTol + kEps, kHeightTol + kEps },       // in
    194         // Upper Right
    195         { kWidth + kEps - kWidthTol, kHeightTol - kEps },     // out
    196         { kWidth - kEps - kWidthTol, kHeightTol + kEps },      // in
    197         // Lower Right
    198         { kWidth + kEps - kWidthTol, kHeight + kEps - kHeightTol },   // out
    199         { kWidth - kEps - kWidthTol, kHeight - kEps - kHeightTol },   // in
    200         // Lower Left
    201         { kWidthTol - kEps, kHeight + kEps - kHeightTol },     //out
    202         { kWidthTol + kEps, kHeight - kEps - kHeightTol },     // in
    203         // Middle
    204         { SkIntToScalar(50), SkIntToScalar(50) } // in
    205     };
    206     static const bool isIn[] = { false, true, false, true, false, true, false, true, true };
    207 
    208     SkASSERT(SK_ARRAY_COUNT(pts) == SK_ARRAY_COUNT(isIn));
    209 
    210     //----
    211     SkRect oval;
    212     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    213     SkRRect rr1;
    214     rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
    215 
    216     REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr1.type());
    217     oval = rr1.rect();
    218     REPORTER_ASSERT(reporter, oval == rect);
    219     for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
    220         REPORTER_ASSERT(reporter, isIn[i] == rr1.contains(pts[i].fX, pts[i].fY));
    221     }
    222 }
    223 
    224 // Test out the non-degenerate RR cases
    225 static void test_round_rect_general(skiatest::Reporter* reporter) {
    226     static const SkScalar kEps = 0.1f;
    227     static const SkScalar kDist20 = 20 * (SK_Scalar1 - SK_ScalarRoot2Over2);
    228     static const SkPoint pts[] = {
    229         // Upper Left
    230         { kDist20 - kEps, kDist20 - kEps },       // out
    231         { kDist20 + kEps, kDist20 + kEps },       // in
    232         // Upper Right
    233         { kWidth + kEps - kDist20, kDist20 - kEps },     // out
    234         { kWidth - kEps - kDist20, kDist20 + kEps },      // in
    235         // Lower Right
    236         { kWidth + kEps - kDist20, kHeight + kEps - kDist20 },   // out
    237         { kWidth - kEps - kDist20, kHeight - kEps - kDist20 },   // in
    238         // Lower Left
    239         { kDist20 - kEps, kHeight + kEps - kDist20 },     //out
    240         { kDist20 + kEps, kHeight - kEps - kDist20 },     // in
    241         // Middle
    242         { SkIntToScalar(50), SkIntToScalar(50) } // in
    243     };
    244     static const bool isIn[] = { false, true, false, true, false, true, false, true, true };
    245 
    246     SkASSERT(SK_ARRAY_COUNT(pts) == SK_ARRAY_COUNT(isIn));
    247 
    248     //----
    249     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    250     SkRRect rr1;
    251     rr1.setRectXY(rect, 20, 20);
    252 
    253     REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr1.type());
    254     for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
    255         REPORTER_ASSERT(reporter, isIn[i] == rr1.contains(pts[i].fX, pts[i].fY));
    256     }
    257 
    258     //----
    259     static const SkScalar kDist50 = 50*(SK_Scalar1 - SK_ScalarRoot2Over2);
    260     static const SkPoint pts2[] = {
    261         // Upper Left
    262         { -SK_Scalar1, -SK_Scalar1 },           // out
    263         { SK_Scalar1, SK_Scalar1 },             // in
    264         // Upper Right
    265         { kWidth + kEps - kDist20, kDist20 - kEps },     // out
    266         { kWidth - kEps - kDist20, kDist20 + kEps },     // in
    267         // Lower Right
    268         { kWidth + kEps - kDist50, kHeight + kEps - kDist50 },   // out
    269         { kWidth - kEps - kDist50, kHeight - kEps - kDist50 },   // in
    270         // Lower Left
    271         { kDist20 - kEps, kHeight + kEps - kDist50 },     // out
    272         { kDist20 + kEps, kHeight - kEps - kDist50 },     // in
    273         // Middle
    274         { SkIntToScalar(50), SkIntToScalar(50) }  // in
    275     };
    276 
    277     SkASSERT(SK_ARRAY_COUNT(pts2) == SK_ARRAY_COUNT(isIn));
    278 
    279     SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
    280 
    281     SkRRect rr2;
    282     rr2.setRectRadii(rect, radii);
    283 
    284     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr2.type());
    285     for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) {
    286         REPORTER_ASSERT(reporter, isIn[i] == rr2.contains(pts2[i].fX, pts2[i].fY));
    287     }
    288 }
    289 
    290 // Test out questionable-parameter handling
    291 static void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
    292 
    293     // When the radii exceed the base rect they are proportionally scaled down
    294     // to fit
    295     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    296     SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
    297 
    298     SkRRect rr1;
    299     rr1.setRectRadii(rect, radii);
    300 
    301     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr1.type());
    302 
    303     const SkPoint& p = rr1.radii(SkRRect::kUpperLeft_Corner);
    304 
    305     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fX, 33.33333f));
    306     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fY, 66.66666f));
    307 
    308     // Negative radii should be capped at zero
    309     SkRRect rr2;
    310     rr2.setRectXY(rect, -10, -20);
    311 
    312     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
    313 
    314     const SkPoint& p2 = rr2.radii(SkRRect::kUpperLeft_Corner);
    315 
    316     REPORTER_ASSERT(reporter, 0.0f == p2.fX);
    317     REPORTER_ASSERT(reporter, 0.0f == p2.fY);
    318 }
    319 
    320 static void TestRoundRect(skiatest::Reporter* reporter) {
    321     test_round_rect_basic(reporter);
    322     test_round_rect_rects(reporter);
    323     test_round_rect_ovals(reporter);
    324     test_round_rect_general(reporter);
    325     test_round_rect_iffy_parameters(reporter);
    326     test_inset(reporter);
    327 }
    328 
    329 #include "TestClassDef.h"
    330 DEFINE_TESTCLASS("RoundRect", TestRoundRectClass, TestRoundRect)
    331