Home | History | Annotate | Download | only in gm
      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 "gm.h"
      9 #include "SkBlurMask.h"
     10 #include "SkBlurMaskFilter.h"
     11 #include "SkCanvas.h"
     12 #include "SkPath.h"
     13 
     14 #define STROKE_WIDTH    SkIntToScalar(10)
     15 
     16 typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
     17 
     18 static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
     19     canvas->drawRect(r, p);
     20 }
     21 
     22 static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
     23     SkRect  rect;
     24     SkPath  path;
     25 
     26     rect = r;
     27     rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
     28     path.addRect(rect);
     29     rect = r;
     30     rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
     31 
     32     path.addRect(rect);
     33     path.setFillType(SkPath::kEvenOdd_FillType);
     34 
     35     canvas->drawPath(path, p);
     36 }
     37 
     38 static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
     39     SkRect  rect;
     40     SkPath  path;
     41 
     42     rect = r;
     43     rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
     44     path.addRect(rect);
     45     rect = r;
     46     rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
     47 
     48     rect.offset(7, -7);
     49 
     50     path.addRect(rect);
     51     path.setFillType(SkPath::kEvenOdd_FillType);
     52 
     53     canvas->drawPath(path, p);
     54 }
     55 
     56 #include "SkGradientShader.h"
     57 
     58 /*
     59  * Spits out a dummy gradient to test blur with shader on paint
     60  */
     61 static SkShader* MakeRadial() {
     62     SkPoint pts[2] = {
     63         { 0, 0 },
     64         { SkIntToScalar(100), SkIntToScalar(100) }
     65     };
     66     SkShader::TileMode tm = SkShader::kClamp_TileMode;
     67     const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
     68     const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
     69     SkMatrix scale;
     70     scale.setScale(0.5f, 0.5f);
     71     scale.postTranslate(25.f, 25.f);
     72     SkPoint center0, center1;
     73     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
     74                 SkScalarAve(pts[0].fY, pts[1].fY));
     75     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
     76                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
     77     return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
     78                                                   center0, (pts[1].fX - pts[0].fX) / 2,
     79                                                   colors, pos, SK_ARRAY_COUNT(colors), tm,
     80                                                   0, &scale);
     81 }
     82 
     83 typedef void (*PaintProc)(SkPaint*, SkScalar width);
     84 
     85 class BlurRectGM : public skiagm::GM {
     86       SkAutoTUnref<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
     87       SkString  fName;
     88       SkAlpha   fAlpha;
     89 public:
     90     BlurRectGM(const char name[], U8CPU alpha)
     91         : fName(name)
     92         , fAlpha(SkToU8(alpha)) {
     93     }
     94 
     95 protected:
     96     void onOnceBeforeDraw() override {
     97         for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
     98             fMaskFilters[i].reset(SkBlurMaskFilter::Create((SkBlurStyle)i,
     99                                   SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)),
    100                                   SkBlurMaskFilter::kHighQuality_BlurFlag));
    101         }
    102     }
    103 
    104     SkString onShortName() override {
    105         return fName;
    106     }
    107 
    108     SkISize onISize() override {
    109         return SkISize::Make(860, 820);
    110     }
    111 
    112     void onDraw(SkCanvas* canvas) override {
    113         canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
    114 
    115         SkRect  r = { 0, 0, 100, 50 };
    116         SkScalar scales[] = { SK_Scalar1, 0.6f };
    117 
    118         for (size_t s = 0; s < SK_ARRAY_COUNT(scales); ++s) {
    119             canvas->save();
    120             for (size_t f = 0; f < SK_ARRAY_COUNT(fMaskFilters); ++f) {
    121                 SkPaint paint;
    122                 paint.setMaskFilter(fMaskFilters[f]);
    123                 paint.setAlpha(fAlpha);
    124 
    125                 SkPaint paintWithRadial = paint;
    126                 paintWithRadial.setShader(MakeRadial())->unref();
    127 
    128                 static const Proc procs[] = {
    129                     fill_rect, draw_donut, draw_donut_skewed
    130                 };
    131 
    132                 canvas->save();
    133                 canvas->scale(scales[s], scales[s]);
    134                 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
    135                 canvas->translate(r.width() * 4/3, 0);
    136                 this->drawProcs(canvas, r, paintWithRadial, false, procs, SK_ARRAY_COUNT(procs));
    137                 canvas->translate(r.width() * 4/3, 0);
    138                 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
    139                 canvas->translate(r.width() * 4/3, 0);
    140                 this->drawProcs(canvas, r, paintWithRadial, true, procs, SK_ARRAY_COUNT(procs));
    141                 canvas->restore();
    142 
    143                 canvas->translate(0, SK_ARRAY_COUNT(procs) * r.height() * 4/3 * scales[s]);
    144             }
    145             canvas->restore();
    146             canvas->translate(4 * r.width() * 4/3 * scales[s], 0);
    147         }
    148     }
    149 
    150 private:
    151     void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
    152                    bool doClip, const Proc procs[], size_t procsCount) {
    153         SkAutoCanvasRestore acr(canvas, true);
    154         for (size_t i = 0; i < procsCount; ++i) {
    155             if (doClip) {
    156                 SkRect clipRect(r);
    157                 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
    158                 canvas->save();
    159                 canvas->clipRect(r);
    160             }
    161             procs[i](canvas, r, paint);
    162             if (doClip) {
    163                 canvas->restore();
    164             }
    165             canvas->translate(0, r.height() * 4/3);
    166         }
    167     }
    168 private:
    169     typedef GM INHERITED;
    170 };
    171 
    172 DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024) {
    173         const int fGMWidth = 1200;
    174         const int fPadding = 10;
    175         const int fMargin = 100;
    176 
    177         const int widths[] = {25, 5, 5, 100, 150, 25};
    178         const int heights[] = {100, 100, 5, 25, 150, 25};
    179         const SkBlurStyle styles[] = {kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle};
    180         const float radii[] = {20, 5, 10};
    181 
    182         canvas->translate(50,20);
    183 
    184         int cur_x = 0;
    185         int cur_y = 0;
    186 
    187         int max_height = 0;
    188 
    189         for (size_t i = 0 ; i < SK_ARRAY_COUNT(widths) ; i++) {
    190             int width = widths[i];
    191             int height = heights[i];
    192             SkRect r;
    193             r.setWH(SkIntToScalar(width), SkIntToScalar(height));
    194             SkAutoCanvasRestore autoRestore(canvas, true);
    195 
    196             for (size_t j = 0 ; j < SK_ARRAY_COUNT(radii) ; j++) {
    197                 float radius = radii[j];
    198                 for (size_t k = 0 ; k < SK_ARRAY_COUNT(styles) ; k++) {
    199                     SkBlurStyle style = styles[k];
    200 
    201                     SkMask mask;
    202                     if (!SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
    203                                               &mask, r, style)) {
    204                         continue;
    205                     }
    206 
    207                     SkAutoMaskFreeImage amfi(mask.fImage);
    208 
    209                     SkBitmap bm;
    210                     bm.installMaskPixels(mask);
    211 
    212                     if (cur_x + bm.width() >= fGMWidth - fMargin) {
    213                         cur_x = 0;
    214                         cur_y += max_height + fPadding;
    215                         max_height = 0;
    216                     }
    217 
    218                     canvas->save();
    219                     canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
    220                     canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
    221                     canvas->drawBitmap(bm, 0.f, 0.f, nullptr);
    222                     canvas->restore();
    223 
    224                     cur_x += bm.width() + fPadding;
    225                     if (bm.height() > max_height)
    226                         max_height = bm.height();
    227                 }
    228             }
    229         }
    230 }
    231 
    232 //////////////////////////////////////////////////////////////////////////////
    233 
    234 DEF_GM(return new BlurRectGM("blurrects", 0xFF);)
    235