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 "SkMatrix.h"
      9 #include "SkRRect.h"
     10 #include "Test.h"
     11 
     12 static const SkScalar kWidth = 100.0f;
     13 static const SkScalar kHeight = 100.0f;
     14 
     15 static void test_inset(skiatest::Reporter* reporter) {
     16     SkRRect rr, rr2;
     17     SkRect r = { 0, 0, 100, 100 };
     18 
     19     rr.setRect(r);
     20     rr.inset(-20, -20, &rr2);
     21     REPORTER_ASSERT(reporter, rr2.isRect());
     22 
     23     rr.inset(20, 20, &rr2);
     24     REPORTER_ASSERT(reporter, rr2.isRect());
     25 
     26     rr.inset(r.width()/2, r.height()/2, &rr2);
     27     REPORTER_ASSERT(reporter, rr2.isEmpty());
     28 
     29     rr.setRectXY(r, 20, 20);
     30     rr.inset(19, 19, &rr2);
     31     REPORTER_ASSERT(reporter, rr2.isSimple());
     32     rr.inset(20, 20, &rr2);
     33     REPORTER_ASSERT(reporter, rr2.isRect());
     34 }
     35 
     36 // Test out the basic API entry points
     37 static void test_round_rect_basic(skiatest::Reporter* reporter) {
     38     // Test out initialization methods
     39     SkPoint zeroPt = { 0, 0 };
     40     SkRRect empty;
     41 
     42     empty.setEmpty();
     43 
     44     REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
     45     REPORTER_ASSERT(reporter, empty.rect().isEmpty());
     46 
     47     for (int i = 0; i < 4; ++i) {
     48         REPORTER_ASSERT(reporter, zeroPt == empty.radii((SkRRect::Corner) i));
     49     }
     50 
     51     //----
     52     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
     53 
     54     SkRRect rr1;
     55     rr1.setRect(rect);
     56 
     57     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
     58     REPORTER_ASSERT(reporter, rr1.rect() == rect);
     59 
     60     for (int i = 0; i < 4; ++i) {
     61         REPORTER_ASSERT(reporter, zeroPt == rr1.radii((SkRRect::Corner) i));
     62     }
     63     SkRRect rr1_2; // construct the same RR using the most general set function
     64     SkVector rr1_2_radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
     65     rr1_2.setRectRadii(rect, rr1_2_radii);
     66     REPORTER_ASSERT(reporter, rr1_2 == rr1 && rr1_2.getType() == rr1.getType());
     67     SkRRect rr1_3;  // construct the same RR using the nine patch set function
     68     rr1_3.setNinePatch(rect, 0, 0, 0, 0);
     69     REPORTER_ASSERT(reporter, rr1_3 == rr1 && rr1_3.getType() == rr1.getType());
     70 
     71     //----
     72     SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
     73     SkRRect rr2;
     74     rr2.setOval(rect);
     75 
     76     REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr2.type());
     77     REPORTER_ASSERT(reporter, rr2.rect() == rect);
     78 
     79     for (int i = 0; i < 4; ++i) {
     80         REPORTER_ASSERT(reporter,
     81                         rr2.radii((SkRRect::Corner) i).equalsWithinTolerance(halfPoint));
     82     }
     83     SkRRect rr2_2;  // construct the same RR using the most general set function
     84     SkVector rr2_2_radii[4] = { { halfPoint.fX, halfPoint.fY }, { halfPoint.fX, halfPoint.fY },
     85                                 { halfPoint.fX, halfPoint.fY }, { halfPoint.fX, halfPoint.fY } };
     86     rr2_2.setRectRadii(rect, rr2_2_radii);
     87     REPORTER_ASSERT(reporter, rr2_2 == rr2 && rr2_2.getType() == rr2.getType());
     88     SkRRect rr2_3;  // construct the same RR using the nine patch set function
     89     rr2_3.setNinePatch(rect, halfPoint.fX, halfPoint.fY, halfPoint.fX, halfPoint.fY);
     90     REPORTER_ASSERT(reporter, rr2_3 == rr2 && rr2_3.getType() == rr2.getType());
     91 
     92     //----
     93     SkPoint p = { 5, 5 };
     94     SkRRect rr3;
     95     rr3.setRectXY(rect, p.fX, p.fY);
     96 
     97     REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr3.type());
     98     REPORTER_ASSERT(reporter, rr3.rect() == rect);
     99 
    100     for (int i = 0; i < 4; ++i) {
    101         REPORTER_ASSERT(reporter, p == rr3.radii((SkRRect::Corner) i));
    102     }
    103     SkRRect rr3_2; // construct the same RR using the most general set function
    104     SkVector rr3_2_radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
    105     rr3_2.setRectRadii(rect, rr3_2_radii);
    106     REPORTER_ASSERT(reporter, rr3_2 == rr3 && rr3_2.getType() == rr3.getType());
    107     SkRRect rr3_3;  // construct the same RR using the nine patch set function
    108     rr3_3.setNinePatch(rect, 5, 5, 5, 5);
    109     REPORTER_ASSERT(reporter, rr3_3 == rr3 && rr3_3.getType() == rr3.getType());
    110 
    111     //----
    112     SkRect ninePatchRadii = { 10, 9, 8, 7 };
    113 
    114     SkRRect rr4;
    115     rr4.setNinePatch(rect, ninePatchRadii.fLeft, ninePatchRadii.fTop, ninePatchRadii.fRight,
    116                      ninePatchRadii.fBottom);
    117 
    118     REPORTER_ASSERT(reporter, SkRRect::kNinePatch_Type == rr4.type());
    119     REPORTER_ASSERT(reporter, rr4.rect() == rect);
    120 
    121     SkPoint rquad[4];
    122     ninePatchRadii.toQuad(rquad);
    123     for (int i = 0; i < 4; ++i) {
    124         REPORTER_ASSERT(reporter, rquad[i] == rr4.radii((SkRRect::Corner) i));
    125     }
    126     SkRRect rr4_2; // construct the same RR using the most general set function
    127     SkVector rr4_2_radii[4] = { { 10, 9 }, { 8, 9 }, {8, 7 }, { 10, 7 } };
    128     rr4_2.setRectRadii(rect, rr4_2_radii);
    129     REPORTER_ASSERT(reporter, rr4_2 == rr4 && rr4_2.getType() == rr4.getType());
    130 
    131     //----
    132     SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
    133 
    134     SkRRect rr5;
    135     rr5.setRectRadii(rect, radii2);
    136 
    137     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr5.type());
    138     REPORTER_ASSERT(reporter, rr5.rect() == rect);
    139 
    140     for (int i = 0; i < 4; ++i) {
    141         REPORTER_ASSERT(reporter, radii2[i] == rr5.radii((SkRRect::Corner) i));
    142     }
    143 
    144     // Test out == & !=
    145     REPORTER_ASSERT(reporter, empty != rr3);
    146     REPORTER_ASSERT(reporter, rr3 != rr4);
    147     REPORTER_ASSERT(reporter, rr4 != rr5);
    148 }
    149 
    150 // Test out the cases when the RR degenerates to a rect
    151 static void test_round_rect_rects(skiatest::Reporter* reporter) {
    152     SkRect r;
    153 
    154     //----
    155     SkRRect empty;
    156 
    157     empty.setEmpty();
    158 
    159     REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == empty.type());
    160     r = empty.rect();
    161     REPORTER_ASSERT(reporter, 0 == r.fLeft && 0 == r.fTop && 0 == r.fRight && 0 == r.fBottom);
    162 
    163     //----
    164     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    165     SkRRect rr1;
    166     rr1.setRectXY(rect, 0, 0);
    167 
    168     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr1.type());
    169     r = rr1.rect();
    170     REPORTER_ASSERT(reporter, rect == r);
    171 
    172     //----
    173     SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
    174 
    175     SkRRect rr2;
    176     rr2.setRectRadii(rect, radii);
    177 
    178     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
    179     r = rr2.rect();
    180     REPORTER_ASSERT(reporter, rect == r);
    181 
    182     //----
    183     SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
    184 
    185     SkRRect rr3;
    186     rr3.setRectRadii(rect, radii2);
    187     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr3.type());
    188 }
    189 
    190 // Test out the cases when the RR degenerates to an oval
    191 static void test_round_rect_ovals(skiatest::Reporter* reporter) {
    192     //----
    193     SkRect oval;
    194     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    195     SkRRect rr1;
    196     rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
    197 
    198     REPORTER_ASSERT(reporter, SkRRect::kOval_Type == rr1.type());
    199     oval = rr1.rect();
    200     REPORTER_ASSERT(reporter, oval == rect);
    201 }
    202 
    203 // Test out the non-degenerate RR cases
    204 static void test_round_rect_general(skiatest::Reporter* reporter) {
    205     //----
    206     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    207     SkRRect rr1;
    208     rr1.setRectXY(rect, 20, 20);
    209 
    210     REPORTER_ASSERT(reporter, SkRRect::kSimple_Type == rr1.type());
    211 
    212     //----
    213     SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
    214 
    215     SkRRect rr2;
    216     rr2.setRectRadii(rect, radii);
    217 
    218     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr2.type());
    219 }
    220 
    221 // Test out questionable-parameter handling
    222 static void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
    223 
    224     // When the radii exceed the base rect they are proportionally scaled down
    225     // to fit
    226     SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
    227     SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
    228 
    229     SkRRect rr1;
    230     rr1.setRectRadii(rect, radii);
    231 
    232     REPORTER_ASSERT(reporter, SkRRect::kComplex_Type == rr1.type());
    233 
    234     const SkPoint& p = rr1.radii(SkRRect::kUpperLeft_Corner);
    235 
    236     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fX, 33.33333f));
    237     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(p.fY, 66.66666f));
    238 
    239     // Negative radii should be capped at zero
    240     SkRRect rr2;
    241     rr2.setRectXY(rect, -10, -20);
    242 
    243     REPORTER_ASSERT(reporter, SkRRect::kRect_Type == rr2.type());
    244 
    245     const SkPoint& p2 = rr2.radii(SkRRect::kUpperLeft_Corner);
    246 
    247     REPORTER_ASSERT(reporter, 0.0f == p2.fX);
    248     REPORTER_ASSERT(reporter, 0.0f == p2.fY);
    249 }
    250 
    251 // Move a small box from the start position by (stepX, stepY) 'numSteps' times
    252 // testing for containment in 'rr' at each step.
    253 static void test_direction(skiatest::Reporter* reporter, const SkRRect &rr,
    254                            SkScalar initX, int stepX, SkScalar initY, int stepY,
    255                            int numSteps, const bool* contains) {
    256     SkScalar x = initX, y = initY;
    257     for (int i = 0; i < numSteps; ++i) {
    258         SkRect test = SkRect::MakeXYWH(x, y,
    259                                        stepX ? SkIntToScalar(stepX) : SK_Scalar1,
    260                                        stepY ? SkIntToScalar(stepY) : SK_Scalar1);
    261         test.sort();
    262 
    263         REPORTER_ASSERT(reporter, contains[i] == rr.contains(test));
    264 
    265         x += stepX;
    266         y += stepY;
    267     }
    268 }
    269 
    270 // Exercise the RR's contains rect method
    271 static void test_round_rect_contains_rect(skiatest::Reporter* reporter) {
    272 
    273     static const int kNumRRects = 4;
    274     static const SkVector gRadii[kNumRRects][4] = {
    275         { {  0,  0 }, {  0,  0 }, {  0,  0 }, {  0,  0 } },  // rect
    276         { { 20, 20 }, { 20, 20 }, { 20, 20 }, { 20, 20 } },  // circle
    277         { { 10, 10 }, { 10, 10 }, { 10, 10 }, { 10, 10 } },  // simple
    278         { {  0,  0 }, { 20, 20 }, { 10, 10 }, { 30, 30 } }   // complex
    279     };
    280 
    281     SkRRect rrects[kNumRRects];
    282     for (int i = 0; i < kNumRRects; ++i) {
    283         rrects[i].setRectRadii(SkRect::MakeWH(40, 40), gRadii[i]);
    284     }
    285 
    286     // First test easy outs - boxes that are obviously out on
    287     // each corner and edge
    288     static const SkRect easyOuts[] = {
    289         { -5, -5,  5,  5 }, // NW
    290         { 15, -5, 20,  5 }, // N
    291         { 35, -5, 45,  5 }, // NE
    292         { 35, 15, 45, 20 }, // E
    293         { 35, 45, 35, 45 }, // SE
    294         { 15, 35, 20, 45 }, // S
    295         { -5, 35,  5, 45 }, // SW
    296         { -5, 15,  5, 20 }  // W
    297     };
    298 
    299     for (int i = 0; i < kNumRRects; ++i) {
    300         for (size_t j = 0; j < SK_ARRAY_COUNT(easyOuts); ++j) {
    301             REPORTER_ASSERT(reporter, !rrects[i].contains(easyOuts[j]));
    302         }
    303     }
    304 
    305     // Now test non-trivial containment. For each compass
    306     // point walk a 1x1 rect in from the edge  of the bounding
    307     // rect
    308     static const int kNumSteps = 15;
    309     bool answers[kNumRRects][8][kNumSteps] = {
    310         // all the test rects are inside the degenerate rrect
    311         {
    312             // rect
    313             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    314             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    315             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    316             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    317             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    318             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    319             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    320             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    321         },
    322         // for the circle we expect 6 blocks to be out on the
    323         // corners (then the rest in) and only the first block
    324         // out on the vertical and horizontal axes (then
    325         // the rest in)
    326         {
    327             // circle
    328             { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    329             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    330             { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    331             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    332             { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    333             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    334             { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    335             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    336         },
    337         // for the simple round rect we expect 3 out on
    338         // the corners (then the rest in) and no blocks out
    339         // on the vertical and horizontal axes
    340         {
    341             // simple RR
    342             { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    343             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    344             { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    345             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    346             { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    347             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    348             { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    349             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    350         },
    351         // for the complex case the answer is different for each direction
    352         {
    353             // complex RR
    354             // all in for NW (rect) corner (same as rect case)
    355             { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    356             // only first block out for N (same as circle case)
    357             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    358             // first 6 blocks out for NE (same as circle case)
    359             { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    360             // only first block out for E (same as circle case)
    361             { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    362             // first 3 blocks out for SE (same as simple case)
    363             { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    364             // first two blocks out for S
    365             { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    366             // first 9 blocks out for SW
    367             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
    368             // first two blocks out for W (same as S)
    369             { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    370          }
    371     };
    372 
    373     for (int i = 0; i < kNumRRects; ++i) {
    374         test_direction(reporter, rrects[i],     0,  1,     0,  1, kNumSteps, answers[i][0]); // NW
    375         test_direction(reporter, rrects[i], 19.5f,  0,     0,  1, kNumSteps, answers[i][1]); // N
    376         test_direction(reporter, rrects[i],    40, -1,     0,  1, kNumSteps, answers[i][2]); // NE
    377         test_direction(reporter, rrects[i],    40, -1, 19.5f,  0, kNumSteps, answers[i][3]); // E
    378         test_direction(reporter, rrects[i],    40, -1,    40, -1, kNumSteps, answers[i][4]); // SE
    379         test_direction(reporter, rrects[i], 19.5f,  0,    40, -1, kNumSteps, answers[i][5]); // S
    380         test_direction(reporter, rrects[i],     0,  1,    40, -1, kNumSteps, answers[i][6]); // SW
    381         test_direction(reporter, rrects[i],     0,  1, 19.5f,  0, kNumSteps, answers[i][7]); // W
    382     }
    383 }
    384 
    385 // Called for a matrix that should cause SkRRect::transform to fail.
    386 static void assert_transform_failure(skiatest::Reporter* reporter, const SkRRect& orig,
    387                                      const SkMatrix& matrix) {
    388     // The test depends on the fact that the original is not empty.
    389     SkASSERT(!orig.isEmpty());
    390     SkRRect dst;
    391     dst.setEmpty();
    392 
    393     const SkRRect copyOfDst = dst;
    394     const SkRRect copyOfOrig = orig;
    395     bool success = orig.transform(matrix, &dst);
    396     // This transform should fail.
    397     REPORTER_ASSERT(reporter, !success);
    398     // Since the transform failed, dst should be unchanged.
    399     REPORTER_ASSERT(reporter, copyOfDst == dst);
    400     // original should not be modified.
    401     REPORTER_ASSERT(reporter, copyOfOrig == orig);
    402     REPORTER_ASSERT(reporter, orig != dst);
    403 }
    404 
    405 #define GET_RADII                                                       \
    406     const SkVector& origUL = orig.radii(SkRRect::kUpperLeft_Corner);    \
    407     const SkVector& origUR = orig.radii(SkRRect::kUpperRight_Corner);   \
    408     const SkVector& origLR = orig.radii(SkRRect::kLowerRight_Corner);   \
    409     const SkVector& origLL = orig.radii(SkRRect::kLowerLeft_Corner);    \
    410     const SkVector& dstUL = dst.radii(SkRRect::kUpperLeft_Corner);      \
    411     const SkVector& dstUR = dst.radii(SkRRect::kUpperRight_Corner);     \
    412     const SkVector& dstLR = dst.radii(SkRRect::kLowerRight_Corner);     \
    413     const SkVector& dstLL = dst.radii(SkRRect::kLowerLeft_Corner)
    414 
    415 // Called to test various transforms on a single SkRRect.
    416 static void test_transform_helper(skiatest::Reporter* reporter, const SkRRect& orig) {
    417     SkRRect dst;
    418     dst.setEmpty();
    419 
    420     // The identity matrix will duplicate the rrect.
    421     bool success = orig.transform(SkMatrix::I(), &dst);
    422     REPORTER_ASSERT(reporter, success);
    423     REPORTER_ASSERT(reporter, orig == dst);
    424 
    425     // Skew and Perspective make transform fail.
    426     SkMatrix matrix;
    427     matrix.reset();
    428     matrix.setSkewX(SkIntToScalar(2));
    429     assert_transform_failure(reporter, orig, matrix);
    430 
    431     matrix.reset();
    432     matrix.setSkewY(SkIntToScalar(3));
    433     assert_transform_failure(reporter, orig, matrix);
    434 
    435     matrix.reset();
    436     matrix.setPerspX(SkScalarToPersp(SkIntToScalar(4)));
    437     assert_transform_failure(reporter, orig, matrix);
    438 
    439     matrix.reset();
    440     matrix.setPerspY(SkScalarToPersp(SkIntToScalar(5)));
    441     assert_transform_failure(reporter, orig, matrix);
    442 
    443     // Rotation fails.
    444     matrix.reset();
    445     matrix.setRotate(SkIntToScalar(90));
    446     assert_transform_failure(reporter, orig, matrix);
    447     matrix.setRotate(SkIntToScalar(37));
    448     assert_transform_failure(reporter, orig, matrix);
    449 
    450     // Translate will keep the rect moved, but otherwise the same.
    451     matrix.reset();
    452     SkScalar translateX = SkIntToScalar(32);
    453     SkScalar translateY = SkIntToScalar(15);
    454     matrix.setTranslateX(translateX);
    455     matrix.setTranslateY(translateY);
    456     dst.setEmpty();
    457     success = orig.transform(matrix, &dst);
    458     REPORTER_ASSERT(reporter, success);
    459     for (int i = 0; i < 4; ++i) {
    460         REPORTER_ASSERT(reporter,
    461                 orig.radii((SkRRect::Corner) i) == dst.radii((SkRRect::Corner) i));
    462     }
    463     REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
    464     REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
    465     REPORTER_ASSERT(reporter, dst.rect().left() == orig.rect().left() + translateX);
    466     REPORTER_ASSERT(reporter, dst.rect().top() == orig.rect().top() + translateY);
    467 
    468     // Keeping the translation, but adding skew will make transform fail.
    469     matrix.setSkewY(SkIntToScalar(7));
    470     assert_transform_failure(reporter, orig, matrix);
    471 
    472     // Scaling in -x will flip the round rect horizontally.
    473     matrix.reset();
    474     matrix.setScaleX(SkIntToScalar(-1));
    475     dst.setEmpty();
    476     success = orig.transform(matrix, &dst);
    477     REPORTER_ASSERT(reporter, success);
    478     {
    479         GET_RADII;
    480         // Radii have swapped in x.
    481         REPORTER_ASSERT(reporter, origUL == dstUR);
    482         REPORTER_ASSERT(reporter, origUR == dstUL);
    483         REPORTER_ASSERT(reporter, origLR == dstLL);
    484         REPORTER_ASSERT(reporter, origLL == dstLR);
    485     }
    486     // Width and height remain the same.
    487     REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
    488     REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
    489     // Right and left have swapped (sort of)
    490     REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left());
    491     // Top has stayed the same.
    492     REPORTER_ASSERT(reporter, orig.rect().top() == dst.rect().top());
    493 
    494     // Keeping the scale, but adding a persp will make transform fail.
    495     matrix.setPerspX(SkScalarToPersp(SkIntToScalar(7)));
    496     assert_transform_failure(reporter, orig, matrix);
    497 
    498     // Scaling in -y will flip the round rect vertically.
    499     matrix.reset();
    500     matrix.setScaleY(SkIntToScalar(-1));
    501     dst.setEmpty();
    502     success = orig.transform(matrix, &dst);
    503     REPORTER_ASSERT(reporter, success);
    504     {
    505         GET_RADII;
    506         // Radii have swapped in y.
    507         REPORTER_ASSERT(reporter, origUL == dstLL);
    508         REPORTER_ASSERT(reporter, origUR == dstLR);
    509         REPORTER_ASSERT(reporter, origLR == dstUR);
    510         REPORTER_ASSERT(reporter, origLL == dstUL);
    511     }
    512     // Width and height remain the same.
    513     REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
    514     REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
    515     // Top and bottom have swapped (sort of)
    516     REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom());
    517     // Left has stayed the same.
    518     REPORTER_ASSERT(reporter, orig.rect().left() == dst.rect().left());
    519 
    520     // Scaling in -x and -y will swap in both directions.
    521     matrix.reset();
    522     matrix.setScaleY(SkIntToScalar(-1));
    523     matrix.setScaleX(SkIntToScalar(-1));
    524     dst.setEmpty();
    525     success = orig.transform(matrix, &dst);
    526     REPORTER_ASSERT(reporter, success);
    527     {
    528         GET_RADII;
    529         REPORTER_ASSERT(reporter, origUL == dstLR);
    530         REPORTER_ASSERT(reporter, origUR == dstLL);
    531         REPORTER_ASSERT(reporter, origLR == dstUL);
    532         REPORTER_ASSERT(reporter, origLL == dstUR);
    533     }
    534     // Width and height remain the same.
    535     REPORTER_ASSERT(reporter, orig.rect().width() == dst.rect().width());
    536     REPORTER_ASSERT(reporter, orig.rect().height() == dst.rect().height());
    537     REPORTER_ASSERT(reporter, orig.rect().top() == -dst.rect().bottom());
    538     REPORTER_ASSERT(reporter, orig.rect().right() == -dst.rect().left());
    539 
    540     // Scale in both directions.
    541     SkScalar xScale = SkIntToScalar(3);
    542     SkScalar yScale = 3.2f;
    543     matrix.reset();
    544     matrix.setScaleX(xScale);
    545     matrix.setScaleY(yScale);
    546     dst.setEmpty();
    547     success = orig.transform(matrix, &dst);
    548     REPORTER_ASSERT(reporter, success);
    549     // Radii are scaled.
    550     for (int i = 0; i < 4; ++i) {
    551         REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fX,
    552                                     SkScalarMul(orig.radii((SkRRect::Corner) i).fX, xScale)));
    553         REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.radii((SkRRect::Corner) i).fY,
    554                                     SkScalarMul(orig.radii((SkRRect::Corner) i).fY, yScale)));
    555     }
    556     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().width(),
    557                                                   SkScalarMul(orig.rect().width(), xScale)));
    558     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().height(),
    559                                                   SkScalarMul(orig.rect().height(), yScale)));
    560     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().left(),
    561                                                   SkScalarMul(orig.rect().left(), xScale)));
    562     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst.rect().top(),
    563                                                   SkScalarMul(orig.rect().top(), yScale)));
    564 }
    565 
    566 static void test_round_rect_transform(skiatest::Reporter* reporter) {
    567     SkRRect rrect;
    568     {
    569         SkRect r = { 0, 0, kWidth, kHeight };
    570         rrect.setRectXY(r, SkIntToScalar(4), SkIntToScalar(7));
    571         test_transform_helper(reporter, rrect);
    572     }
    573     {
    574         SkRect r = { SkIntToScalar(5), SkIntToScalar(15),
    575                      SkIntToScalar(27), SkIntToScalar(34) };
    576         SkVector radii[4] = { { 0, SkIntToScalar(1) },
    577                               { SkIntToScalar(2), SkIntToScalar(3) },
    578                               { SkIntToScalar(4), SkIntToScalar(5) },
    579                               { SkIntToScalar(6), SkIntToScalar(7) } };
    580         rrect.setRectRadii(r, radii);
    581         test_transform_helper(reporter, rrect);
    582     }
    583 }
    584 
    585 DEF_TEST(RoundRect, reporter) {
    586     test_round_rect_basic(reporter);
    587     test_round_rect_rects(reporter);
    588     test_round_rect_ovals(reporter);
    589     test_round_rect_general(reporter);
    590     test_round_rect_iffy_parameters(reporter);
    591     test_inset(reporter);
    592     test_round_rect_contains_rect(reporter);
    593     test_round_rect_transform(reporter);
    594 }
    595