xref: /aosp_15_r20/external/skia/gm/gradient_matrix.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2013 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/SkTileMode.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor gColors[] = {
23*c8dee2aaSAndroid Build Coastguard Worker     SK_ColorRED, SK_ColorYELLOW
24*c8dee2aaSAndroid Build Coastguard Worker };
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker // These annoying defines are necessary, because the only other alternative
27*c8dee2aaSAndroid Build Coastguard Worker // is to use SkIntToScalar(...) everywhere.
28*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar sZero = 0;
29*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar sHalf = SK_ScalarHalf;
30*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar sOne = SK_Scalar1;
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker // These arrays define the gradient stop points
33*c8dee2aaSAndroid Build Coastguard Worker // as x1, y1, x2, y2 per gradient to draw.
34*c8dee2aaSAndroid Build Coastguard Worker constexpr SkPoint linearPts[][2] = {
35*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sZero}, {sOne,  sZero}},
36*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sZero}, {sZero, sOne}},
37*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sZero}, {sZero, sZero}},
38*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sOne},  {sZero, sZero}},
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sZero}, {sOne,  sOne}},
41*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sOne},  {sZero, sZero}},
42*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sZero}, {sZero, sOne}},
43*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sOne},  {sOne,  sZero}}
44*c8dee2aaSAndroid Build Coastguard Worker };
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker constexpr SkPoint radialPts[][2] = {
47*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sHalf}, {sOne,  sHalf}},
48*c8dee2aaSAndroid Build Coastguard Worker     {{sHalf, sZero}, {sHalf, sOne}},
49*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sHalf}, {sZero, sHalf}},
50*c8dee2aaSAndroid Build Coastguard Worker     {{sHalf, sOne},  {sHalf, sZero}},
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sZero}, {sOne,  sOne}},
53*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sOne},  {sZero, sZero}},
54*c8dee2aaSAndroid Build Coastguard Worker     {{sOne,  sZero}, {sZero, sOne}},
55*c8dee2aaSAndroid Build Coastguard Worker     {{sZero, sOne},  {sOne,  sZero}}
56*c8dee2aaSAndroid Build Coastguard Worker };
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker // These define the pixels allocated to each gradient image.
59*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar TESTGRID_X = SkIntToScalar(200);
60*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar TESTGRID_Y = SkIntToScalar(200);
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker constexpr int IMAGES_X = 4;             // number of images per row
63*c8dee2aaSAndroid Build Coastguard Worker 
make_linear_gradient(const SkPoint pts[2],const SkMatrix & localMatrix)64*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_linear_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
65*c8dee2aaSAndroid Build Coastguard Worker     return SkGradientShader::MakeLinear(pts, gColors, nullptr, std::size(gColors),
66*c8dee2aaSAndroid Build Coastguard Worker                                         SkTileMode::kClamp, 0, &localMatrix);
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker 
make_radial_gradient(const SkPoint pts[2],const SkMatrix & localMatrix)69*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
70*c8dee2aaSAndroid Build Coastguard Worker     SkPoint center;
71*c8dee2aaSAndroid Build Coastguard Worker     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
72*c8dee2aaSAndroid Build Coastguard Worker                SkScalarAve(pts[0].fY, pts[1].fY));
73*c8dee2aaSAndroid Build Coastguard Worker     float radius = (center - pts[0]).length();
74*c8dee2aaSAndroid Build Coastguard Worker     return SkGradientShader::MakeRadial(center, radius, gColors, nullptr, std::size(gColors),
75*c8dee2aaSAndroid Build Coastguard Worker                                         SkTileMode::kClamp, 0, &localMatrix);
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker 
draw_gradients(SkCanvas * canvas,sk_sp<SkShader> (* makeShader)(const SkPoint[2],const SkMatrix &),const SkPoint ptsArray[][2],int numImages)78*c8dee2aaSAndroid Build Coastguard Worker static void draw_gradients(SkCanvas* canvas,
79*c8dee2aaSAndroid Build Coastguard Worker                            sk_sp<SkShader> (*makeShader)(const SkPoint[2], const SkMatrix&),
80*c8dee2aaSAndroid Build Coastguard Worker                            const SkPoint ptsArray[][2], int numImages) {
81*c8dee2aaSAndroid Build Coastguard Worker     // Use some nice prime numbers for the rectangle and matrix with
82*c8dee2aaSAndroid Build Coastguard Worker     // different scaling along the x and y axes (which is the bug this
83*c8dee2aaSAndroid Build Coastguard Worker     // test addresses, where incorrect order of operations mixed up the axes)
84*c8dee2aaSAndroid Build Coastguard Worker     SkRect rectGrad = {
85*c8dee2aaSAndroid Build Coastguard Worker         SkIntToScalar(43),  SkIntToScalar(61),
86*c8dee2aaSAndroid Build Coastguard Worker         SkIntToScalar(181), SkIntToScalar(167) };
87*c8dee2aaSAndroid Build Coastguard Worker     SkMatrix shaderMat;
88*c8dee2aaSAndroid Build Coastguard Worker     shaderMat.setScale(rectGrad.width(), rectGrad.height());
89*c8dee2aaSAndroid Build Coastguard Worker     shaderMat.postTranslate(rectGrad.left(), rectGrad.top());
90*c8dee2aaSAndroid Build Coastguard Worker 
91*c8dee2aaSAndroid Build Coastguard Worker     canvas->save();
92*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numImages; i++) {
93*c8dee2aaSAndroid Build Coastguard Worker         // Advance line downwards if necessary.
94*c8dee2aaSAndroid Build Coastguard Worker         if (i % IMAGES_X == 0 && i != 0) {
95*c8dee2aaSAndroid Build Coastguard Worker             canvas->restore();
96*c8dee2aaSAndroid Build Coastguard Worker             canvas->translate(0, TESTGRID_Y);
97*c8dee2aaSAndroid Build Coastguard Worker             canvas->save();
98*c8dee2aaSAndroid Build Coastguard Worker         }
99*c8dee2aaSAndroid Build Coastguard Worker 
100*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
101*c8dee2aaSAndroid Build Coastguard Worker         paint.setShader(makeShader(*ptsArray, shaderMat));
102*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawRect(rectGrad, paint);
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker         // Advance to next position.
105*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(TESTGRID_X, 0);
106*c8dee2aaSAndroid Build Coastguard Worker         ptsArray++;
107*c8dee2aaSAndroid Build Coastguard Worker     }
108*c8dee2aaSAndroid Build Coastguard Worker     canvas->restore();
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM_BG(gradient_matrix, canvas, 800, 800, 0xFFDDDDDD) {
112*c8dee2aaSAndroid Build Coastguard Worker         draw_gradients(canvas, &make_linear_gradient,
113*c8dee2aaSAndroid Build Coastguard Worker                       linearPts, std::size(linearPts));
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0, TESTGRID_Y);
116*c8dee2aaSAndroid Build Coastguard Worker 
117*c8dee2aaSAndroid Build Coastguard Worker         draw_gradients(canvas, &make_radial_gradient,
118*c8dee2aaSAndroid Build Coastguard Worker                       radialPts, std::size(radialPts));
119*c8dee2aaSAndroid Build Coastguard Worker }
120