Home | History | Annotate | Download | only in gm
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "gm.h"
     10 #include "SkTArray.h"
     11 #include "SkRandom.h"
     12 #include "SkMatrix.h"
     13 #include "SkBlurMaskFilter.h"
     14 #include "SkGradientShader.h"
     15 #include "SkBlurDrawLooper.h"
     16 #include "SkRect.h"
     17 #include "SkRRect.h"
     18 
     19 namespace skiagm {
     20 
     21 static SkColor gen_color(SkRandom* rand) {
     22     SkScalar hsv[3];
     23     hsv[0] = rand->nextRangeF(0.0f, 360.0f);
     24     hsv[1] = rand->nextRangeF(0.75f, 1.0f);
     25     hsv[2] = rand->nextRangeF(0.75f, 1.0f);
     26 
     27     return sk_tool_utils::color_to_565(SkHSVToColor(hsv));
     28 }
     29 
     30 class RoundRectGM : public GM {
     31 public:
     32     RoundRectGM() {
     33         this->setBGColor(0xFF000000);
     34         this->makePaints();
     35         this->makeMatrices();
     36     }
     37 
     38 protected:
     39 
     40     SkString onShortName() override {
     41         return SkString("roundrects");
     42     }
     43 
     44     SkISize onISize() override {
     45         return SkISize::Make(1200, 900);
     46     }
     47 
     48     void makePaints() {
     49         {
     50         // no AA
     51         SkPaint p;
     52         fPaints.push_back(p);
     53         }
     54 
     55         {
     56         // AA
     57         SkPaint p;
     58         p.setAntiAlias(true);
     59         fPaints.push_back(p);
     60         }
     61 
     62         {
     63         // AA with stroke style
     64         SkPaint p;
     65         p.setAntiAlias(true);
     66         p.setStyle(SkPaint::kStroke_Style);
     67         p.setStrokeWidth(SkIntToScalar(5));
     68         fPaints.push_back(p);
     69         }
     70 
     71         {
     72         // AA with stroke style, width = 0
     73         SkPaint p;
     74         p.setAntiAlias(true);
     75         p.setStyle(SkPaint::kStroke_Style);
     76         fPaints.push_back(p);
     77         }
     78 
     79         {
     80         // AA with stroke and fill style
     81         SkPaint p;
     82         p.setAntiAlias(true);
     83         p.setStyle(SkPaint::kStrokeAndFill_Style);
     84         p.setStrokeWidth(SkIntToScalar(3));
     85         fPaints.push_back(p);
     86         }
     87     }
     88 
     89     void makeMatrices() {
     90         {
     91         SkMatrix m;
     92         m.setIdentity();
     93         fMatrices.push_back(m);
     94         }
     95 
     96         {
     97         SkMatrix m;
     98         m.setScale(SkIntToScalar(3), SkIntToScalar(2));
     99         fMatrices.push_back(m);
    100         }
    101 
    102         {
    103         SkMatrix m;
    104         m.setScale(SkIntToScalar(2), SkIntToScalar(2));
    105         fMatrices.push_back(m);
    106         }
    107 
    108         {
    109         SkMatrix m;
    110         m.setScale(SkIntToScalar(1), SkIntToScalar(2));
    111         fMatrices.push_back(m);
    112         }
    113 
    114         {
    115         SkMatrix m;
    116         m.setScale(SkIntToScalar(4), SkIntToScalar(1));
    117         fMatrices.push_back(m);
    118         }
    119 
    120         {
    121         SkMatrix m;
    122         m.setRotate(SkIntToScalar(90));
    123         fMatrices.push_back(m);
    124         }
    125 
    126         {
    127         SkMatrix m;
    128         m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
    129         fMatrices.push_back(m);
    130         }
    131 
    132         {
    133         SkMatrix m;
    134         m.setRotate(SkIntToScalar(60));
    135         fMatrices.push_back(m);
    136         }
    137     }
    138 
    139     void onDraw(SkCanvas* canvas) override {
    140         SkRandom rand(1);
    141         canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
    142         const SkRect rect = SkRect::MakeLTRB(-20, -30, 20, 30);
    143         SkRRect circleRect;
    144         circleRect.setRectXY(rect, 5, 5);
    145 
    146         const SkScalar kXStart = 60.0f;
    147         const SkScalar kYStart = 80.0f;
    148         const int kXStep = 150;
    149         const int kYStep = 160;
    150         int maxX = fMatrices.count();
    151 
    152         SkPaint rectPaint;
    153         rectPaint.setAntiAlias(true);
    154         rectPaint.setStyle(SkPaint::kStroke_Style);
    155         rectPaint.setStrokeWidth(SkIntToScalar(0));
    156         rectPaint.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY));
    157 
    158         int testCount = 0;
    159         for (int i = 0; i < fPaints.count(); ++i) {
    160             for (int j = 0; j < fMatrices.count(); ++j) {
    161                 canvas->save();
    162                 SkMatrix mat = fMatrices[j];
    163                 // position the roundrect, and make it at off-integer coords.
    164                 mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
    165                                   SK_Scalar1 / 4,
    166                                   kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
    167                                   3 * SK_Scalar1 / 4);
    168                 canvas->concat(mat);
    169 
    170                 SkColor color = gen_color(&rand);
    171                 fPaints[i].setColor(color);
    172 
    173                 canvas->drawRect(rect, rectPaint);
    174                 canvas->drawRRect(circleRect, fPaints[i]);
    175 
    176                 canvas->restore();
    177 
    178                 ++testCount;
    179             }
    180         }
    181 
    182         // special cases
    183 
    184         // non-scaled tall and skinny roundrect
    185         for (int i = 0; i < fPaints.count(); ++i) {
    186             SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60);
    187             SkRRect ellipseRect;
    188             ellipseRect.setRectXY(rect, 5, 10);
    189 
    190             canvas->save();
    191             // position the roundrect, and make it at off-integer coords.
    192             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
    193                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
    194 
    195             SkColor color = gen_color(&rand);
    196             fPaints[i].setColor(color);
    197 
    198             canvas->drawRect(rect, rectPaint);
    199             canvas->drawRRect(ellipseRect, fPaints[i]);
    200             canvas->restore();
    201         }
    202 
    203         // non-scaled wide and short roundrect
    204         for (int i = 0; i < fPaints.count(); ++i) {
    205             SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30);
    206             SkRRect ellipseRect;
    207             ellipseRect.setRectXY(rect, 20, 5);
    208 
    209             canvas->save();
    210             // position the roundrect, and make it at off-integer coords.
    211             canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
    212                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
    213                               SK_ScalarHalf * kYStep);
    214 
    215             SkColor color = gen_color(&rand);
    216             fPaints[i].setColor(color);
    217 
    218             canvas->drawRect(rect, rectPaint);
    219             canvas->drawRRect(ellipseRect, fPaints[i]);
    220             canvas->restore();
    221         }
    222 
    223         // super skinny roundrect
    224         for (int i = 0; i < fPaints.count(); ++i) {
    225             SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60);
    226             SkRRect circleRect;
    227             circleRect.setRectXY(rect, 5, 5);
    228 
    229             canvas->save();
    230             // position the roundrect, and make it at off-integer coords.
    231             canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
    232                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
    233 
    234             SkColor color = gen_color(&rand);
    235             fPaints[i].setColor(color);
    236 
    237             canvas->drawRRect(circleRect, fPaints[i]);
    238             canvas->restore();
    239         }
    240 
    241         // super short roundrect
    242         for (int i = 0; i < fPaints.count(); ++i) {
    243             SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0);
    244             SkRRect circleRect;
    245             circleRect.setRectXY(rect, 5, 5);
    246 
    247             canvas->save();
    248             // position the roundrect, and make it at off-integer coords.
    249             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
    250                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
    251                               SK_ScalarHalf * kYStep);
    252 
    253             SkColor color = gen_color(&rand);
    254             fPaints[i].setColor(color);
    255 
    256             canvas->drawRRect(circleRect, fPaints[i]);
    257             canvas->restore();
    258         }
    259 
    260         // radial gradient
    261         SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
    262         SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
    263         SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
    264         SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center,
    265                                                      SkIntToScalar(20),
    266                                                      colors,
    267                                                      pos,
    268                                                      SK_ARRAY_COUNT(colors),
    269                                                      SkShader::kClamp_TileMode));
    270 
    271         for (int i = 0; i < fPaints.count(); ++i) {
    272             canvas->save();
    273             // position the path, and make it at off-integer coords.
    274             canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
    275                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
    276                               SK_ScalarHalf * kYStep);
    277 
    278             SkColor color = gen_color(&rand);
    279             fPaints[i].setColor(color);
    280             fPaints[i].setShader(shader);
    281 
    282             canvas->drawRect(rect, rectPaint);
    283             canvas->drawRRect(circleRect, fPaints[i]);
    284 
    285             fPaints[i].setShader(nullptr);
    286 
    287             canvas->restore();
    288         }
    289 
    290         // strokes and radii
    291         {
    292             SkScalar radii[][2] = {
    293                 {10,10},
    294                 {5,15},
    295                 {5,15},
    296                 {5,15}
    297             };
    298 
    299             SkScalar strokeWidths[] = {
    300                 20, 10, 20, 40
    301             };
    302 
    303             for (int i = 0; i < 4; ++i) {
    304                 SkRRect circleRect;
    305                 circleRect.setRectXY(rect, radii[i][0], radii[i][1]);
    306 
    307                 canvas->save();
    308                 // position the roundrect, and make it at off-integer coords.
    309                 canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
    310                                   kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
    311                                   SK_ScalarHalf * kYStep);
    312 
    313                 SkColor color = gen_color(&rand);
    314 
    315                 SkPaint p;
    316                 p.setAntiAlias(true);
    317                 p.setStyle(SkPaint::kStroke_Style);
    318                 p.setStrokeWidth(strokeWidths[i]);
    319                 p.setColor(color);
    320 
    321                 canvas->drawRRect(circleRect, p);
    322                 canvas->restore();
    323             }
    324         }
    325 
    326         // test old entry point ( https://bug.skia.org/3786 )
    327         {
    328             canvas->save();
    329 
    330             canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
    331                               kYStart + SK_Scalar1 * kYStep * 4 + SK_Scalar1 / 4 +
    332                               SK_ScalarHalf * kYStep);
    333 
    334             const SkColor color = gen_color(&rand);
    335 
    336             SkPaint p;
    337             p.setColor(color);
    338 
    339             const SkRect oooRect = { 20, 30, -20, -30 };     // intentionally out of order
    340             canvas->drawRoundRect(oooRect, 10, 10, p);
    341 
    342             canvas->restore();
    343         }
    344     }
    345 
    346 private:
    347     SkTArray<SkPaint> fPaints;
    348     SkTArray<SkMatrix> fMatrices;
    349 
    350     typedef GM INHERITED;
    351 };
    352 
    353 //////////////////////////////////////////////////////////////////////////////
    354 
    355 static GM* MyFactory(void*) { return new RoundRectGM; }
    356 static GMRegistry reg(MyFactory);
    357 
    358 }
    359