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