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 #include "gm.h"
      8 #include "SkGradientShader.h"
      9 
     10 using namespace skiagm;
     11 
     12 struct GradData {
     13     int             fCount;
     14     const SkColor*  fColors;
     15     const SkScalar* fPos;
     16 };
     17 
     18 static const SkColor gColors[] = {
     19     SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE,
     20 };
     21 
     22 static const GradData gGradData[] = {
     23     { 1, gColors, NULL },
     24     { 2, gColors, NULL },
     25     { 3, gColors, NULL },
     26     { 4, gColors, NULL },
     27 };
     28 
     29 static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
     30     return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm);
     31 }
     32 
     33 static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
     34     SkPoint center;
     35     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
     36                SkScalarAve(pts[0].fY, pts[1].fY));
     37     return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
     38                                           data.fPos, data.fCount, tm);
     39 }
     40 
     41 static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode) {
     42     SkPoint center;
     43     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
     44                SkScalarAve(pts[0].fY, pts[1].fY));
     45     return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount);
     46 }
     47 
     48 static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
     49     SkPoint center0, center1;
     50     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
     51                 SkScalarAve(pts[0].fY, pts[1].fY));
     52     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
     53                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
     54     return SkGradientShader::CreateTwoPointRadial(
     55         center1, (pts[1].fX - pts[0].fX) / 7,
     56         center0, (pts[1].fX - pts[0].fX) / 2,
     57         data.fColors, data.fPos, data.fCount, tm);
     58 }
     59 
     60 static SkShader* Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) {
     61     SkPoint center0, center1;
     62     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
     63     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
     64     center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
     65     center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
     66     return SkGradientShader::CreateTwoPointConical(center1, radius1,
     67                                                    center0, radius0,
     68                                                    data.fColors, data.fPos,
     69                                                    data.fCount, tm);
     70 }
     71 
     72 
     73 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm);
     74 
     75 static const GradMaker gGradMakers[] = {
     76     MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical,
     77 };
     78 
     79 ///////////////////////////////////////////////////////////////////////////////
     80 
     81 class GradientsNoTextureGM : public GM {
     82 public:
     83     GradientsNoTextureGM() {
     84         this->setBGColor(0xFFDDDDDD);
     85     }
     86 
     87 protected:
     88     virtual uint32_t onGetFlags() const SK_OVERRIDE {
     89         return kSkipTiled_Flag;
     90     }
     91 
     92     SkString onShortName() SK_OVERRIDE { return SkString("gradients_no_texture"); }
     93     virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(640, 615); }
     94 
     95     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
     96         static const SkPoint kPts[2] = { { 0, 0 },
     97                                          { SkIntToScalar(50), SkIntToScalar(50) } };
     98         static const SkShader::TileMode kTM = SkShader::kClamp_TileMode;
     99         SkRect kRect = { 0, 0, SkIntToScalar(50), SkIntToScalar(50) };
    100         SkPaint paint;
    101         paint.setAntiAlias(true);
    102 
    103         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
    104         static const uint8_t kAlphas[] = { 0xff, 0x40 };
    105         for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphas); ++a) {
    106             for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); ++i) {
    107                 canvas->save();
    108                 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); ++j) {
    109                     SkShader* shader = gGradMakers[j](kPts, gGradData[i], kTM);
    110                     paint.setShader(shader)->unref();
    111                     paint.setAlpha(kAlphas[a]);
    112                     canvas->drawRect(kRect, paint);
    113                     canvas->translate(0, SkIntToScalar(kRect.height() + 20));
    114                 }
    115                 canvas->restore();
    116                 canvas->translate(SkIntToScalar(kRect.width() + 20), 0);
    117             }
    118         }
    119     }
    120 
    121 private:
    122     typedef GM INHERITED;
    123 };
    124 
    125 ///////////////////////////////////////////////////////////////////////////////
    126 
    127 struct ColorPos {
    128     SkColor*    fColors;
    129     SkScalar*   fPos;
    130     int         fCount;
    131 
    132     ColorPos() : fColors(NULL), fPos(NULL), fCount(0) {}
    133     ~ColorPos() {
    134         SkDELETE_ARRAY(fColors);
    135         SkDELETE_ARRAY(fPos);
    136     }
    137 
    138     void construct(const SkColor colors[], const SkScalar pos[], int count) {
    139         fColors = SkNEW_ARRAY(SkColor, count);
    140         memcpy(fColors, colors, count * sizeof(SkColor));
    141         if (pos) {
    142             fPos = SkNEW_ARRAY(SkScalar, count);
    143             memcpy(fPos, pos, count * sizeof(SkScalar));
    144             fPos[0] = 0;
    145             fPos[count - 1] = 1;
    146         }
    147         fCount = count;
    148     }
    149 };
    150 
    151 static void make0(ColorPos* rec) {
    152 #if 0
    153     From http://jsfiddle.net/3fe2a/
    154 
    155 background-image: -webkit-linear-gradient(left, #22d1cd 1%, #22d1cd 0.9510157507590116%, #df4b37 2.9510157507590113%, #df4b37 23.695886056604927%, #22d1cd 25.695886056604927%, #22d1cd 25.39321881940624%, #e6de36 27.39321881940624%, #e6de36 31.849399922570655%, #3267ff 33.849399922570655%, #3267ff 44.57735802921938%, #9d47d1 46.57735802921938%, #9d47d1 53.27185850805876%, #3267ff 55.27185850805876%, #3267ff 61.95718972227316%, #5cdd9d 63.95718972227316%, #5cdd9d 69.89166004442%, #3267ff 71.89166004442%, #3267ff 74.45795382765857%, #9d47d1 76.45795382765857%, #9d47d1 82.78364610713776%, #3267ff 84.78364610713776%, #3267ff 94.52743647737229%, #e3d082 96.52743647737229%, #e3d082 96.03934633331295%);
    156 height: 30px;
    157 #endif
    158 
    159     const SkColor colors[] = {
    160         0xFF22d1cd, 0xFF22d1cd, 0xFFdf4b37, 0xFFdf4b37, 0xFF22d1cd, 0xFF22d1cd, 0xFFe6de36, 0xFFe6de36,
    161         0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFF5cdd9d, 0xFF5cdd9d,
    162         0xFF3267ff, 0xFF3267ff, 0xFF9d47d1, 0xFF9d47d1, 0xFF3267ff, 0xFF3267ff, 0xFFe3d082, 0xFFe3d082
    163     };
    164     const double percent[] = {
    165         1, 0.9510157507590116, 2.9510157507590113, 23.695886056604927,
    166         25.695886056604927, 25.39321881940624, 27.39321881940624, 31.849399922570655,
    167         33.849399922570655, 44.57735802921938, 46.57735802921938, 53.27185850805876,
    168         55.27185850805876, 61.95718972227316, 63.95718972227316, 69.89166004442,
    169         71.89166004442, 74.45795382765857, 76.45795382765857, 82.78364610713776,
    170         84.78364610713776, 94.52743647737229, 96.52743647737229, 96.03934633331295,
    171     };
    172     const int N = SK_ARRAY_COUNT(percent);
    173     SkScalar pos[N];
    174     for (int i = 0; i < N; ++i) {
    175         pos[i] = SkDoubleToScalar(percent[i] / 100);
    176     }
    177     rec->construct(colors, pos, N);
    178 }
    179 
    180 static void make1(ColorPos* rec) {
    181     const SkColor colors[] = {
    182         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
    183         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
    184         SK_ColorBLACK,
    185     };
    186     rec->construct(colors, NULL, SK_ARRAY_COUNT(colors));
    187 }
    188 
    189 static void make2(ColorPos* rec) {
    190     const SkColor colors[] = {
    191         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
    192         SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE,
    193         SK_ColorBLACK,
    194     };
    195     const int N = SK_ARRAY_COUNT(colors);
    196     SkScalar pos[N];
    197     for (int i = 0; i < N; ++i) {
    198         pos[i] = SK_Scalar1 * i / (N - 1);
    199     }
    200     rec->construct(colors, pos, N);
    201 }
    202 
    203 class GradientsManyColorsGM : public GM {
    204     enum {
    205         W = 800,
    206     };
    207     SkAutoTUnref<SkShader> fShader;
    208 
    209     typedef void (*Proc)(ColorPos*);
    210 public:
    211     GradientsManyColorsGM() {}
    212 
    213 protected:
    214     virtual uint32_t onGetFlags() const SK_OVERRIDE {
    215         return kSkipTiled_Flag;
    216     }
    217 
    218     SkString onShortName() SK_OVERRIDE { return SkString("gradients_many"); }
    219     virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(850, 100); }
    220 
    221     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
    222         const Proc procs[] = {
    223             make0, make1, make2,
    224         };
    225         const SkPoint pts[] = {
    226             { 0, 0 },
    227             { SkIntToScalar(W), 0 },
    228         };
    229         const SkRect r = SkRect::MakeWH(SkIntToScalar(W), 30);
    230 
    231         SkPaint paint;
    232 
    233         canvas->translate(20, 20);
    234 
    235         for (int i = 0; i <= 8; ++i) {
    236             SkScalar x = r.width() * i / 8;
    237             canvas->drawLine(x, 0, x, 10000, paint);
    238         }
    239 
    240         for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
    241             ColorPos rec;
    242             procs[i](&rec);
    243             SkShader* s = SkGradientShader::CreateLinear(pts, rec.fColors, rec.fPos, rec.fCount,
    244                                                          SkShader::kClamp_TileMode);
    245             paint.setShader(s)->unref();
    246             canvas->drawRect(r, paint);
    247             canvas->translate(0, r.height() + 20);
    248         }
    249     }
    250 
    251 private:
    252     typedef GM INHERITED;
    253 };
    254 
    255 ///////////////////////////////////////////////////////////////////////////////
    256 
    257 DEF_GM( return SkNEW(GradientsNoTextureGM));
    258 DEF_GM( return SkNEW(GradientsManyColorsGM));
    259