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