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 "SkBlurMaskFilter.h"
     10 #include "SkBlurMask.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 typedef void (*PaintProc)(SkPaint*, SkScalar width);
     59 
     60 static const char* gBlurStyle2Name[] = {
     61     "normal",
     62     "solid",
     63     "outer",
     64     "inner"
     65 };
     66 
     67 class BlurRectGM : public skiagm::GM {
     68     SkAutoTUnref<SkMaskFilter> fMaskFilter;
     69     SkString  fName;
     70     PaintProc fPProc;
     71     SkAlpha   fAlpha;
     72 public:
     73     BlurRectGM(const char name[], PaintProc pproc, U8CPU alpha,
     74                SkBlurMaskFilter::BlurStyle bs) :
     75         fMaskFilter(SkBlurMaskFilter::Create(STROKE_WIDTH/2, bs,
     76                                        SkBlurMaskFilter::kHighQuality_BlurFlag))
     77         , fName(name)
     78         , fPProc(pproc)
     79         , fAlpha(SkToU8(alpha))
     80     {
     81         fName.appendf("_%s", gBlurStyle2Name[bs]);
     82     }
     83 
     84 protected:
     85     virtual SkString onShortName() {
     86         return fName;
     87     }
     88 
     89     virtual SkISize onISize() {
     90         return SkISize::Make(640, 480);
     91     }
     92 
     93     virtual void onDraw(SkCanvas* canvas) {
     94         canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
     95 
     96         SkRect  r = { 0, 0, 250, 120 };
     97 
     98         SkPaint paint;
     99         paint.setMaskFilter(fMaskFilter);
    100         if (fPProc) {
    101             fPProc(&paint, r.width());
    102         }
    103         paint.setAlpha(fAlpha);
    104 
    105         static const Proc procs[] = {
    106             fill_rect, draw_donut, draw_donut_skewed
    107         };
    108 
    109         this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
    110         canvas->translate(r.width() * 4/3, 0);
    111         this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
    112     }
    113 
    114     virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
    115 
    116 private:
    117     void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
    118                    bool doClip, const Proc procs[], size_t procsCount) {
    119         SkAutoCanvasRestore acr(canvas, true);
    120         for (size_t i = 0; i < procsCount; ++i) {
    121             if (doClip) {
    122                 SkRect clipRect(r);
    123                 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
    124                 canvas->save();
    125                 canvas->clipRect(r);
    126             }
    127             procs[i](canvas, r, paint);
    128             if (doClip) {
    129                 canvas->restore();
    130             }
    131             canvas->translate(0, r.height() * 4/3);
    132         }
    133     }
    134 
    135     typedef GM INHERITED;
    136 };
    137 
    138 class BlurRectCompareGM : public skiagm::GM {
    139     SkString  fName;
    140     unsigned int fRectWidth, fRectHeight;
    141     SkScalar fRadius;
    142 public:
    143     BlurRectCompareGM(const char name[], unsigned int rectWidth, unsigned int rectHeight, float radius)
    144         : fName(name)
    145         , fRectWidth(rectWidth)
    146         , fRectHeight(rectHeight)
    147         , fRadius(radius)
    148     {}
    149 
    150   int width() const { return fRectWidth; }
    151   int height() const { return fRectHeight; }
    152   SkScalar radius() const { return fRadius; }
    153 
    154 protected:
    155     virtual SkString onShortName() {
    156         return fName;
    157     }
    158 
    159     virtual SkISize onISize() {
    160         return SkISize::Make(640, 480);
    161     }
    162 
    163     virtual void makeMask(SkMask *m, const SkRect&) = 0;
    164 
    165     virtual void onDraw(SkCanvas* canvas) {
    166       SkRect r;
    167       r.setWH(SkIntToScalar(fRectWidth), SkIntToScalar(fRectHeight));
    168 
    169       SkMask mask;
    170 
    171       this->makeMask(&mask, r);
    172       SkAutoMaskFreeImage amfi(mask.fImage);
    173 
    174       SkBitmap bm;
    175       bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height());
    176       bm.setPixels(mask.fImage);
    177       canvas->drawBitmap(bm, 50, 50, NULL);
    178     }
    179 
    180     virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
    181 
    182 private:
    183     typedef GM INHERITED;
    184 };
    185 
    186 class BlurRectFastGM: public BlurRectCompareGM {
    187 public:
    188     BlurRectFastGM(const char name[], unsigned int rect_width,
    189                    unsigned int rect_height, float blur_radius) :
    190         BlurRectCompareGM(name, rect_width, rect_height, blur_radius) {}
    191 protected:
    192     virtual void makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
    193         SkBlurMask::BlurRect(m, r, radius(), SkBlurMask::kNormal_Style,
    194                              SkBlurMask::kHigh_Quality );
    195     }
    196 };
    197 
    198 class BlurRectSlowGM: public BlurRectCompareGM {
    199 public:
    200   BlurRectSlowGM(const char name[], unsigned int rect_width, unsigned int rect_height, float blur_radius) :
    201     BlurRectCompareGM( name, rect_width, rect_height, blur_radius ) {}
    202 protected:
    203     virtual void makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
    204         SkMask src;
    205         r.roundOut(&src.fBounds);
    206         src.fBounds.offset(-src.fBounds.fLeft, -src.fBounds.fTop);  // move to origin
    207         src.fFormat = SkMask::kA8_Format;
    208         src.fRowBytes = src.fBounds.width();
    209         src.fImage = SkMask::AllocImage( src.computeTotalImageSize() );
    210         SkAutoMaskFreeImage amfi(src.fImage);
    211 
    212         memset(src.fImage, 0xff, src.computeTotalImageSize());
    213 
    214         SkBlurMask::BlurSeparable(m, src, radius()/2, SkBlurMask::kNormal_Style, SkBlurMask::kHigh_Quality);
    215     }
    216 };
    217 
    218 
    219 //////////////////////////////////////////////////////////////////////////////
    220 
    221 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kNormal_BlurStyle);)
    222 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kSolid_BlurStyle);)
    223 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kOuter_BlurStyle);)
    224 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kInner_BlurStyle);)
    225 
    226 DEF_GM(return new BlurRectFastGM("blurrect_fast_100_100_10", 100, 100, 10);)
    227 DEF_GM(return new BlurRectFastGM("blurrect_fast_100_100_2", 100, 100, 2);)
    228 DEF_GM(return new BlurRectFastGM("blurrect_fast_10_10_100", 10, 10, 100);)
    229 DEF_GM(return new BlurRectFastGM("blurrect_fast_10_100_10", 10, 100, 10);)
    230 
    231 DEF_GM(return new BlurRectSlowGM("blurrect_slow_100_100_10", 100, 100, 10);)
    232 DEF_GM(return new BlurRectSlowGM("blurrect_slow_100_100_2", 100, 100, 2);)
    233 DEF_GM(return new BlurRectSlowGM("blurrect_slow_10_10_100", 10, 10, 100);)
    234 DEF_GM(return new BlurRectSlowGM("blurrect_slow_10_100_10", 10, 100, 10);)
    235