Home | History | Annotate | Download | only in gm
      1 
      2 /*
      3  * Copyright 2011 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 #include "gm.h"
      9 #include "SkPath.h"
     10 #include "SkRegion.h"
     11 #include "SkShader.h"
     12 #include "SkUtils.h"
     13 #include "SkColorPriv.h"
     14 #include "SkColorFilter.h"
     15 #include "SkTypeface.h"
     16 
     17 // effects
     18 #include "SkGradientShader.h"
     19 #include "SkBlurDrawLooper.h"
     20 
     21 static void makebm(SkBitmap* bm, SkColorType ct, int w, int h) {
     22     bm->allocPixels(SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType));
     23     bm->eraseColor(SK_ColorTRANSPARENT);
     24 
     25     SkCanvas    canvas(*bm);
     26     SkPoint     pts[] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h)} };
     27     SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
     28     SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
     29     SkPaint     paint;
     30 
     31     paint.setDither(true);
     32     paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos,
     33                 SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode))->unref();
     34     canvas.drawPaint(paint);
     35 }
     36 
     37 static void setup(SkPaint* paint, const SkBitmap& bm, bool filter,
     38                   SkShader::TileMode tmx, SkShader::TileMode tmy) {
     39     SkShader* shader = SkShader::CreateBitmapShader(bm, tmx, tmy);
     40     paint->setShader(shader)->unref();
     41     paint->setFilterLevel(filter ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
     42 }
     43 
     44 static const SkColorType gColorTypes[] = {
     45     kN32_SkColorType,
     46     kRGB_565_SkColorType,
     47 };
     48 
     49 class TilingGM : public skiagm::GM {
     50 public:
     51     TilingGM(bool powerOfTwoSize)
     52             : fPowerOfTwoSize(powerOfTwoSize) {
     53     }
     54 
     55     SkBitmap    fTexture[SK_ARRAY_COUNT(gColorTypes)];
     56 
     57 protected:
     58 
     59     enum {
     60         kPOTSize = 32,
     61         kNPOTSize = 21,
     62     };
     63 
     64     SkString onShortName() {
     65         SkString name("tilemodes");
     66         if (!fPowerOfTwoSize) {
     67             name.append("_npot");
     68         }
     69         return name;
     70     }
     71 
     72     SkISize onISize() { return SkISize::Make(880, 560); }
     73 
     74     virtual void onOnceBeforeDraw() SK_OVERRIDE {
     75         int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
     76         for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
     77             makebm(&fTexture[i], gColorTypes[i], size, size);
     78         }
     79     }
     80 
     81     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
     82 
     83         int size = fPowerOfTwoSize ? kPOTSize : kNPOTSize;
     84 
     85         SkRect r = { 0, 0, SkIntToScalar(size*2), SkIntToScalar(size*2) };
     86 
     87         static const char* gConfigNames[] = { "8888", "565", "4444" };
     88 
     89         static const bool           gFilters[] = { false, true };
     90         static const char*          gFilterNames[] = {     "point",                     "bilinear" };
     91 
     92         static const SkShader::TileMode gModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode };
     93         static const char*          gModeNames[] = {    "C",                    "R",                   "M" };
     94 
     95         SkScalar y = SkIntToScalar(24);
     96         SkScalar x = SkIntToScalar(10);
     97 
     98         for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
     99             for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
    100                 SkPaint p;
    101                 SkString str;
    102                 p.setAntiAlias(true);
    103                 p.setDither(true);
    104                 str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
    105 
    106                 p.setTextAlign(SkPaint::kCenter_Align);
    107                 canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
    108 
    109                 x += r.width() * 4 / 3;
    110             }
    111         }
    112 
    113         y += SkIntToScalar(16);
    114 
    115         for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
    116             for (size_t j = 0; j < SK_ARRAY_COUNT(gFilters); j++) {
    117                 x = SkIntToScalar(10);
    118                 for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
    119                     for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
    120                         SkPaint paint;
    121 #if 1 // Temporary change to regen bitmap before each draw. This may help tracking down an issue
    122       // on SGX where resizing NPOT textures to POT textures exhibits a driver bug.
    123                         if (!fPowerOfTwoSize) {
    124                             makebm(&fTexture[i], gColorTypes[i], size, size);
    125                         }
    126 #endif
    127                         setup(&paint, fTexture[i], gFilters[j], gModes[kx], gModes[ky]);
    128                         paint.setDither(true);
    129 
    130                         canvas->save();
    131                         canvas->translate(x, y);
    132                         canvas->drawRect(r, paint);
    133                         canvas->restore();
    134 
    135                         x += r.width() * 4 / 3;
    136                     }
    137                 }
    138                 {
    139                     SkPaint p;
    140                     SkString str;
    141                     p.setAntiAlias(true);
    142                     str.printf("%s, %s", gConfigNames[i], gFilterNames[j]);
    143                     canvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p);
    144                 }
    145 
    146                 y += r.height() * 4 / 3;
    147             }
    148         }
    149     }
    150 
    151 private:
    152     bool fPowerOfTwoSize;
    153     typedef skiagm::GM INHERITED;
    154 };
    155 
    156 static const int gWidth = 32;
    157 static const int gHeight = 32;
    158 
    159 static SkShader* make_bm(SkShader::TileMode tx, SkShader::TileMode ty) {
    160     SkBitmap bm;
    161     makebm(&bm, kN32_SkColorType, gWidth, gHeight);
    162     return SkShader::CreateBitmapShader(bm, tx, ty);
    163 }
    164 
    165 static SkShader* make_grad(SkShader::TileMode tx, SkShader::TileMode ty) {
    166     SkPoint pts[] = { { 0, 0 }, { SkIntToScalar(gWidth), SkIntToScalar(gHeight)} };
    167     SkPoint center = { SkIntToScalar(gWidth)/2, SkIntToScalar(gHeight)/2 };
    168     SkScalar rad = SkIntToScalar(gWidth)/2;
    169     SkColor colors[] = { 0xFFFF0000, 0xFF0044FF };
    170 
    171     int index = (int)ty;
    172     switch (index % 3) {
    173         case 0:
    174             return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors), tx);
    175         case 1:
    176             return SkGradientShader::CreateRadial(center, rad, colors, NULL, SK_ARRAY_COUNT(colors), tx);
    177         case 2:
    178             return SkGradientShader::CreateSweep(center.fX, center.fY, colors, NULL, SK_ARRAY_COUNT(colors));
    179     }
    180 
    181     return NULL;
    182 }
    183 
    184 typedef SkShader* (*ShaderProc)(SkShader::TileMode, SkShader::TileMode);
    185 
    186 class Tiling2GM : public skiagm::GM {
    187     ShaderProc fProc;
    188     SkString   fName;
    189 public:
    190     Tiling2GM(ShaderProc proc, const char name[]) : fProc(proc) {
    191         fName.printf("tilemode_%s", name);
    192     }
    193 
    194 protected:
    195     virtual uint32_t onGetFlags() const SK_OVERRIDE {
    196         return kSkipTiled_Flag;
    197     }
    198 
    199     SkString onShortName() {
    200         return fName;
    201     }
    202 
    203     SkISize onISize() { return SkISize::Make(880, 560); }
    204 
    205     virtual void onDraw(SkCanvas* canvas) {
    206         canvas->scale(SkIntToScalar(3)/2, SkIntToScalar(3)/2);
    207 
    208         const SkScalar w = SkIntToScalar(gWidth);
    209         const SkScalar h = SkIntToScalar(gHeight);
    210         SkRect r = { -w, -h, w*2, h*2 };
    211 
    212         static const SkShader::TileMode gModes[] = {
    213             SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode
    214         };
    215         static const char* gModeNames[] = {
    216             "Clamp", "Repeat", "Mirror"
    217         };
    218 
    219         SkScalar y = SkIntToScalar(24);
    220         SkScalar x = SkIntToScalar(66);
    221 
    222         SkPaint p;
    223         p.setAntiAlias(true);
    224         p.setTextAlign(SkPaint::kCenter_Align);
    225 
    226         for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
    227             SkString str(gModeNames[kx]);
    228             canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
    229             x += r.width() * 4 / 3;
    230         }
    231 
    232         y += SkIntToScalar(16) + h;
    233         p.setTextAlign(SkPaint::kRight_Align);
    234 
    235         for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
    236             x = SkIntToScalar(16) + w;
    237 
    238             SkString str(gModeNames[ky]);
    239             canvas->drawText(str.c_str(), str.size(), x, y + h/2, p);
    240 
    241             x += SkIntToScalar(50);
    242             for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
    243                 SkPaint paint;
    244                 paint.setShader(fProc(gModes[kx], gModes[ky]))->unref();
    245 
    246                 canvas->save();
    247                 canvas->translate(x, y);
    248                 canvas->drawRect(r, paint);
    249                 canvas->restore();
    250 
    251                 x += r.width() * 4 / 3;
    252             }
    253             y += r.height() * 4 / 3;
    254         }
    255     }
    256 
    257 private:
    258     typedef skiagm::GM INHERITED;
    259 };
    260 
    261 //////////////////////////////////////////////////////////////////////////////
    262 
    263 DEF_GM( return new TilingGM(true); )
    264 DEF_GM( return new TilingGM(false); )
    265 DEF_GM( return new Tiling2GM(make_bm, "bitmap"); )
    266 DEF_GM( return new Tiling2GM(make_grad, "gradient"); )
    267