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