| /* | 
 |  * Copyright 2013 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "gm/gm.h" | 
 | #include "include/core/SkCanvas.h" | 
 | #include "include/core/SkColor.h" | 
 | #include "include/core/SkMatrix.h" | 
 | #include "include/core/SkPaint.h" | 
 | #include "include/core/SkPoint.h" | 
 | #include "include/core/SkRect.h" | 
 | #include "include/core/SkRefCnt.h" | 
 | #include "include/core/SkScalar.h" | 
 | #include "include/core/SkShader.h" | 
 | #include "include/core/SkTileMode.h" | 
 | #include "include/core/SkTypes.h" | 
 | #include "include/effects/SkGradientShader.h" | 
 |  | 
 | constexpr SkColor gColors[] = { | 
 |     SK_ColorRED, SK_ColorYELLOW | 
 | }; | 
 |  | 
 | // These annoying defines are necessary, because the only other alternative | 
 | // is to use SkIntToScalar(...) everywhere. | 
 | constexpr SkScalar sZero = 0; | 
 | constexpr SkScalar sHalf = SK_ScalarHalf; | 
 | constexpr SkScalar sOne = SK_Scalar1; | 
 |  | 
 | // These arrays define the gradient stop points | 
 | // as x1, y1, x2, y2 per gradient to draw. | 
 | constexpr SkPoint linearPts[][2] = { | 
 |     {{sZero, sZero}, {sOne,  sZero}}, | 
 |     {{sZero, sZero}, {sZero, sOne}}, | 
 |     {{sOne,  sZero}, {sZero, sZero}}, | 
 |     {{sZero, sOne},  {sZero, sZero}}, | 
 |  | 
 |     {{sZero, sZero}, {sOne,  sOne}}, | 
 |     {{sOne,  sOne},  {sZero, sZero}}, | 
 |     {{sOne,  sZero}, {sZero, sOne}}, | 
 |     {{sZero, sOne},  {sOne,  sZero}} | 
 | }; | 
 |  | 
 | constexpr SkPoint radialPts[][2] = { | 
 |     {{sZero, sHalf}, {sOne,  sHalf}}, | 
 |     {{sHalf, sZero}, {sHalf, sOne}}, | 
 |     {{sOne,  sHalf}, {sZero, sHalf}}, | 
 |     {{sHalf, sOne},  {sHalf, sZero}}, | 
 |  | 
 |     {{sZero, sZero}, {sOne,  sOne}}, | 
 |     {{sOne,  sOne},  {sZero, sZero}}, | 
 |     {{sOne,  sZero}, {sZero, sOne}}, | 
 |     {{sZero, sOne},  {sOne,  sZero}} | 
 | }; | 
 |  | 
 | // These define the pixels allocated to each gradient image. | 
 | constexpr SkScalar TESTGRID_X = SkIntToScalar(200); | 
 | constexpr SkScalar TESTGRID_Y = SkIntToScalar(200); | 
 |  | 
 | constexpr int IMAGES_X = 4;             // number of images per row | 
 |  | 
 | static sk_sp<SkShader> make_linear_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) { | 
 |     return SkGradientShader::MakeLinear(pts, gColors, nullptr, std::size(gColors), | 
 |                                         SkTileMode::kClamp, 0, &localMatrix); | 
 | } | 
 |  | 
 | static sk_sp<SkShader> make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) { | 
 |     SkPoint center; | 
 |     center.set(SkScalarAve(pts[0].fX, pts[1].fX), | 
 |                SkScalarAve(pts[0].fY, pts[1].fY)); | 
 |     float radius = (center - pts[0]).length(); | 
 |     return SkGradientShader::MakeRadial(center, radius, gColors, nullptr, std::size(gColors), | 
 |                                         SkTileMode::kClamp, 0, &localMatrix); | 
 | } | 
 |  | 
 | static void draw_gradients(SkCanvas* canvas, | 
 |                            sk_sp<SkShader> (*makeShader)(const SkPoint[2], const SkMatrix&), | 
 |                            const SkPoint ptsArray[][2], int numImages) { | 
 |     // Use some nice prime numbers for the rectangle and matrix with | 
 |     // different scaling along the x and y axes (which is the bug this | 
 |     // test addresses, where incorrect order of operations mixed up the axes) | 
 |     SkRect rectGrad = { | 
 |         SkIntToScalar(43),  SkIntToScalar(61), | 
 |         SkIntToScalar(181), SkIntToScalar(167) }; | 
 |     SkMatrix shaderMat; | 
 |     shaderMat.setScale(rectGrad.width(), rectGrad.height()); | 
 |     shaderMat.postTranslate(rectGrad.left(), rectGrad.top()); | 
 |  | 
 |     canvas->save(); | 
 |     for (int i = 0; i < numImages; i++) { | 
 |         // Advance line downwards if necessary. | 
 |         if (i % IMAGES_X == 0 && i != 0) { | 
 |             canvas->restore(); | 
 |             canvas->translate(0, TESTGRID_Y); | 
 |             canvas->save(); | 
 |         } | 
 |  | 
 |         SkPaint paint; | 
 |         paint.setShader(makeShader(*ptsArray, shaderMat)); | 
 |         canvas->drawRect(rectGrad, paint); | 
 |  | 
 |         // Advance to next position. | 
 |         canvas->translate(TESTGRID_X, 0); | 
 |         ptsArray++; | 
 |     } | 
 |     canvas->restore(); | 
 | } | 
 |  | 
 | DEF_SIMPLE_GM_BG(gradient_matrix, canvas, 800, 800, 0xFFDDDDDD) { | 
 |         draw_gradients(canvas, &make_linear_gradient, | 
 |                       linearPts, std::size(linearPts)); | 
 |  | 
 |         canvas->translate(0, TESTGRID_Y); | 
 |  | 
 |         draw_gradients(canvas, &make_radial_gradient, | 
 |                       radialPts, std::size(radialPts)); | 
 | } |