gradients_no_texture.cpp 10 KB

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