1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
73d9005c0286f2dff8f3db030c4c1ad19371deebdreed
842309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com#include "gm.h"
933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h"
1042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com#include "SkGradientShader.h"
11bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita#include "SkLinearGradient.h"
1242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
1342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.comnamespace skiagm {
1442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
1542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.comstruct GradData {
16e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    int              fCount;
17e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    const SkColor*   fColors;
18e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    const SkColor4f* fColors4f;
19e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    const SkScalar*  fPos;
2042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
2142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
22dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkColor gColors[] = {
2342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
2442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
25e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanconstexpr SkColor4f gColors4f[] ={
26e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 1.0f, 0.0f, 0.0f, 1.0f }, // Red
27e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 1.0f, 0.0f, 1.0f }, // Green
28e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 0.0f, 1.0f, 1.0f }, // Blue
29e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 1.0f, 1.0f, 1.0f, 1.0f }, // White
30e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 0.0f, 0.0f, 1.0f }  // Black
31e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman};
32dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkScalar gPos0[] = { 0, SK_Scalar1 };
33dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
34dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkScalar gPos2[] = {
3542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
3642309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
3742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
38dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkScalar gPosClamp[]   = {0.0f, 0.0f, 1.0f, 1.0f};
39dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkColor  gColorClamp[] = {
408ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org    SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLUE
418ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org};
42e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanconstexpr SkColor4f gColor4fClamp[] ={
43e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 1.0f, 0.0f, 0.0f, 1.0f }, // Red
44e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 1.0f, 0.0f, 1.0f }, // Green
45e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 1.0f, 0.0f, 1.0f }, // Green
46e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 0.0f, 0.0f, 1.0f, 1.0f }  // Blue
47e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman};
48dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr GradData gGradData[] = {
49e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 2, gColors, gColors4f, nullptr },
50e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 2, gColors, gColors4f, gPos0 },
51e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 2, gColors, gColors4f, gPos1 },
52e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 5, gColors, gColors4f, nullptr },
53e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 5, gColors, gColors4f, gPos2 },
54e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    { 4, gColorClamp, gColor4fClamp, gPosClamp }
5542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
5642309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
571a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data,
581a9b9640843a64af8d9d90337ec3b3fea663196areed                                  SkShader::TileMode tm, const SkMatrix& localMatrix) {
591a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm, 0,
601a9b9640843a64af8d9d90337ec3b3fea663196areed                                        &localMatrix);
6142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com}
62f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com
63e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanstatic sk_sp<SkShader> MakeLinear4f(const SkPoint pts[2], const GradData& data,
64e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                    SkShader::TileMode tm, const SkMatrix& localMatrix) {
6577a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett    auto srgb = SkColorSpace::MakeSRGBLinear();
66e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    return SkGradientShader::MakeLinear(pts, data.fColors4f, srgb, data.fPos, data.fCount, tm, 0,
67e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                        &localMatrix);
68e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman}
69e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
701a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data,
711a9b9640843a64af8d9d90337ec3b3fea663196areed                                  SkShader::TileMode tm, const SkMatrix& localMatrix) {
7242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    SkPoint center;
7342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
7442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com               SkScalarAve(pts[0].fY, pts[1].fY));
751a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeRadial(center, center.fX, data.fColors, data.fPos, data.fCount,
761a9b9640843a64af8d9d90337ec3b3fea663196areed                                        tm, 0, &localMatrix);
7742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com}
7842309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
79e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanstatic sk_sp<SkShader> MakeRadial4f(const SkPoint pts[2], const GradData& data,
80e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                    SkShader::TileMode tm, const SkMatrix& localMatrix) {
81e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkPoint center;
82e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
83e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman               SkScalarAve(pts[0].fY, pts[1].fY));
8477a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett    auto srgb = SkColorSpace::MakeSRGBLinear();
85e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    return SkGradientShader::MakeRadial(center, center.fX, data.fColors4f, srgb, data.fPos,
86e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                        data.fCount, tm, 0, &localMatrix);
87e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman}
88e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
891a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data,
901a9b9640843a64af8d9d90337ec3b3fea663196areed                                 SkShader::TileMode, const SkMatrix& localMatrix) {
9142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    SkPoint center;
9242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
9342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com               SkScalarAve(pts[0].fY, pts[1].fY));
941a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount,
951a9b9640843a64af8d9d90337ec3b3fea663196areed                                       0, &localMatrix);
9642309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com}
9742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
98e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanstatic sk_sp<SkShader> MakeSweep4f(const SkPoint pts[2], const GradData& data,
99e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                   SkShader::TileMode, const SkMatrix& localMatrix) {
100e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkPoint center;
101e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
102e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman               SkScalarAve(pts[0].fY, pts[1].fY));
10377a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett    auto srgb = SkColorSpace::MakeSRGBLinear();
104e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors4f, srgb, data.fPos,
105e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                       data.fCount, 0, &localMatrix);
106e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman}
107e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
1081a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> Make2Radial(const SkPoint pts[2], const GradData& data,
1091a9b9640843a64af8d9d90337ec3b3fea663196areed                                   SkShader::TileMode tm, const SkMatrix& localMatrix) {
110f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com    SkPoint center0, center1;
111f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
112f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com                SkScalarAve(pts[0].fY, pts[1].fY));
113f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
114f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
1151a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
1161a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 center0, (pts[1].fX - pts[0].fX) / 2,
1171a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 data.fColors, data.fPos, data.fCount, tm,
1181a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 0, &localMatrix);
119f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com}
120f3c1cc906391f5cb5179ee49c7fcaba8f9e6e5ccreed@google.com
121e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanstatic sk_sp<SkShader> Make2Radial4f(const SkPoint pts[2], const GradData& data,
122e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                     SkShader::TileMode tm, const SkMatrix& localMatrix) {
123e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkPoint center0, center1;
124e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
125e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                SkScalarAve(pts[0].fY, pts[1].fY));
126e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3) / 5),
127e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1) / 4));
12877a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett    auto srgb = SkColorSpace::MakeSRGBLinear();
129e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
130e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                                 center0, (pts[1].fX - pts[0].fX) / 2,
131e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                                 data.fColors4f, srgb, data.fPos, data.fCount, tm,
132e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                                 0, &localMatrix);
133e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman}
134e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
1351a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data,
136e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                    SkShader::TileMode tm, const SkMatrix& localMatrix) {
1375cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    SkPoint center0, center1;
13880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
13980ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed    SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
1405cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
1415cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
1421a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeTwoPointConical(center1, radius1, center0, radius0,
1431a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 data.fColors, data.fPos,
1441a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 data.fCount, tm, 0, &localMatrix);
1455cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com}
1465cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com
147e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanstatic sk_sp<SkShader> Make2Conical4f(const SkPoint pts[2], const GradData& data,
148e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                      SkShader::TileMode tm, const SkMatrix& localMatrix) {
149e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkPoint center0, center1;
150e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
151e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
152e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
153e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
15477a7a1b57c16c97f056c1e50c03bdc954947778cMatt Sarett    auto srgb = SkColorSpace::MakeSRGBLinear();
155e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    return SkGradientShader::MakeTwoPointConical(center1, radius1, center0, radius0,
156e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                                 data.fColors4f, srgb, data.fPos,
157e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                                                 data.fCount, tm, 0, &localMatrix);
158e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman}
159e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
1601a9b9640843a64af8d9d90337ec3b3fea663196areedtypedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data,
1611a9b9640843a64af8d9d90337ec3b3fea663196areed                                     SkShader::TileMode tm, const SkMatrix& localMatrix);
162dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr GradMaker gGradMakers[] = {
1635cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical
16442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
165e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanconstexpr GradMaker gGradMakers4f[] ={
166e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    MakeLinear4f, MakeRadial4f, MakeSweep4f, Make2Radial4f, Make2Conical4f
167e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman};
16842309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
16942309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com///////////////////////////////////////////////////////////////////////////////
17042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
17142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.comclass GradientsGM : public GM {
17242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.compublic:
173063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    GradientsGM(bool dither) : fDither(dither) {
174eebe87f7a2bc3102a84750c498d2a33e9d23a952Matt Sarett        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
17548dd1a26ec07c5baa04856202e4e7e2a53e4d7e5bsalomon@google.com    }
176d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
17742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.comprotected:
178a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org
17942309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    SkString onShortName() {
180063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "gradients" : "gradients_nodither");
18142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    }
182d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1831da3a80d46f10b06d7fa4e90a355547f1572c65fedisonn@google.com    virtual SkISize onISize() { return SkISize::Make(840, 815); }
184d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
18542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    virtual void onDraw(SkCanvas* canvas) {
186d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
18742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        SkPoint pts[2] = {
18842309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            { 0, 0 },
189eebe87f7a2bc3102a84750c498d2a33e9d23a952Matt Sarett            { SkIntToScalar(100), SkIntToScalar(100) }
19042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        };
19142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        SkShader::TileMode tm = SkShader::kClamp_TileMode;
192eebe87f7a2bc3102a84750c498d2a33e9d23a952Matt Sarett        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
19342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        SkPaint paint;
19442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        paint.setAntiAlias(true);
195063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
196d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
19742309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
19842309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
19942309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            canvas->save();
20042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
2019c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                SkMatrix scale = SkMatrix::I();
2028ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org
2038ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org                if (i == 5) { // if the clamp case
2048ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org                    scale.setScale(0.5f, 0.5f);
2058ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org                    scale.postTranslate(25.f, 25.f);
2068ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org                }
207d55e357a8e276d1f1cd6231d57dda339a2beb76fskia.committer@gmail.com
2081a9b9640843a64af8d9d90337ec3b3fea663196areed                paint.setShader(gGradMakers[j](pts, gGradData[i], tm, scale));
20942309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com                canvas->drawRect(r, paint);
21042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com                canvas->translate(0, SkIntToScalar(120));
21142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            }
21242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            canvas->restore();
21342309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com            canvas->translate(SkIntToScalar(120), 0);
21442309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com        }
21542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    }
216d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
217063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaprotected:
218063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
219063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
22042309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.comprivate:
22142309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com    typedef GM INHERITED;
22242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com};
223063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsGM(true); )
224063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsGM(false); )
22542309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
226e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman// Like the original gradients GM, but using the SkColor4f shader factories. Should be identical.
227e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanclass Gradients4fGM : public GM {
228e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanpublic:
229e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    Gradients4fGM(bool dither) : fDither(dither) {
230e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
231e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    }
232e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
233e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanprotected:
234e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
235e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    SkString onShortName() {
236e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        return SkString(fDither ? "gradients4f" : "gradients4f_nodither");
237e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    }
238e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
239e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    virtual SkISize onISize() { return SkISize::Make(840, 815); }
240e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
241e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    virtual void onDraw(SkCanvas* canvas) {
242e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
243e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        SkPoint pts[2] ={
244e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            { 0, 0 },
245e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            { SkIntToScalar(100), SkIntToScalar(100) }
246e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        };
247e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        SkShader::TileMode tm = SkShader::kClamp_TileMode;
248e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        SkRect r ={ 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
249e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        SkPaint paint;
250e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        paint.setAntiAlias(true);
251e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        paint.setDither(fDither);
252e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
253e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
254e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
255e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            canvas->save();
256e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers4f); j++) {
257e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                SkMatrix scale = SkMatrix::I();
258e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
259e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                if (i == 5) { // if the clamp case
260e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                    scale.setScale(0.5f, 0.5f);
261e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                    scale.postTranslate(25.f, 25.f);
262e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                }
263e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
264e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                paint.setShader(gGradMakers4f[j](pts, gGradData[i], tm, scale));
265e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                canvas->drawRect(r, paint);
266e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman                canvas->translate(0, SkIntToScalar(120));
267e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            }
268e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            canvas->restore();
269e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman            canvas->translate(SkIntToScalar(120), 0);
270e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman        }
271e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    }
272e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
273e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanprotected:
274e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    bool fDither;
275e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
276e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanprivate:
277e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman    typedef GM INHERITED;
278e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman};
279e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanDEF_GM(return new Gradients4fGM(true); )
280e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosmanDEF_GM(return new Gradients4fGM(false); )
281e25d71ccbcdb47c7ee7bdf13235066092ae11af3brianosman
2825cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com// Based on the original gradient slide, but with perspective applied to the
2835cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com// gradient shaders' local matrices
2845cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comclass GradientsLocalPerspectiveGM : public GM {
2855cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.compublic:
286063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    GradientsLocalPerspectiveGM(bool dither) : fDither(dither) {
28765cdba6ba78aaec0c0a4596bb5941020c789482bcaryclark        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
2885cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    }
289d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2905cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comprotected:
291a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org
2925cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    SkString onShortName() {
293063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "gradients_local_perspective" :
294063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita                                  "gradients_local_perspective_nodither");
2955cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    }
296d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2971da3a80d46f10b06d7fa4e90a355547f1572c65fedisonn@google.com    virtual SkISize onISize() { return SkISize::Make(840, 815); }
298d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2995cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    virtual void onDraw(SkCanvas* canvas) {
300d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3015cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        SkPoint pts[2] = {
3025cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            { 0, 0 },
3035cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            { SkIntToScalar(100), SkIntToScalar(100) }
3045cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        };
3055cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        SkShader::TileMode tm = SkShader::kClamp_TileMode;
3065cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
3075cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        SkPaint paint;
3085cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        paint.setAntiAlias(true);
309063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
310d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3115cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
3125cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
3135cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            canvas->save();
3145cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
3155cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com                // apply an increasing y perspective as we move to the right
3165cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com                SkMatrix perspective;
3175cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com                perspective.setIdentity();
31880ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed                perspective.setPerspY(SkIntToScalar(i+1) / 500);
31980ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed                perspective.setSkewX(SkIntToScalar(i+1) / 10);
3208ba1ad3a0bc278988f8503e3ca5280898cb396a9commit-bot@chromium.org
3211a9b9640843a64af8d9d90337ec3b3fea663196areed                paint.setShader(gGradMakers[j](pts, gGradData[i], tm, perspective));
3225cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com                canvas->drawRect(r, paint);
3235cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com                canvas->translate(0, SkIntToScalar(120));
3245cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            }
3255cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            canvas->restore();
3265cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com            canvas->translate(SkIntToScalar(120), 0);
3275cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        }
3285cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    }
329d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3305cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comprivate:
331063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
332063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
3335cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    typedef GM INHERITED;
3345cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com};
335063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsLocalPerspectiveGM(true); )
336063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsLocalPerspectiveGM(false); )
3375cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com
3385cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com// Based on the original gradient slide, but with perspective applied to
3395cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com// the view matrix
3405cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comclass GradientsViewPerspectiveGM : public GradientsGM {
341063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitapublic:
342063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    GradientsViewPerspectiveGM(bool dither) : INHERITED(dither) { }
343063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
3445cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comprotected:
3455cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    SkString onShortName() {
346063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "gradients_view_perspective" :
347063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita                                  "gradients_view_perspective_nodither");
3485cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    }
349d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3501da3a80d46f10b06d7fa4e90a355547f1572c65fedisonn@google.com    virtual SkISize onISize() { return SkISize::Make(840, 500); }
351d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3525cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    virtual void onDraw(SkCanvas* canvas) {
3535cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        SkMatrix perspective;
3545cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        perspective.setIdentity();
35580ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        perspective.setPerspY(0.001f);
35680ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        perspective.setSkewX(SkIntToScalar(8) / 25);
357837d31a0c9351c4d65f5d703ff12db2c7cc5f6cdscroggo@google.com        canvas->concat(perspective);
3585cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com        INHERITED::onDraw(canvas);
3595cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    }
360d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3615cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.comprivate:
3625cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com    typedef GradientsGM INHERITED;
3635cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com};
364063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsViewPerspectiveGM(true); )
365063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsViewPerspectiveGM(false); )
3665cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com
367ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com/*
368ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com Inspired by this <canvas> javascript, where we need to detect that we are not
369ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com solving a quadratic equation, but must instead solve a linear (since our X^2
370ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com coefficient is 0)
371ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com
372ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com ctx.fillStyle = '#f00';
373ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com ctx.fillRect(0, 0, 100, 50);
374d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
375ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
376ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com g.addColorStop(0, '#f00');
377ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com g.addColorStop(0.01, '#0f0');
378ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com g.addColorStop(0.99, '#0f0');
379ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com g.addColorStop(1, '#f00');
380ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com ctx.fillStyle = g;
381ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com ctx.fillRect(0, 0, 100, 50);
382ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com */
383ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.comclass GradientsDegenrate2PointGM : public GM {
384ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.compublic:
385063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    GradientsDegenrate2PointGM(bool dither) : fDither(dither) {}
386d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
387ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.comprotected:
388ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    SkString onShortName() {
389063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "gradients_degenerate_2pt" : "gradients_degenerate_2pt_nodither");
390ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    }
391d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3921da3a80d46f10b06d7fa4e90a355547f1572c65fedisonn@google.com    virtual SkISize onISize() { return SkISize::Make(320, 320); }
393d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
394ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    void drawBG(SkCanvas* canvas) {
395ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com        canvas->drawColor(SK_ColorBLUE);
396ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    }
397d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
398ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    virtual void onDraw(SkCanvas* canvas) {
399ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com        this->drawBG(canvas);
400d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
401ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
4024b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        SkScalar pos[] = { 0, 0.01f, 0.99f, SK_Scalar1 };
40359f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        SkPoint c0;
40459f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        c0.iset(-80, 25);
40559f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        SkScalar r0 = SkIntToScalar(70);
40659f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        SkPoint c1;
40759f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        c1.iset(0, 25);
40859f3abf146bc40ccf923dbfe3797f87c13c20dd4epoger@google.com        SkScalar r1 = SkIntToScalar(150);
4099283d20afc27571f7a871d1bd1100dd5df584941reed        SkPaint paint;
4101a9b9640843a64af8d9d90337ec3b3fea663196areed        paint.setShader(SkGradientShader::MakeTwoPointConical(c0, r0, c1, r1, colors,
4111a9b9640843a64af8d9d90337ec3b3fea663196areed                                                              pos, SK_ARRAY_COUNT(pos),
4121a9b9640843a64af8d9d90337ec3b3fea663196areed                                                              SkShader::kClamp_TileMode));
413063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
414ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com        canvas->drawPaint(paint);
415ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    }
416d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
417ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.comprivate:
418063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
419063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
420ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com    typedef GM INHERITED;
421ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com};
422063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsDegenrate2PointGM(true); )
423063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new GradientsDegenrate2PointGM(false); )
424ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com
425cb10071171b1db9313bf47b25f0c8567c154f590caryclark/* bug.skia.org/517
426cb10071171b1db9313bf47b25f0c8567c154f590caryclark<canvas id="canvas"></canvas>
427cb10071171b1db9313bf47b25f0c8567c154f590caryclark<script>
428cb10071171b1db9313bf47b25f0c8567c154f590caryclarkvar c = document.getElementById("canvas");
429cb10071171b1db9313bf47b25f0c8567c154f590caryclarkvar ctx = c.getContext("2d");
430cb10071171b1db9313bf47b25f0c8567c154f590caryclarkctx.fillStyle = '#ff0';
431cb10071171b1db9313bf47b25f0c8567c154f590caryclarkctx.fillRect(0, 0, 100, 50);
432cb10071171b1db9313bf47b25f0c8567c154f590caryclark
433cb10071171b1db9313bf47b25f0c8567c154f590caryclarkvar g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
434cb10071171b1db9313bf47b25f0c8567c154f590caryclarkg.addColorStop(0, '#0f0');
435cb10071171b1db9313bf47b25f0c8567c154f590caryclarkg.addColorStop(0.003, '#f00');  // 0.004 makes this work
436cb10071171b1db9313bf47b25f0c8567c154f590caryclarkg.addColorStop(1, '#ff0');
437cb10071171b1db9313bf47b25f0c8567c154f590caryclarkctx.fillStyle = g;
438cb10071171b1db9313bf47b25f0c8567c154f590caryclarkctx.fillRect(0, 0, 100, 50);
439cb10071171b1db9313bf47b25f0c8567c154f590caryclark</script>
440cb10071171b1db9313bf47b25f0c8567c154f590caryclark*/
441cb10071171b1db9313bf47b25f0c8567c154f590caryclark
442cb10071171b1db9313bf47b25f0c8567c154f590caryclark// should draw only green
443cb10071171b1db9313bf47b25f0c8567c154f590caryclarkDEF_SIMPLE_GM(small_color_stop, canvas, 100, 150) {
444cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkColor colors[] = { SK_ColorGREEN, SK_ColorRED, SK_ColorYELLOW };
445cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkScalar pos[] = { 0, 0.003f, SK_Scalar1 };  // 0.004f makes this work
446cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkPoint c0 = { 200, 25 };
447cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkScalar r0 = 20;
448cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkPoint c1 = { 200, 25 };
449cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkScalar r1 = 10;
4501a9b9640843a64af8d9d90337ec3b3fea663196areed
451cb10071171b1db9313bf47b25f0c8567c154f590caryclark    SkPaint paint;
452cb10071171b1db9313bf47b25f0c8567c154f590caryclark    paint.setColor(SK_ColorYELLOW);
453cb10071171b1db9313bf47b25f0c8567c154f590caryclark    canvas->drawRect(SkRect::MakeWH(100, 150), paint);
4541a9b9640843a64af8d9d90337ec3b3fea663196areed    paint.setShader(SkGradientShader::MakeTwoPointConical(c0, r0, c1, r1, colors, pos,
4551a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          SK_ARRAY_COUNT(pos),
4561a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          SkShader::kClamp_TileMode));
457cb10071171b1db9313bf47b25f0c8567c154f590caryclark    canvas->drawRect(SkRect::MakeWH(100, 150), paint);
458cb10071171b1db9313bf47b25f0c8567c154f590caryclark}
459cb10071171b1db9313bf47b25f0c8567c154f590caryclark
460cb10071171b1db9313bf47b25f0c8567c154f590caryclark
4615ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com/// Tests correctness of *optimized* codepaths in gradients.
4625ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4635ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.comclass ClampedGradientsGM : public GM {
4645ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.compublic:
465063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    ClampedGradientsGM(bool dither) : fDither(dither) {}
4665ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4675ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.comprotected:
468063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    SkString onShortName() {
469063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "clamped_gradients" : "clamped_gradients_nodither");
470063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    }
4715ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4721da3a80d46f10b06d7fa4e90a355547f1572c65fedisonn@google.com    virtual SkISize onISize() { return SkISize::Make(640, 510); }
4735ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4745ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com    void drawBG(SkCanvas* canvas) {
475125960152dfd7f2aba4c2239131bdf75d9ac2705caryclark        canvas->drawColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
4765ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com    }
4775ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4785ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com    virtual void onDraw(SkCanvas* canvas) {
4795ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        this->drawBG(canvas);
4805ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4815ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
4825ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        SkPaint paint;
483063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
4845ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        paint.setAntiAlias(true);
4855ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4865ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        SkPoint center;
4875ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        center.iset(0, 300);
4885ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
4891a9b9640843a64af8d9d90337ec3b3fea663196areed        paint.setShader(SkGradientShader::MakeRadial(
4905ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com            SkPoint(center),
49196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            SkIntToScalar(200), gColors, nullptr, 5,
4921a9b9640843a64af8d9d90337ec3b3fea663196areed            SkShader::kClamp_TileMode));
4935ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com        canvas->drawRect(r, paint);
4945ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com    }
4955ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
4965ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.comprivate:
497063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
498063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
4995ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com    typedef GM INHERITED;
5005ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com};
501063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new ClampedGradientsGM(true); )
502063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new ClampedGradientsGM(false); )
5035ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
504b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com/// Checks quality of large radial gradients, which may display
505b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com/// some banding.
506b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com
507b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.comclass RadialGradientGM : public GM {
508b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.compublic:
509b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com    RadialGradientGM() {}
510b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com
511b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.comprotected:
512a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org
51336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override { return SkString("radial_gradient"); }
51436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(1280, 1280); }
515b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com    void drawBG(SkCanvas* canvas) {
516b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        canvas->drawColor(0xFF000000);
517b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com    }
51836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
519bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        const SkISize dim = this->getISize();
520bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com
521b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        this->drawBG(canvas);
522d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
523b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        SkPaint paint;
524b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        paint.setDither(true);
525b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        SkPoint center;
526bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        center.set(SkIntToScalar(dim.width())/2, SkIntToScalar(dim.height())/2);
527bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        SkScalar radius = SkIntToScalar(dim.width())/2;
528bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        const SkColor colors[] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
5294b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        const SkScalar pos[] = { 0.0f,
5304b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org                             0.35f,
5314b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org                             1.0f };
5321a9b9640843a64af8d9d90337ec3b3fea663196areed        paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, pos,
5331a9b9640843a64af8d9d90337ec3b3fea663196areed                                                     SK_ARRAY_COUNT(pos),
5341a9b9640843a64af8d9d90337ec3b3fea663196areed                                                     SkShader::kClamp_TileMode));
535bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        SkRect r = {
536bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com            0, 0, SkIntToScalar(dim.width()), SkIntToScalar(dim.height())
537bb0948fce2744e1009d9f388c9faad5cc6dc946creed@google.com        };
538b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com        canvas->drawRect(r, paint);
539b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com    }
540b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.comprivate:
541b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com    typedef GM INHERITED;
542b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com};
5433d9005c0286f2dff8f3db030c4c1ad19371deebdreedDEF_GM( return new RadialGradientGM; )
544b18e58c065cad6eb273ee23ef4d68a03791ef3aftomhudson@google.com
545361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.comclass RadialGradient2GM : public GM {
546361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.compublic:
547063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    RadialGradient2GM(bool dither) : fDither(dither) {}
548361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
549361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.comprotected:
550a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org
551063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    SkString onShortName() override {
552063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "radial_gradient2" : "radial_gradient2_nodither");
553063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    }
554063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
55536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override { return SkISize::Make(800, 400); }
556361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com    void drawBG(SkCanvas* canvas) {
557361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        canvas->drawColor(0xFF000000);
558361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com    }
559361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
560361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com    // Reproduces the example given in bug 7671058.
56136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
562361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        SkPaint paint1, paint2, paint3;
563361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        paint1.setStyle(SkPaint::kFill_Style);
564361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        paint2.setStyle(SkPaint::kFill_Style);
565361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        paint3.setStyle(SkPaint::kFill_Style);
566361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
567361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        const SkColor sweep_colors[] =
568361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com            { 0xFFFF0000, 0xFFFFFF00, 0xFF00FF00, 0xFF00FFFF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF0000 };
569361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        const SkColor colors1[] = { 0xFFFFFFFF, 0x00000000 };
570361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        const SkColor colors2[] = { 0xFF000000, 0x00000000 };
571361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
572361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        const SkScalar cx = 200, cy = 200, radius = 150;
573361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        SkPoint center;
574361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com        center.set(cx, cy);
575361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
5763ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com        // We can either interpolate endpoints and premultiply each point (default, more precision),
5773ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com        // or premultiply the endpoints first, avoiding the need to premultiply each point (cheap).
5783ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com        const uint32_t flags[] = { 0, SkGradientShader::kInterpolateColorsInPremul_Flag };
5793ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com
5803ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(flags); i++) {
5811a9b9640843a64af8d9d90337ec3b3fea663196areed            paint1.setShader(SkGradientShader::MakeSweep(cx, cy, sweep_colors,
5821a9b9640843a64af8d9d90337ec3b3fea663196areed                                                         nullptr, SK_ARRAY_COUNT(sweep_colors),
5831a9b9640843a64af8d9d90337ec3b3fea663196areed                                                         flags[i], nullptr));
5841a9b9640843a64af8d9d90337ec3b3fea663196areed            paint2.setShader(SkGradientShader::MakeRadial(center, radius, colors1,
5851a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          nullptr, SK_ARRAY_COUNT(colors1),
5861a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          SkShader::kClamp_TileMode,
5871a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          flags[i], nullptr));
5881a9b9640843a64af8d9d90337ec3b3fea663196areed            paint3.setShader(SkGradientShader::MakeRadial(center, radius, colors2,
5891a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          nullptr, SK_ARRAY_COUNT(colors2),
5901a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          SkShader::kClamp_TileMode,
5911a9b9640843a64af8d9d90337ec3b3fea663196areed                                                          flags[i], nullptr));
592063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita            paint1.setDither(fDither);
593063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita            paint2.setDither(fDither);
594063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita            paint3.setDither(fDither);
5953ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com
5963ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com            canvas->drawCircle(cx, cy, radius, paint1);
5973ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com            canvas->drawCircle(cx, cy, radius, paint3);
5983ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com            canvas->drawCircle(cx, cy, radius, paint2);
5993ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com
6003ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com            canvas->translate(400, 0);
6013ef7eeac9a2205285ca56d2d70e4d6740af556e6mtklein@google.com        }
602361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com    }
603361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
604361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.comprivate:
605063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
606063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
607361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com    typedef GM INHERITED;
608361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com};
609063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient2GM(true); )
610063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient2GM(false); )
6115ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
6123d9005c0286f2dff8f3db030c4c1ad19371deebdreed// Shallow radial (shows banding on raster)
6133d9005c0286f2dff8f3db030c4c1ad19371deebdreedclass RadialGradient3GM : public GM {
614063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitapublic:
615063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    RadialGradient3GM(bool dither) : fDither(dither) { }
61642309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com
6173d9005c0286f2dff8f3db030c4c1ad19371deebdreedprotected:
618063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    SkString onShortName() override {
619063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "radial_gradient3" : "radial_gradient3_nodither");
620063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    }
621ac864a945cb7e1be93717f209bf7eff2c4b6b2b5reed@google.com
6223d9005c0286f2dff8f3db030c4c1ad19371deebdreed    SkISize onISize() override { return SkISize::Make(500, 500); }
6235ea050f6620fa9e675a1c801f738e946fa993e14tomhudson@google.com
6243d9005c0286f2dff8f3db030c4c1ad19371deebdreed    bool runAsBench() const override { return true; }
6255cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com
6263d9005c0286f2dff8f3db030c4c1ad19371deebdreed    void onOnceBeforeDraw() override {
6273d9005c0286f2dff8f3db030c4c1ad19371deebdreed        const SkPoint center = { 0, 0 };
6283d9005c0286f2dff8f3db030c4c1ad19371deebdreed        const SkScalar kRadius = 3000;
6293d9005c0286f2dff8f3db030c4c1ad19371deebdreed        const SkColor gColors[] = { 0xFFFFFFFF, 0xFF000000 };
6301a9b9640843a64af8d9d90337ec3b3fea663196areed        fShader = SkGradientShader::MakeRadial(center, kRadius, gColors, nullptr, 2,
6311a9b9640843a64af8d9d90337ec3b3fea663196areed                                               SkShader::kClamp_TileMode);
6323d9005c0286f2dff8f3db030c4c1ad19371deebdreed    }
6335cf2c28427c1e8eaf464aaedddc1c9c73f2475aerileya@google.com
6343d9005c0286f2dff8f3db030c4c1ad19371deebdreed    void onDraw(SkCanvas* canvas) override {
6353d9005c0286f2dff8f3db030c4c1ad19371deebdreed        SkPaint paint;
6363d9005c0286f2dff8f3db030c4c1ad19371deebdreed        paint.setShader(fShader);
637063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
6383d9005c0286f2dff8f3db030c4c1ad19371deebdreed        canvas->drawRect(SkRect::MakeWH(500, 500), paint);
6393d9005c0286f2dff8f3db030c4c1ad19371deebdreed    }
6409d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
6413d9005c0286f2dff8f3db030c4c1ad19371deebdreedprivate:
6421a9b9640843a64af8d9d90337ec3b3fea663196areed    sk_sp<SkShader> fShader;
643063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
644063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
6453d9005c0286f2dff8f3db030c4c1ad19371deebdreed    typedef GM INHERITED;
6463d9005c0286f2dff8f3db030c4c1ad19371deebdreed};
647063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient3GM(true); )
648063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient3GM(false); )
649361a72fc4579ce04d112f2894eaa74139f6488c4mtklein@google.com
6501864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclarkclass RadialGradient4GM : public GM {
651063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitapublic:
652063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    RadialGradient4GM(bool dither) : fDither(dither) { }
6531864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark
6541864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclarkprotected:
655063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    SkString onShortName() override {
656063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "radial_gradient4" : "radial_gradient4_nodither");
657063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    }
6581864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark
6591864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    SkISize onISize() override { return SkISize::Make(500, 500); }
6601864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark
6611864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    void onOnceBeforeDraw() override {
6621864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        const SkPoint center = { 250, 250 };
6631864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        const SkScalar kRadius = 250;
6641864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        const SkColor colors[] = { SK_ColorRED, SK_ColorRED, SK_ColorWHITE, SK_ColorWHITE,
6651864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark                SK_ColorRED };
6661864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        const SkScalar pos[] = { 0, .4f, .4f, .8f, .8f, 1 };
6671a9b9640843a64af8d9d90337ec3b3fea663196areed        fShader = SkGradientShader::MakeRadial(center, kRadius, colors, pos,
6681a9b9640843a64af8d9d90337ec3b3fea663196areed                                               SK_ARRAY_COUNT(gColors), SkShader::kClamp_TileMode);
6691864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    }
6701864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark
6711864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    void onDraw(SkCanvas* canvas) override {
6721864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        SkPaint paint;
6731864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        paint.setAntiAlias(true);
674063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
6751864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        paint.setShader(fShader);
6761864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark        canvas->drawRect(SkRect::MakeWH(500, 500), paint);
6771864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    }
6789d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
6791864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclarkprivate:
6801a9b9640843a64af8d9d90337ec3b3fea663196areed    sk_sp<SkShader> fShader;
681063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
682063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
6831864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark    typedef GM INHERITED;
6841864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark};
685063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient4GM(true); )
686063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new RadialGradient4GM(false); )
6871864bfae63a008e84a29ca8b2b8c7b77ded8cf64caryclark
688159fa572c45cba98d32832c2b59f630063fbb201caryclarkclass LinearGradientGM : public GM {
689063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitapublic:
690063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    LinearGradientGM(bool dither) : fDither(dither) { }
691159fa572c45cba98d32832c2b59f630063fbb201caryclark
692159fa572c45cba98d32832c2b59f630063fbb201caryclarkprotected:
693063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    SkString onShortName() override {
694063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        return SkString(fDither ? "linear_gradient" : "linear_gradient_nodither");
695063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    }
696063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
697159fa572c45cba98d32832c2b59f630063fbb201caryclark    const SkScalar kWidthBump = 30.f;
698159fa572c45cba98d32832c2b59f630063fbb201caryclark    const SkScalar kHeight = 5.f;
699159fa572c45cba98d32832c2b59f630063fbb201caryclark    const SkScalar kMinWidth = 540.f;
700159fa572c45cba98d32832c2b59f630063fbb201caryclark
701159fa572c45cba98d32832c2b59f630063fbb201caryclark    SkISize onISize() override { return SkISize::Make(500, 500); }
702159fa572c45cba98d32832c2b59f630063fbb201caryclark
703159fa572c45cba98d32832c2b59f630063fbb201caryclark    void onOnceBeforeDraw() override {
704159fa572c45cba98d32832c2b59f630063fbb201caryclark        SkPoint pts[2] = { {0, 0}, {0, 0} };
705159fa572c45cba98d32832c2b59f630063fbb201caryclark        const SkColor colors[] = { SK_ColorWHITE, SK_ColorWHITE, 0xFF008200, 0xFF008200,
706159fa572c45cba98d32832c2b59f630063fbb201caryclark                SK_ColorWHITE, SK_ColorWHITE };
707159fa572c45cba98d32832c2b59f630063fbb201caryclark        const SkScalar unitPos[] = { 0, 50, 70, 500, 540 };
708159fa572c45cba98d32832c2b59f630063fbb201caryclark        SkScalar pos[6];
709159fa572c45cba98d32832c2b59f630063fbb201caryclark        pos[5] = 1;
710159fa572c45cba98d32832c2b59f630063fbb201caryclark        for (int index = 0; index < (int) SK_ARRAY_COUNT(fShader); ++index) {
711159fa572c45cba98d32832c2b59f630063fbb201caryclark            pts[1].fX = 500.f + index * kWidthBump;
712159fa572c45cba98d32832c2b59f630063fbb201caryclark            for (int inner = 0; inner < (int) SK_ARRAY_COUNT(unitPos); ++inner) {
713159fa572c45cba98d32832c2b59f630063fbb201caryclark                pos[inner] = unitPos[inner] / (kMinWidth + index * kWidthBump);
714159fa572c45cba98d32832c2b59f630063fbb201caryclark            }
7151a9b9640843a64af8d9d90337ec3b3fea663196areed            fShader[index] = SkGradientShader::MakeLinear(pts, colors, pos,
7161a9b9640843a64af8d9d90337ec3b3fea663196areed                    SK_ARRAY_COUNT(gColors), SkShader::kClamp_TileMode);
717159fa572c45cba98d32832c2b59f630063fbb201caryclark        }
718159fa572c45cba98d32832c2b59f630063fbb201caryclark    }
719159fa572c45cba98d32832c2b59f630063fbb201caryclark
720159fa572c45cba98d32832c2b59f630063fbb201caryclark    void onDraw(SkCanvas* canvas) override {
721159fa572c45cba98d32832c2b59f630063fbb201caryclark        SkPaint paint;
722159fa572c45cba98d32832c2b59f630063fbb201caryclark        paint.setAntiAlias(true);
723063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita        paint.setDither(fDither);
724159fa572c45cba98d32832c2b59f630063fbb201caryclark        for (int index = 0; index < (int) SK_ARRAY_COUNT(fShader); ++index) {
725159fa572c45cba98d32832c2b59f630063fbb201caryclark            paint.setShader(fShader[index]);
726159fa572c45cba98d32832c2b59f630063fbb201caryclark            canvas->drawRect(SkRect::MakeLTRB(0, index * kHeight, kMinWidth + index * kWidthBump,
727159fa572c45cba98d32832c2b59f630063fbb201caryclark                    (index + 1) * kHeight), paint);
728159fa572c45cba98d32832c2b59f630063fbb201caryclark        }
729159fa572c45cba98d32832c2b59f630063fbb201caryclark    }
7309d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
731159fa572c45cba98d32832c2b59f630063fbb201caryclarkprivate:
7321a9b9640843a64af8d9d90337ec3b3fea663196areed    sk_sp<SkShader> fShader[100];
733063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita    bool fDither;
734063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalita
735159fa572c45cba98d32832c2b59f630063fbb201caryclark    typedef GM INHERITED;
736159fa572c45cba98d32832c2b59f630063fbb201caryclark};
737063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new LinearGradientGM(true); )
738063675ba374cb520fe58bbcdaf5afeea0aa0ad60fmalitaDEF_GM( return new LinearGradientGM(false); )
739159fa572c45cba98d32832c2b59f630063fbb201caryclark
7408b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalitaclass LinearGradientTinyGM : public GM {
741bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitapublic:
742bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    LinearGradientTinyGM(uint32_t flags, const char* suffix = nullptr)
743bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    : fName("linear_gradient_tiny")
744bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    , fFlags(flags) {
745bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        fName.append(suffix);
746bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    }
747bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
7488b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalitaprotected:
7498b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    SkString onShortName() override {
750bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        return fName;
7518b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    }
7528b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
7538b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    SkISize onISize() override {
7548b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        return SkISize::Make(600, 500);
7558b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    }
7568b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
7578b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    void onDraw(SkCanvas* canvas) override {
7588b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        const SkScalar kRectSize = 100;
7598b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        const unsigned kStopCount = 3;
7608b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        const SkColor colors[kStopCount] = { SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN };
7618b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        const struct {
7628b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita            SkPoint pts[2];
7638b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita            SkScalar pos[kStopCount];
7648b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        } configs[] = {
765de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(10, 0) },       { 0, 0.999999f,    1 }},
766de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(10, 0) },       { 0, 0.000001f,    1 }},
767de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(10, 0) },       { 0, 0.999999999f, 1 }},
768de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(10, 0) },       { 0, 0.000000001f, 1 }},
769de3aac8cea8a7113f31591e6e02c51fe0ac45280reed
770de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0, 10) },       { 0, 0.999999f,    1 }},
771de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0, 10) },       { 0, 0.000001f,    1 }},
772de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0, 10) },       { 0, 0.999999999f, 1 }},
773de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0, 10) },       { 0, 0.000000001f, 1 }},
774de3aac8cea8a7113f31591e6e02c51fe0ac45280reed
775de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0.00001f, 0) }, { 0, 0.5f, 1 }},
776de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(9.99999f, 0), SkPoint::Make(10, 0) },       { 0, 0.5f, 1 }},
777de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 0),        SkPoint::Make(0, 0.00001f) }, { 0, 0.5f, 1 }},
778de3aac8cea8a7113f31591e6e02c51fe0ac45280reed            { { SkPoint::Make(0, 9.99999f), SkPoint::Make(0, 10) },       { 0, 0.5f, 1 }},
7798b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        };
7808b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
7818b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        SkPaint paint;
7828b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        for (unsigned i = 0; i < SK_ARRAY_COUNT(configs); ++i) {
7838b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita            SkAutoCanvasRestore acr(canvas, true);
7841a9b9640843a64af8d9d90337ec3b3fea663196areed            paint.setShader(SkGradientShader::MakeLinear(configs[i].pts, colors, configs[i].pos,
7851a9b9640843a64af8d9d90337ec3b3fea663196areed                                                         kStopCount, SkShader::kClamp_TileMode,
7861a9b9640843a64af8d9d90337ec3b3fea663196areed                                                         fFlags, nullptr));
7878b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita            canvas->translate(kRectSize * ((i % 4) * 1.5f + 0.25f),
7888b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita                              kRectSize * ((i / 4) * 1.5f + 0.25f));
7898b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
7908b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita            canvas->drawRect(SkRect::MakeWH(kRectSize, kRectSize), paint);
7918b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita        }
7928b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    }
7938b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
7948b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalitaprivate:
7958b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita    typedef GM INHERITED;
7968b78bd6d5b39fe8ef407c4b59b1be8421e58d665fmalita
797bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    SkString fName;
798bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    uint32_t fFlags;
799bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita};
800bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitaDEF_GM( return new LinearGradientTinyGM(0); )
801bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitaDEF_GM( return new LinearGradientTinyGM(SkLinearGradient::kForce4fContext_PrivateFlag, "_4f"); )
80242309d415e56f6fbeeea8239479d3f4ccf81a5acreed@android.com}
803d4eaa25cafc6b113015690c851d26f399640a0eareed
804d4eaa25cafc6b113015690c851d26f399640a0eareed///////////////////////////////////////////////////////////////////////////////////////////////////
805d4eaa25cafc6b113015690c851d26f399640a0eareed
806d4eaa25cafc6b113015690c851d26f399640a0eareedstruct GradRun {
807d4eaa25cafc6b113015690c851d26f399640a0eareed    SkColor  fColors[4];
808d4eaa25cafc6b113015690c851d26f399640a0eareed    SkScalar fPos[4];
809d4eaa25cafc6b113015690c851d26f399640a0eareed    int      fCount;
810d4eaa25cafc6b113015690c851d26f399640a0eareed};
811d4eaa25cafc6b113015690c851d26f399640a0eareed
812d4eaa25cafc6b113015690c851d26f399640a0eareed#define SIZE 121
813d4eaa25cafc6b113015690c851d26f399640a0eareed
8141a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> make_linear(const GradRun& run, SkShader::TileMode mode) {
815d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkPoint pts[] { { 30, 30 }, { SIZE - 30, SIZE - 30 } };
8161a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeLinear(pts, run.fColors, run.fPos, run.fCount, mode);
817d4eaa25cafc6b113015690c851d26f399640a0eareed}
818d4eaa25cafc6b113015690c851d26f399640a0eareed
8191a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> make_radial(const GradRun& run, SkShader::TileMode mode) {
820d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkScalar half = SIZE * 0.5f;
8211a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeRadial({half,half}, half - 10, run.fColors, run.fPos,
8221a9b9640843a64af8d9d90337ec3b3fea663196areed                                        run.fCount, mode);
823d4eaa25cafc6b113015690c851d26f399640a0eareed}
824d4eaa25cafc6b113015690c851d26f399640a0eareed
8251a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> make_conical(const GradRun& run, SkShader::TileMode mode) {
826d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkScalar half = SIZE * 0.5f;
827d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkPoint center { half, half };
8281a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeTwoPointConical(center, 20, center, half - 10,
8291a9b9640843a64af8d9d90337ec3b3fea663196areed                                                 run.fColors, run.fPos, run.fCount, mode);
830d4eaa25cafc6b113015690c851d26f399640a0eareed}
831d4eaa25cafc6b113015690c851d26f399640a0eareed
8321a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> make_sweep(const GradRun& run, SkShader::TileMode) {
833d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkScalar half = SIZE * 0.5f;
8341a9b9640843a64af8d9d90337ec3b3fea663196areed    return SkGradientShader::MakeSweep(half, half, run.fColors, run.fPos, run.fCount);
835d4eaa25cafc6b113015690c851d26f399640a0eareed}
836d4eaa25cafc6b113015690c851d26f399640a0eareed
837d4eaa25cafc6b113015690c851d26f399640a0eareed/*
838d4eaa25cafc6b113015690c851d26f399640a0eareed *  Exercise duplicate color-stops, at the ends, and in the middle
839d4eaa25cafc6b113015690c851d26f399640a0eareed *
840d4eaa25cafc6b113015690c851d26f399640a0eareed *  At the time of this writing, only Linear correctly deals with duplicates at the ends,
841d4eaa25cafc6b113015690c851d26f399640a0eareed *  and then only correctly on CPU backend.
842d4eaa25cafc6b113015690c851d26f399640a0eareed */
843d4eaa25cafc6b113015690c851d26f399640a0eareedDEF_SIMPLE_GM(gradients_dup_color_stops, canvas, 704, 564) {
844d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkColor preColor  = 0xFFFF0000;   // clamp color before start
845d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkColor postColor = 0xFF0000FF;   // clamp color after end
846d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkColor color0    = 0xFF000000;
847d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkColor color1    = 0xFF00FF00;
848d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkColor badColor  = 0xFF3388BB;   // should never be seen, fills out fixed-size array
849d4eaa25cafc6b113015690c851d26f399640a0eareed
850d4eaa25cafc6b113015690c851d26f399640a0eareed    const GradRun runs[] = {
851d4eaa25cafc6b113015690c851d26f399640a0eareed        {   { color0, color1, badColor, badColor },
852d4eaa25cafc6b113015690c851d26f399640a0eareed            { 0, 1, -1, -1 },
853d4eaa25cafc6b113015690c851d26f399640a0eareed            2,
854d4eaa25cafc6b113015690c851d26f399640a0eareed        },
855d4eaa25cafc6b113015690c851d26f399640a0eareed        {   { preColor, color0, color1, badColor },
856d4eaa25cafc6b113015690c851d26f399640a0eareed            { 0, 0, 1, -1 },
857d4eaa25cafc6b113015690c851d26f399640a0eareed            3,
858d4eaa25cafc6b113015690c851d26f399640a0eareed        },
859d4eaa25cafc6b113015690c851d26f399640a0eareed        {   { color0, color1, postColor, badColor },
860d4eaa25cafc6b113015690c851d26f399640a0eareed            { 0, 1, 1, -1 },
861d4eaa25cafc6b113015690c851d26f399640a0eareed            3,
862d4eaa25cafc6b113015690c851d26f399640a0eareed        },
863d4eaa25cafc6b113015690c851d26f399640a0eareed        {   { preColor, color0, color1, postColor },
864d4eaa25cafc6b113015690c851d26f399640a0eareed            { 0, 0, 1, 1 },
865d4eaa25cafc6b113015690c851d26f399640a0eareed            4,
866d4eaa25cafc6b113015690c851d26f399640a0eareed        },
867d4eaa25cafc6b113015690c851d26f399640a0eareed        {   { color0, color0, color1, color1 },
868d4eaa25cafc6b113015690c851d26f399640a0eareed            { 0, 0.5f, 0.5f, 1 },
869d4eaa25cafc6b113015690c851d26f399640a0eareed            4,
870d4eaa25cafc6b113015690c851d26f399640a0eareed        },
871d4eaa25cafc6b113015690c851d26f399640a0eareed    };
8721a9b9640843a64af8d9d90337ec3b3fea663196areed    sk_sp<SkShader> (*factories[])(const GradRun&, SkShader::TileMode) {
873d4eaa25cafc6b113015690c851d26f399640a0eareed        make_linear, make_radial, make_conical, make_sweep
874d4eaa25cafc6b113015690c851d26f399640a0eareed    };
875d4eaa25cafc6b113015690c851d26f399640a0eareed
876d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkRect rect = SkRect::MakeWH(SIZE, SIZE);
877d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkScalar dx = SIZE + 20;
878d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkScalar dy = SIZE + 20;
879d4eaa25cafc6b113015690c851d26f399640a0eareed    const SkShader::TileMode mode = SkShader::kClamp_TileMode;
880d4eaa25cafc6b113015690c851d26f399640a0eareed
881d4eaa25cafc6b113015690c851d26f399640a0eareed    SkPaint paint;
882d4eaa25cafc6b113015690c851d26f399640a0eareed    canvas->translate(10, 10 - dy);
883d4eaa25cafc6b113015690c851d26f399640a0eareed    for (auto factory : factories) {
884d4eaa25cafc6b113015690c851d26f399640a0eareed        canvas->translate(0, dy);
885d4eaa25cafc6b113015690c851d26f399640a0eareed        SkAutoCanvasRestore acr(canvas, true);
886d4eaa25cafc6b113015690c851d26f399640a0eareed        for (const auto& run : runs) {
8871a9b9640843a64af8d9d90337ec3b3fea663196areed            paint.setShader(factory(run, mode));
888d4eaa25cafc6b113015690c851d26f399640a0eareed            canvas->drawRect(rect, paint);
889d4eaa25cafc6b113015690c851d26f399640a0eareed            canvas->translate(dx, 0);
890d4eaa25cafc6b113015690c851d26f399640a0eareed        }
891d4eaa25cafc6b113015690c851d26f399640a0eareed    }
892d4eaa25cafc6b113015690c851d26f399640a0eareed}
893bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
894bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitastatic void draw_many_stops(SkCanvas* canvas, uint32_t flags) {
895bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    const unsigned kStopCount = 200;
896bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    const SkPoint pts[] = { {50, 50}, {450, 465}};
897bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
898bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    SkColor colors[kStopCount];
899bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    for (unsigned i = 0; i < kStopCount; i++) {
900bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        switch (i % 5) {
901bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        case 0: colors[i] = SK_ColorRED; break;
902bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        case 1: colors[i] = SK_ColorGREEN; break;
903bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        case 2: colors[i] = SK_ColorGREEN; break;
904bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        case 3: colors[i] = SK_ColorBLUE; break;
905bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        case 4: colors[i] = SK_ColorRED; break;
906bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita        }
907bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    }
908bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
9099283d20afc27571f7a871d1bd1100dd5df584941reed    SkPaint p;
9101a9b9640843a64af8d9d90337ec3b3fea663196areed    p.setShader(SkGradientShader::MakeLinear(
9111a9b9640843a64af8d9d90337ec3b3fea663196areed        pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode, flags, nullptr));
9129283d20afc27571f7a871d1bd1100dd5df584941reed
913bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    canvas->drawRect(SkRect::MakeXYWH(0, 0, 500, 500), p);
914bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita}
915bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
916bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitaDEF_SIMPLE_GM(gradient_many_stops, canvas, 500, 500) {
917bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    draw_many_stops(canvas, 0);
918bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita}
919bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita
920bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalitaDEF_SIMPLE_GM(gradient_many_stops_4f, canvas, 500, 500) {
921bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita    draw_many_stops(canvas, SkLinearGradient::kForce4fContext_PrivateFlag);
922bc590c01b00ef79e1e1f30058e7a70a29419f2a9fmalita}
923afac581523af9de5e0af0af1dc128cac1b846006fmalita
924afac581523af9de5e0af0af1dc128cac1b846006fmalitastatic void draw_subpixel_gradient(SkCanvas* canvas, uint32_t flags) {
925afac581523af9de5e0af0af1dc128cac1b846006fmalita    const SkPoint pts[] = { {50, 50}, {50.1f, 50.1f}};
926afac581523af9de5e0af0af1dc128cac1b846006fmalita    SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
927afac581523af9de5e0af0af1dc128cac1b846006fmalita    SkPaint p;
928afac581523af9de5e0af0af1dc128cac1b846006fmalita    p.setShader(SkGradientShader::MakeLinear(
929afac581523af9de5e0af0af1dc128cac1b846006fmalita        pts, colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kRepeat_TileMode, flags, nullptr));
930afac581523af9de5e0af0af1dc128cac1b846006fmalita    canvas->drawRect(SkRect::MakeXYWH(0, 0, 500, 500), p);
931afac581523af9de5e0af0af1dc128cac1b846006fmalita}
932afac581523af9de5e0af0af1dc128cac1b846006fmalita
933afac581523af9de5e0af0af1dc128cac1b846006fmalitaDEF_SIMPLE_GM(gradient_subpixel, canvas, 500, 500) {
934afac581523af9de5e0af0af1dc128cac1b846006fmalita    draw_subpixel_gradient(canvas, 0);
935afac581523af9de5e0af0af1dc128cac1b846006fmalita}
936afac581523af9de5e0af0af1dc128cac1b846006fmalita
937afac581523af9de5e0af0af1dc128cac1b846006fmalitaDEF_SIMPLE_GM(gradient_subpixel_4f, canvas, 500, 500) {
938afac581523af9de5e0af0af1dc128cac1b846006fmalita    draw_subpixel_gradient(canvas, SkLinearGradient::kForce4fContext_PrivateFlag);
939afac581523af9de5e0af0af1dc128cac1b846006fmalita}
940