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