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 "SkBlurMask.h"
     10 #include "SkBlurMaskFilter.h"
     11 #include "SkCanvas.h"
     12 #include "SkColorFilter.h"
     13 #include "SkLayerDrawLooper.h"
     14 #include "SkPaint.h"
     15 #include "SkPath.h"
     16 #include "SkPoint.h"
     17 #include "SkRect.h"
     18 #include "SkRRect.h"
     19 #include "SkString.h"
     20 #include "SkXfermode.h"
     21 
     22 // This GM mimics a blurred RR seen in the wild.
     23 class BlurRoundRectGM : public skiagm::GM {
     24 public:
     25     BlurRoundRectGM(int width, int height)
     26         : fName("blurroundrect"), fWidth(width), fHeight(height) {
     27         fName.appendf("-WH-%ix%i-unevenCorners", width,  height);
     28     }
     29 
     30     SkString onShortName() override {
     31         return fName;
     32     }
     33 
     34     SkISize onISize() override {
     35         return SkISize::Make(fWidth, fHeight);
     36     }
     37 
     38     void onOnceBeforeDraw() override {
     39         SkVector radii[4];
     40         radii[0].set(SkIntToScalar(30), SkIntToScalar(30));
     41         radii[1].set(SkIntToScalar(10), SkIntToScalar(10));
     42         radii[2].set(SkIntToScalar(30), SkIntToScalar(30));
     43         radii[3].set(SkIntToScalar(10), SkIntToScalar(10));
     44         SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight));
     45         fRRect.setRectRadii(r, radii);
     46     }
     47 
     48     void onDraw(SkCanvas* canvas) override {
     49         SkLayerDrawLooper::Builder looperBuilder;
     50         {
     51             SkLayerDrawLooper::LayerInfo info;
     52             info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit
     53                               | SkLayerDrawLooper::kColorFilter_Bit;
     54             info.fColorMode = SkXfermode::kSrc_Mode;
     55             info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0));
     56             info.fPostTranslate = false;
     57             SkPaint* paint = looperBuilder.addLayerOnTop(info);
     58             SkMaskFilter* maskFilter = SkBlurMaskFilter::Create(
     59                     kNormal_SkBlurStyle,
     60                     SkBlurMask::ConvertRadiusToSigma(SK_ScalarHalf),
     61                     SkBlurMaskFilter::kHighQuality_BlurFlag);
     62             paint->setMaskFilter(maskFilter)->unref();
     63             SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(
     64                     sk_tool_utils::color_to_565(SK_ColorLTGRAY),
     65                     SkXfermode::kSrcIn_Mode);
     66             paint->setColorFilter(colorFilter)->unref();
     67             paint->setColor(sk_tool_utils::color_to_565(SK_ColorGRAY));
     68         }
     69         {
     70             SkLayerDrawLooper::LayerInfo info;
     71             looperBuilder.addLayerOnTop(info);
     72         }
     73         SkPaint paint;
     74         canvas->drawRect(fRRect.rect(), paint);
     75 
     76         paint.setLooper(looperBuilder.detachLooper())->unref();
     77         paint.setColor(SK_ColorCYAN);
     78         paint.setAntiAlias(true);
     79 
     80         canvas->drawRRect(fRRect, paint);
     81     }
     82 
     83 private:
     84     SkString        fName;
     85     SkRRect         fRRect;
     86     int             fWidth, fHeight;
     87 
     88     typedef skiagm::GM INHERITED;
     89 };
     90 
     91 #include "SkGradientShader.h"
     92 /*
     93  * Spits out a dummy gradient to test blur with shader on paint
     94  */
     95 static SkShader* MakeRadial() {
     96     SkPoint pts[2] = {
     97         { 0, 0 },
     98         { SkIntToScalar(100), SkIntToScalar(100) }
     99     };
    100     SkShader::TileMode tm = SkShader::kClamp_TileMode;
    101     const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
    102     const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
    103     SkMatrix scale;
    104     scale.setScale(0.5f, 0.5f);
    105     scale.postTranslate(5.f, 5.f);
    106     SkPoint center0, center1;
    107     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
    108                 SkScalarAve(pts[0].fY, pts[1].fY));
    109     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
    110                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    111     return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
    112                                                    center0, (pts[1].fX - pts[0].fX) / 2,
    113                                                    colors, pos, SK_ARRAY_COUNT(colors), tm,
    114                                                    0, &scale);
    115 }
    116 
    117 // Simpler blurred RR test cases where all the radii are the same.
    118 class SimpleBlurRoundRectGM : public skiagm::GM {
    119 public:
    120     SimpleBlurRoundRectGM()
    121         : fName("simpleblurroundrect") {
    122     }
    123 
    124 protected:
    125 
    126     SkString onShortName() override {
    127         return fName;
    128     }
    129 
    130     SkISize onISize() override {
    131         return SkISize::Make(1000, 500);
    132     }
    133 
    134     void onDraw(SkCanvas* canvas) override {
    135         canvas->scale(1.5f, 1.5f);
    136         canvas->translate(50,50);
    137 
    138         const float blurRadii[] = { 1,5,10,20 };
    139         const int cornerRadii[] = { 1,5,10,20 };
    140         const SkRect r = SkRect::MakeWH(SkIntToScalar(25), SkIntToScalar(25));
    141         for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) {
    142             SkAutoCanvasRestore autoRestore(canvas, true);
    143             canvas->translate(0, (r.height() + SkIntToScalar(50)) * i);
    144             for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) {
    145                 for (int k = 0; k <= 1; k++) {
    146                     SkMaskFilter* filter = SkBlurMaskFilter::Create(
    147                         kNormal_SkBlurStyle,
    148                         SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])),
    149                         SkBlurMaskFilter::kHighQuality_BlurFlag);
    150                     SkPaint paint;
    151                     paint.setColor(SK_ColorBLACK);
    152                     paint.setMaskFilter(filter)->unref();
    153 
    154                     bool useRadial = SkToBool(k);
    155                     if (useRadial) {
    156                         paint.setShader(MakeRadial())->unref();
    157                     }
    158 
    159                     SkRRect rrect;
    160                     rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]),
    161                                     SkIntToScalar(cornerRadii[j]));
    162                     canvas->drawRRect(rrect, paint);
    163                     canvas->translate(r.width() + SkIntToScalar(50), 0);
    164                 }
    165             }
    166         }
    167     }
    168 private:
    169     const SkString  fName;
    170 
    171     typedef         skiagm::GM INHERITED;
    172 };
    173 
    174 // Create one with dimensions/rounded corners based on the skp
    175 //
    176 // TODO(scroggo): Disabled in an attempt to rememdy
    177 // https://code.google.com/p/skia/issues/detail?id=1801 ('Win7 Test bots all failing GenerateGMs:
    178 // ran wrong number of tests')
    179 //DEF_GM(return new BlurRoundRectGM(600, 5514, 6);)
    180 
    181 // Rounded rect with two opposite corners with large radii, the other two
    182 // small.
    183 DEF_GM(return new BlurRoundRectGM(100, 100);)
    184 
    185 DEF_GM(return new SimpleBlurRoundRectGM();)
    186