1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "gm/gm.h"
9cb93a386Sopenharmony_ci#include "include/core/SkBlendMode.h"
10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
12cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
14cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
15cb93a386Sopenharmony_ci#include "include/core/SkPoint.h"
16cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h"
17cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
18cb93a386Sopenharmony_ci#include "include/core/SkShader.h"
19cb93a386Sopenharmony_ci#include "include/core/SkTileMode.h"
20cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
21cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h"
22cb93a386Sopenharmony_ci#include "src/utils/SkPatchUtils.h"
23cb93a386Sopenharmony_ci#include "tools/Resources.h"
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_cistatic sk_sp<SkShader> make_shader() {
26cb93a386Sopenharmony_ci    const SkColor colors[] = {
27cb93a386Sopenharmony_ci        SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE,
28cb93a386Sopenharmony_ci        SK_ColorYELLOW,
29cb93a386Sopenharmony_ci    };
30cb93a386Sopenharmony_ci    const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } };
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
33cb93a386Sopenharmony_ci                                        SkTileMode::kMirror);
34cb93a386Sopenharmony_ci}
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cistatic void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
37cb93a386Sopenharmony_ci    //draw control points
38cb93a386Sopenharmony_ci    SkPaint paint;
39cb93a386Sopenharmony_ci    SkPoint bottom[SkPatchUtils::kNumPtsCubic];
40cb93a386Sopenharmony_ci    SkPatchUtils::GetBottomCubic(cubics, bottom);
41cb93a386Sopenharmony_ci    SkPoint top[SkPatchUtils::kNumPtsCubic];
42cb93a386Sopenharmony_ci    SkPatchUtils::GetTopCubic(cubics, top);
43cb93a386Sopenharmony_ci    SkPoint left[SkPatchUtils::kNumPtsCubic];
44cb93a386Sopenharmony_ci    SkPatchUtils::GetLeftCubic(cubics, left);
45cb93a386Sopenharmony_ci    SkPoint right[SkPatchUtils::kNumPtsCubic];
46cb93a386Sopenharmony_ci    SkPatchUtils::GetRightCubic(cubics, right);
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    paint.setColor(SK_ColorBLACK);
49cb93a386Sopenharmony_ci    paint.setStrokeWidth(0.5f);
50cb93a386Sopenharmony_ci    SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
51cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
52cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint);
53cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
54cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
55cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint);
58cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint);
59cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint);
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    paint.setStrokeWidth(2);
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    paint.setColor(SK_ColorRED);
64cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    paint.setColor(SK_ColorBLUE);
67cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint);
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    paint.setColor(SK_ColorCYAN);
70cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint);
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    paint.setColor(SK_ColorYELLOW);
73cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint);
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    paint.setColor(SK_ColorGREEN);
76cb93a386Sopenharmony_ci    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint);
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci// The order of the colors and points is clockwise starting at upper-left corner.
80cb93a386Sopenharmony_ciconst SkPoint gCubics[SkPatchUtils::kNumCtrlPts] = {
81cb93a386Sopenharmony_ci    //top points
82cb93a386Sopenharmony_ci    {100,100},{150,50},{250,150}, {300,100},
83cb93a386Sopenharmony_ci    //right points
84cb93a386Sopenharmony_ci    {250, 150},{350,250},
85cb93a386Sopenharmony_ci    //bottom points
86cb93a386Sopenharmony_ci    {300,300},{250,250},{150,350},{100,300},
87cb93a386Sopenharmony_ci    //left points
88cb93a386Sopenharmony_ci    {50,250},{150,150}
89cb93a386Sopenharmony_ci};
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ciconst SkPoint gTexCoords[SkPatchUtils::kNumCorners] = {
92cb93a386Sopenharmony_ci    {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f}
93cb93a386Sopenharmony_ci};
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_cistatic void dopatch(SkCanvas* canvas, const SkColor colors[], sk_sp<SkImage> img,
97cb93a386Sopenharmony_ci                    const SkMatrix* localMatrix) {
98cb93a386Sopenharmony_ci    SkPaint paint;
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    const SkBlendMode modes[] = {
101cb93a386Sopenharmony_ci        SkBlendMode::kSrc,
102cb93a386Sopenharmony_ci        SkBlendMode::kDst,
103cb93a386Sopenharmony_ci        SkBlendMode::kModulate,
104cb93a386Sopenharmony_ci    };
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    SkPoint texStorage[4];
107cb93a386Sopenharmony_ci    const SkPoint* tex = gTexCoords;
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    sk_sp<SkShader> shader;
110cb93a386Sopenharmony_ci    if (img) {
111cb93a386Sopenharmony_ci        SkScalar w = img->width();
112cb93a386Sopenharmony_ci        SkScalar h = img->height();
113cb93a386Sopenharmony_ci        shader = img->makeShader(SkSamplingOptions(), localMatrix);
114cb93a386Sopenharmony_ci        texStorage[0].set(0, 0);
115cb93a386Sopenharmony_ci        texStorage[1].set(w, 0);
116cb93a386Sopenharmony_ci        texStorage[2].set(w, h);
117cb93a386Sopenharmony_ci        texStorage[3].set(0, h);
118cb93a386Sopenharmony_ci        tex = texStorage;
119cb93a386Sopenharmony_ci    } else {
120cb93a386Sopenharmony_ci        shader = make_shader();
121cb93a386Sopenharmony_ci    }
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    canvas->save();
124cb93a386Sopenharmony_ci    for (int y = 0; y < 3; y++) {
125cb93a386Sopenharmony_ci        for (int x = 0; x < 4; x++) {
126cb93a386Sopenharmony_ci            canvas->save();
127cb93a386Sopenharmony_ci            canvas->translate(x * 350.0f, y * 350.0f);
128cb93a386Sopenharmony_ci            switch (x) {
129cb93a386Sopenharmony_ci                case 0:
130cb93a386Sopenharmony_ci                    canvas->drawPatch(gCubics, nullptr, nullptr, modes[y], paint);
131cb93a386Sopenharmony_ci                    break;
132cb93a386Sopenharmony_ci                case 1:
133cb93a386Sopenharmony_ci                    canvas->drawPatch(gCubics, colors, nullptr, modes[y], paint);
134cb93a386Sopenharmony_ci                    break;
135cb93a386Sopenharmony_ci                case 2:
136cb93a386Sopenharmony_ci                    paint.setShader(shader);
137cb93a386Sopenharmony_ci                    canvas->drawPatch(gCubics, nullptr, tex, modes[y], paint);
138cb93a386Sopenharmony_ci                    paint.setShader(nullptr);
139cb93a386Sopenharmony_ci                    break;
140cb93a386Sopenharmony_ci                case 3:
141cb93a386Sopenharmony_ci                    paint.setShader(shader);
142cb93a386Sopenharmony_ci                    canvas->drawPatch(gCubics, colors, tex, modes[y], paint);
143cb93a386Sopenharmony_ci                    paint.setShader(nullptr);
144cb93a386Sopenharmony_ci                    break;
145cb93a386Sopenharmony_ci                default:
146cb93a386Sopenharmony_ci                    break;
147cb93a386Sopenharmony_ci            }
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci            draw_control_points(canvas, gCubics);
150cb93a386Sopenharmony_ci            canvas->restore();
151cb93a386Sopenharmony_ci        }
152cb93a386Sopenharmony_ci    }
153cb93a386Sopenharmony_ci    canvas->restore();
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ciDEF_SIMPLE_GM(patch_primitive, canvas, 1500, 1100) {
157cb93a386Sopenharmony_ci    const SkColor colors[SkPatchUtils::kNumCorners] = {
158cb93a386Sopenharmony_ci        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
159cb93a386Sopenharmony_ci    };
160cb93a386Sopenharmony_ci    dopatch(canvas, colors, nullptr, nullptr);
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ciDEF_SIMPLE_GM(patch_image, canvas, 1500, 1100) {
163cb93a386Sopenharmony_ci    const SkColor colors[SkPatchUtils::kNumCorners] = {
164cb93a386Sopenharmony_ci        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
165cb93a386Sopenharmony_ci    };
166cb93a386Sopenharmony_ci    dopatch(canvas, colors, GetResourceAsImage("images/mandrill_128.png"), nullptr);
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ciDEF_SIMPLE_GM(patch_image_persp, canvas, 1500, 1100) {
169cb93a386Sopenharmony_ci    const SkColor colors[SkPatchUtils::kNumCorners] = {
170cb93a386Sopenharmony_ci        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
171cb93a386Sopenharmony_ci    };
172cb93a386Sopenharmony_ci    SkMatrix localM;
173cb93a386Sopenharmony_ci    localM.reset();
174cb93a386Sopenharmony_ci    localM[6] = 0.00001f;    // force perspective
175cb93a386Sopenharmony_ci    dopatch(canvas, colors, GetResourceAsImage("images/mandrill_128.png"), &localM);
176cb93a386Sopenharmony_ci}
177cb93a386Sopenharmony_ciDEF_SIMPLE_GM(patch_alpha, canvas, 1500, 1100) {
178cb93a386Sopenharmony_ci    const SkColor colors[SkPatchUtils::kNumCorners] = {
179cb93a386Sopenharmony_ci        SK_ColorRED, 0x0000FF00, SK_ColorBLUE, 0x00FF00FF,
180cb93a386Sopenharmony_ci    };
181cb93a386Sopenharmony_ci    dopatch(canvas, colors, nullptr, nullptr);
182cb93a386Sopenharmony_ci}
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci// These two should look the same (one patch, one simple path)
185cb93a386Sopenharmony_ciDEF_SIMPLE_GM(patch_alpha_test, canvas, 550, 250) {
186cb93a386Sopenharmony_ci    canvas->translate(-75, -75);
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    const SkColor colors[SkPatchUtils::kNumCorners] = {
189cb93a386Sopenharmony_ci        0x80FF0000, 0x80FF0000, 0x80FF0000, 0x80FF0000,
190cb93a386Sopenharmony_ci    };
191cb93a386Sopenharmony_ci    SkPaint paint;
192cb93a386Sopenharmony_ci    canvas->drawPatch(gCubics, colors, nullptr, SkBlendMode::kModulate, paint);
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    canvas->translate(300, 0);
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    SkPath path;
197cb93a386Sopenharmony_ci    path.moveTo(gCubics[0]);
198cb93a386Sopenharmony_ci    path.cubicTo(gCubics[ 1], gCubics[ 2], gCubics[ 3]);
199cb93a386Sopenharmony_ci    path.cubicTo(gCubics[ 4], gCubics[ 5], gCubics[ 6]);
200cb93a386Sopenharmony_ci    path.cubicTo(gCubics[ 7], gCubics[ 8], gCubics[ 9]);
201cb93a386Sopenharmony_ci    path.cubicTo(gCubics[10], gCubics[11], gCubics[ 0]);
202cb93a386Sopenharmony_ci    paint.setColor(colors[0]);
203cb93a386Sopenharmony_ci    canvas->drawPath(path, paint);
204cb93a386Sopenharmony_ci}
205cb93a386Sopenharmony_ci
206