1ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org/*
2ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org * Copyright 2013 Google Inc.
3ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org *
4ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org * found in the LICENSE file.
6ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org */
7ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
8ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkCanvas.h"
9ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkColor.h"
10ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkGradientShader.h"
11ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkMatrix.h"
12ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkPaint.h"
13ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkPoint.h"
14ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkRect.h"
15ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkRefCnt.h"
16ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkScalar.h"
17ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkSize.h"
18ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "SkString.h"
19ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
20ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org#include "gm.h"
21ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
22ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.orgstatic const SkColor gColors[] = {
23ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    SK_ColorRED, SK_ColorYELLOW
24ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org};
25ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
2645672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org// These annoying defines are necessary, because the only other alternative
274b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org// is to use SkIntToScalar(...) everywhere.
2845672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.orgstatic const SkScalar sZero = 0;
2945672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.orgstatic const SkScalar sHalf = SK_ScalarHalf;
3045672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.orgstatic const SkScalar sOne = SK_Scalar1;
3145672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org
3245672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org// These arrays define the gradient stop points
3345672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org// as x1, y1, x2, y2 per gradient to draw.
34ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.orgstatic const SkPoint linearPts[][2] = {
3545672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sZero}, {sOne,  sZero}},
3645672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sZero}, {sZero, sOne}},
3745672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sZero}, {sZero, sZero}},
3845672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sOne},  {sZero, sZero}},
39ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
4045672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sZero}, {sOne,  sOne}},
4145672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sOne},  {sZero, sZero}},
4245672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sZero}, {sZero, sOne}},
4345672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sOne},  {sOne,  sZero}}
44ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org};
45ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
461ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.orgstatic const SkPoint radialPts[][2] = {
4745672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sHalf}, {sOne,  sHalf}},
4845672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sHalf, sZero}, {sHalf, sOne}},
4945672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sHalf}, {sZero, sHalf}},
5045672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sHalf, sOne},  {sHalf, sZero}},
511ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org
5245672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sZero}, {sOne,  sOne}},
5345672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sOne},  {sZero, sZero}},
5445672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sOne,  sZero}, {sZero, sOne}},
5545672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    {{sZero, sOne},  {sOne,  sZero}}
561ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org};
571ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org
5845672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org// These define the pixels allocated to each gradient image.
5945672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.orgstatic const SkScalar TESTGRID_X = SkIntToScalar(200);
6045672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.orgstatic const SkScalar TESTGRID_Y = SkIntToScalar(200);
61ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
62ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.orgstatic const int IMAGES_X = 4;             // number of images per row
63ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
649c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.orgstatic SkShader* make_linear_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return SkGradientShader::CreateLinear(pts, gColors, nullptr, SK_ARRAY_COUNT(gColors),
6683f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                                          SkShader::kClamp_TileMode, 0, &localMatrix);
67ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org}
68ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
699c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.orgstatic SkShader* make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
701ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org    SkPoint center;
711ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
721ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org               SkScalarAve(pts[0].fY, pts[1].fY));
731ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org    float radius = (center - pts[0]).length();
742880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return SkGradientShader::CreateRadial(center, radius, gColors, nullptr, SK_ARRAY_COUNT(gColors),
7583f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org                                          SkShader::kClamp_TileMode, 0, &localMatrix);
761ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org}
771ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org
789c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.orgstatic void draw_gradients(SkCanvas* canvas,
799c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org                           SkShader* (*makeShader)(const SkPoint[2], const SkMatrix&),
801ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org                           const SkPoint ptsArray[][2], int numImages) {
81ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    // Use some nice prime numbers for the rectangle and matrix with
82ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    // different scaling along the x and y axes (which is the bug this
83ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    // test addresses, where incorrect order of operations mixed up the axes)
8445672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org    SkRect rectGrad = {
8545672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org        SkIntToScalar(43),  SkIntToScalar(61),
8645672099ea3006cde5b8a97b52fcd0b8ac69d4e1commit-bot@chromium.org        SkIntToScalar(181), SkIntToScalar(167) };
87ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    SkMatrix shaderMat;
88ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    shaderMat.setScale(rectGrad.width(), rectGrad.height());
89ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    shaderMat.postTranslate(rectGrad.left(), rectGrad.top());
90ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
91ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    canvas->save();
92ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    for (int i = 0; i < numImages; i++) {
93ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        // Advance line downwards if necessary.
94ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        if (i % IMAGES_X == 0 && i != 0) {
95ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org            canvas->restore();
96ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org            canvas->translate(0, TESTGRID_Y);
97ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org            canvas->save();
98ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        }
99ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
100ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        // Setup shader and draw.
1019c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org        SkAutoTUnref<SkShader> shader(makeShader(*ptsArray, shaderMat));
102ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
103ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        SkPaint paint;
104ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        paint.setShader(shader);
105ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        canvas->drawRect(rectGrad, paint);
106ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
107ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        // Advance to next position.
108ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        canvas->translate(TESTGRID_X, 0);
109ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        ptsArray++;
110ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    }
111ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org    canvas->restore();
112ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org}
113ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org
1142880df2609eba09b555ca37be04b6ad89290c765Tom HudsonDEF_SIMPLE_GM_BG(gradient_matrix, canvas, 800, 800,
1152880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                 sk_tool_utils::color_to_565(0xFFDDDDDD)) {
116ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org        draw_gradients(canvas, &make_linear_gradient,
117ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org                      linearPts, SK_ARRAY_COUNT(linearPts));
1181ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org
1191ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org        canvas->translate(0, TESTGRID_Y);
1201ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org
1211ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org        draw_gradients(canvas, &make_radial_gradient,
1221ac1cf695dfffd01d241d07d419f0bce975d9186commit-bot@chromium.org                      radialPts, SK_ARRAY_COUNT(radialPts));
123ace2269edfed9dfd3097597f1698921aaddf80a1commit-bot@chromium.org}
124