gradients_no_texture.cpp revision ee0cac336c6a3a357ae3cb18be8ef4b3cb5edddb
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 10using namespace skiagm; 11 12struct GradData { 13 int fCount; 14 const SkColor* fColors; 15 const SkScalar* fPos; 16}; 17 18static const SkColor gColors[] = { 19 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, 20}; 21 22static const GradData gGradData[] = { 23 { 1, gColors, NULL }, 24 { 2, gColors, NULL }, 25 { 3, gColors, NULL }, 26 { 4, gColors, NULL }, 27}; 28 29static 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 33static 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 41static 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 48static 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 60static 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 73typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm); 74 75static const GradMaker gGradMakers[] = { 76 MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical, 77}; 78 79/////////////////////////////////////////////////////////////////////////////// 80 81class GradientsNoTextureGM : public GM { 82public: 83 GradientsNoTextureGM() { 84 this->setBGColor(0xFFDDDDDD); 85 } 86 87protected: 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 make_isize(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 121private: 122 typedef GM INHERITED; 123}; 124 125/////////////////////////////////////////////////////////////////////////////// 126 127struct 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 151static void make0(ColorPos* rec) { 152#if 0 153 From http://jsfiddle.net/3fe2a/ 154 155background-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%); 156height: 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 180static 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 189static 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 203class GradientsManyColorsGM : public GM { 204 enum { 205 W = 800, 206 }; 207 SkAutoTUnref<SkShader> fShader; 208 209 typedef void (*Proc)(ColorPos*); 210public: 211 GradientsManyColorsGM() {} 212 213protected: 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 251private: 252 typedef GM INHERITED; 253}; 254 255/////////////////////////////////////////////////////////////////////////////// 256 257DEF_GM( return SkNEW(GradientsNoTextureGM)); 258DEF_GM( return SkNEW(GradientsManyColorsGM)); 259