1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker struct GradData {
27*c8dee2aaSAndroid Build Coastguard Worker int fCount;
28*c8dee2aaSAndroid Build Coastguard Worker const SkColor* fColors;
29*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fPos;
30*c8dee2aaSAndroid Build Coastguard Worker };
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor gColors[] = {
33*c8dee2aaSAndroid Build Coastguard Worker SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
34*c8dee2aaSAndroid Build Coastguard Worker };
35*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar gPos0[] = { 0, SK_Scalar1 };
36*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
37*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar gPos2[] = {
38*c8dee2aaSAndroid Build Coastguard Worker 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
39*c8dee2aaSAndroid Build Coastguard Worker };
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar gPosClamp[] = {0.0f, 0.0f, 1.0f, 1.0f};
42*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor gColorClamp[] = {
43*c8dee2aaSAndroid Build Coastguard Worker SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLUE
44*c8dee2aaSAndroid Build Coastguard Worker };
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker constexpr GradData gGradData[] = {
47*c8dee2aaSAndroid Build Coastguard Worker { 2, gColors, gPos0 },
48*c8dee2aaSAndroid Build Coastguard Worker { 2, gColors, gPos1 },
49*c8dee2aaSAndroid Build Coastguard Worker { 5, gColors, gPos2 },
50*c8dee2aaSAndroid Build Coastguard Worker { 4, gColorClamp, gPosClamp }
51*c8dee2aaSAndroid Build Coastguard Worker };
52*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalOutside(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)53*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalOutside(const SkPoint pts[2], const GradData& data,
54*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
55*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
56*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
57*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
58*c8dee2aaSAndroid Build Coastguard Worker center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
59*c8dee2aaSAndroid Build Coastguard Worker center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
60*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
61*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalOutsideStrip(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)64*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalOutsideStrip(const SkPoint pts[2], const GradData& data,
65*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
66*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
67*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius = (pts[1].fX - pts[0].fX) / 3;
68*c8dee2aaSAndroid Build Coastguard Worker center0.set(pts[0].fX, pts[0].fY);
69*c8dee2aaSAndroid Build Coastguard Worker center1.set(pts[1].fX, pts[1].fY);
70*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius, center1, radius, data.fColors,
71*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalOutsideFlip(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)74*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalOutsideFlip(const SkPoint pts[2], const GradData& data,
75*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
76*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
77*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 10;
78*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
79*c8dee2aaSAndroid Build Coastguard Worker center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
80*c8dee2aaSAndroid Build Coastguard Worker center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
81*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center1, radius1, center0, radius0, data.fColors,
82*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalInside(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)85*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalInside(const SkPoint pts[2], const GradData& data,
86*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
87*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
88*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
89*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
90*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
91*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
92*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
93*c8dee2aaSAndroid Build Coastguard Worker center0, (pts[1].fX - pts[0].fX) / 2,
94*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
95*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalInsideFlip(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)98*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalInsideFlip(const SkPoint pts[2], const GradData& data,
99*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
100*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
101*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
102*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
103*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
104*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
105*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2,
106*c8dee2aaSAndroid Build Coastguard Worker center1, (pts[1].fX - pts[0].fX) / 7,
107*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
108*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalInsideCenter(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)111*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalInsideCenter(const SkPoint pts[2], const GradData& data,
112*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
113*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0;
114*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
115*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
116*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 7,
117*c8dee2aaSAndroid Build Coastguard Worker center0, (pts[1].fX - pts[0].fX) / 2,
118*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
119*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalInsideCenterReversed(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)122*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalInsideCenterReversed(const SkPoint pts[2], const GradData& data,
123*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
124*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0;
125*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
126*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
127*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2,
128*c8dee2aaSAndroid Build Coastguard Worker center0, (pts[1].fX - pts[0].fX) / 7,
129*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
130*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRad(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)133*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRad(const SkPoint pts[2], const GradData& data,
134*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
135*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
136*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
137*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
138*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
139*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
140*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center1, 0.f,
141*c8dee2aaSAndroid Build Coastguard Worker center0, (pts[1].fX - pts[0].fX) / 2,
142*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
143*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadFlip(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)146*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadFlip(const SkPoint pts[2], const GradData& data,
147*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
148*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
149*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
150*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
151*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
152*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
153*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 2,
154*c8dee2aaSAndroid Build Coastguard Worker center0, 0.f,
155*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
156*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadCenter(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)159*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadCenter(const SkPoint pts[2], const GradData& data,
160*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
161*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
162*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
163*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
164*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
165*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
166*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, 0.f, center0, (pts[1].fX - pts[0].fX) / 2,
167*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
168*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadOutside(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)171*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadOutside(const SkPoint pts[2], const GradData& data,
172*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm,
173*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& localMatrix) {
174*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
175*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = 0.f;
176*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
177*c8dee2aaSAndroid Build Coastguard Worker center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
178*c8dee2aaSAndroid Build Coastguard Worker center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
179*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1,
180*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos,
181*c8dee2aaSAndroid Build Coastguard Worker data.fCount, tm, 0, &localMatrix);
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadFlipOutside(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)184*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadFlipOutside(const SkPoint pts[2], const GradData& data,
185*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm,
186*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& localMatrix) {
187*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
188*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = 0.f;
189*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
190*c8dee2aaSAndroid Build Coastguard Worker center0.set(pts[0].fX + radius0, pts[0].fY + radius0);
191*c8dee2aaSAndroid Build Coastguard Worker center1.set(pts[1].fX - radius1, pts[1].fY - radius1);
192*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center1, radius1, center0, radius0, data.fColors,
193*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
194*c8dee2aaSAndroid Build Coastguard Worker }
195*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalEdgeX(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)196*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalEdgeX(const SkPoint pts[2], const GradData& data,
197*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
198*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
199*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 7;
200*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
201*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
202*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
203*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX + radius1, center1.fY);
204*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
205*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalEdgeY(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)208*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalEdgeY(const SkPoint pts[2], const GradData& data,
209*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
210*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
211*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 7;
212*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
213*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
214*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
215*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX, center1.fY + radius1);
216*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
217*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadEdgeX(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)220*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadEdgeX(const SkPoint pts[2], const GradData& data,
221*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm,
222*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& localMatrix) {
223*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
224*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = 0.f;
225*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
226*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
227*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
228*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX + radius1, center1.fY);
229*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
230*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalZeroRadEdgeY(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)233*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalZeroRadEdgeY(const SkPoint pts[2], const GradData& data,
234*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
235*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
236*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = 0.f;
237*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
238*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
239*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
240*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX, center1.fY + radius1);
241*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
242*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalTouchX(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)245*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalTouchX(const SkPoint pts[2], const GradData& data,
246*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
247*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
248*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 7;
249*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
250*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
251*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
252*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX - radius1 + radius0, center1.fY);
253*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
254*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
255*c8dee2aaSAndroid Build Coastguard Worker }
256*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalTouchY(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)257*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalTouchY(const SkPoint pts[2], const GradData& data,
258*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
259*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
260*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius0 = (pts[1].fX - pts[0].fX) / 7;
261*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius1 = (pts[1].fX - pts[0].fX) / 3;
262*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarAve(pts[0].fX, pts[1].fX),
263*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
264*c8dee2aaSAndroid Build Coastguard Worker center0.set(center1.fX, center1.fY + radius1 - radius0);
265*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, radius0, center1, radius1, data.fColors,
266*c8dee2aaSAndroid Build Coastguard Worker data.fPos, data.fCount, tm, 0, &localMatrix);
267*c8dee2aaSAndroid Build Coastguard Worker }
268*c8dee2aaSAndroid Build Coastguard Worker
Make2ConicalInsideSmallRad(const SkPoint pts[2],const GradData & data,SkTileMode tm,const SkMatrix & localMatrix)269*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> Make2ConicalInsideSmallRad(const SkPoint pts[2], const GradData& data,
270*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix) {
271*c8dee2aaSAndroid Build Coastguard Worker SkPoint center0, center1;
272*c8dee2aaSAndroid Build Coastguard Worker center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
273*c8dee2aaSAndroid Build Coastguard Worker SkScalarAve(pts[0].fY, pts[1].fY));
274*c8dee2aaSAndroid Build Coastguard Worker center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
275*c8dee2aaSAndroid Build Coastguard Worker SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
276*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeTwoPointConical(center0, 0.0000000000000000001f,
277*c8dee2aaSAndroid Build Coastguard Worker center0, (pts[1].fX - pts[0].fX) / 2,
278*c8dee2aaSAndroid Build Coastguard Worker data.fColors, data.fPos, data.fCount, tm,
279*c8dee2aaSAndroid Build Coastguard Worker 0, &localMatrix);
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data,
283*c8dee2aaSAndroid Build Coastguard Worker SkTileMode tm, const SkMatrix& localMatrix);
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker constexpr GradMaker gGradMakersOutside[] = {
286*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalOutside, Make2ConicalOutsideFlip,
287*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalZeroRadOutside, Make2ConicalZeroRadFlipOutside,
288*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalOutsideStrip
289*c8dee2aaSAndroid Build Coastguard Worker };
290*c8dee2aaSAndroid Build Coastguard Worker
291*c8dee2aaSAndroid Build Coastguard Worker constexpr GradMaker gGradMakersInside[] = {
292*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalInside, Make2ConicalInsideFlip, Make2ConicalInsideCenter,
293*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalZeroRad, Make2ConicalZeroRadFlip, Make2ConicalZeroRadCenter,
294*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalInsideCenterReversed
295*c8dee2aaSAndroid Build Coastguard Worker };
296*c8dee2aaSAndroid Build Coastguard Worker
297*c8dee2aaSAndroid Build Coastguard Worker constexpr GradMaker gGradMakersEdgeCases[] = {
298*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalEdgeX, Make2ConicalEdgeY,
299*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalZeroRadEdgeX, Make2ConicalZeroRadEdgeY,
300*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalTouchX, Make2ConicalTouchY,
301*c8dee2aaSAndroid Build Coastguard Worker Make2ConicalInsideSmallRad
302*c8dee2aaSAndroid Build Coastguard Worker };
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker
305*c8dee2aaSAndroid Build Coastguard Worker constexpr struct {
306*c8dee2aaSAndroid Build Coastguard Worker const GradMaker* fMaker;
307*c8dee2aaSAndroid Build Coastguard Worker const int fCount;
308*c8dee2aaSAndroid Build Coastguard Worker const char* fName;
309*c8dee2aaSAndroid Build Coastguard Worker } gGradCases[] = {
310*c8dee2aaSAndroid Build Coastguard Worker { gGradMakersOutside, std::size(gGradMakersOutside), "outside" },
311*c8dee2aaSAndroid Build Coastguard Worker { gGradMakersInside, std::size(gGradMakersInside), "inside" },
312*c8dee2aaSAndroid Build Coastguard Worker { gGradMakersEdgeCases, std::size(gGradMakersEdgeCases), "edge" },
313*c8dee2aaSAndroid Build Coastguard Worker };
314*c8dee2aaSAndroid Build Coastguard Worker
315*c8dee2aaSAndroid Build Coastguard Worker enum GradCaseType { // these must match the order in gGradCases
316*c8dee2aaSAndroid Build Coastguard Worker kOutside_GradCaseType,
317*c8dee2aaSAndroid Build Coastguard Worker kInside_GradCaseType,
318*c8dee2aaSAndroid Build Coastguard Worker kEdge_GradCaseType,
319*c8dee2aaSAndroid Build Coastguard Worker };
320*c8dee2aaSAndroid Build Coastguard Worker
321*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker class ConicalGradientsGM : public GM {
324*c8dee2aaSAndroid Build Coastguard Worker public:
ConicalGradientsGM(GradCaseType gradCaseType,bool dither,SkTileMode mode=SkTileMode::kClamp)325*c8dee2aaSAndroid Build Coastguard Worker ConicalGradientsGM(GradCaseType gradCaseType, bool dither,
326*c8dee2aaSAndroid Build Coastguard Worker SkTileMode mode = SkTileMode::kClamp)
327*c8dee2aaSAndroid Build Coastguard Worker : fGradCaseType(gradCaseType)
328*c8dee2aaSAndroid Build Coastguard Worker , fDither(dither)
329*c8dee2aaSAndroid Build Coastguard Worker , fMode(mode) {
330*c8dee2aaSAndroid Build Coastguard Worker fName.printf("gradients_2pt_conical_%s%s", gGradCases[gradCaseType].fName,
331*c8dee2aaSAndroid Build Coastguard Worker fDither ? "" : "_nodither");
332*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
333*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kRepeat:
334*c8dee2aaSAndroid Build Coastguard Worker fName.appendf("_repeat");
335*c8dee2aaSAndroid Build Coastguard Worker break;
336*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kMirror:
337*c8dee2aaSAndroid Build Coastguard Worker fName.appendf("_mirror");
338*c8dee2aaSAndroid Build Coastguard Worker break;
339*c8dee2aaSAndroid Build Coastguard Worker default:
340*c8dee2aaSAndroid Build Coastguard Worker break;
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker
344*c8dee2aaSAndroid Build Coastguard Worker private:
onOnceBeforeDraw()345*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { this->setBGColor(0xFFDDDDDD); }
346*c8dee2aaSAndroid Build Coastguard Worker
getName() const347*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return fName; }
348*c8dee2aaSAndroid Build Coastguard Worker
getISize()349*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return {840, 815}; }
350*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)351*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
352*c8dee2aaSAndroid Build Coastguard Worker
353*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[2] = {
354*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 },
355*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(100), SkIntToScalar(100) }
356*c8dee2aaSAndroid Build Coastguard Worker };
357*c8dee2aaSAndroid Build Coastguard Worker SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
358*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
359*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
360*c8dee2aaSAndroid Build Coastguard Worker paint.setDither(fDither);
361*c8dee2aaSAndroid Build Coastguard Worker
362*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
363*c8dee2aaSAndroid Build Coastguard Worker
364*c8dee2aaSAndroid Build Coastguard Worker const GradMaker* gradMaker = gGradCases[fGradCaseType].fMaker;
365*c8dee2aaSAndroid Build Coastguard Worker const int count = gGradCases[fGradCaseType].fCount;
366*c8dee2aaSAndroid Build Coastguard Worker
367*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(gGradData); i++) {
368*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
369*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < count; j++) {
370*c8dee2aaSAndroid Build Coastguard Worker SkMatrix scale = SkMatrix::I();
371*c8dee2aaSAndroid Build Coastguard Worker
372*c8dee2aaSAndroid Build Coastguard Worker if (i == 3) { // if the clamp case
373*c8dee2aaSAndroid Build Coastguard Worker scale.setScale(0.5f, 0.5f);
374*c8dee2aaSAndroid Build Coastguard Worker scale.postTranslate(25.f, 25.f);
375*c8dee2aaSAndroid Build Coastguard Worker }
376*c8dee2aaSAndroid Build Coastguard Worker
377*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(gradMaker[j](pts, gGradData[i], fMode, scale));
378*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
379*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, SkIntToScalar(120));
380*c8dee2aaSAndroid Build Coastguard Worker }
381*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
382*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(SkIntToScalar(120), 0);
383*c8dee2aaSAndroid Build Coastguard Worker }
384*c8dee2aaSAndroid Build Coastguard Worker }
385*c8dee2aaSAndroid Build Coastguard Worker
386*c8dee2aaSAndroid Build Coastguard Worker private:
387*c8dee2aaSAndroid Build Coastguard Worker GradCaseType fGradCaseType;
388*c8dee2aaSAndroid Build Coastguard Worker SkString fName;
389*c8dee2aaSAndroid Build Coastguard Worker bool fDither;
390*c8dee2aaSAndroid Build Coastguard Worker SkTileMode fMode;
391*c8dee2aaSAndroid Build Coastguard Worker };
392*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
393*c8dee2aaSAndroid Build Coastguard Worker
394*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kInside_GradCaseType, true); )
395*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kOutside_GradCaseType, true); )
396*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kEdge_GradCaseType, true); )
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kInside_GradCaseType, true, SkTileMode::kRepeat); )
399*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kOutside_GradCaseType, true, SkTileMode::kRepeat); )
400*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kEdge_GradCaseType, true, SkTileMode::kRepeat); )
401*c8dee2aaSAndroid Build Coastguard Worker
402*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kInside_GradCaseType, true, SkTileMode::kMirror); )
403*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kOutside_GradCaseType, true, SkTileMode::kMirror); )
404*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kEdge_GradCaseType, true, SkTileMode::kMirror); )
405*c8dee2aaSAndroid Build Coastguard Worker
406*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kInside_GradCaseType, false); )
407*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kOutside_GradCaseType, false); )
408*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ConicalGradientsGM(kEdge_GradCaseType, false); )
409*c8dee2aaSAndroid Build Coastguard Worker
410*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
411