1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "convex_paths.h"
16 
17 #include <native_drawing/drawing_bitmap.h>
18 #include <native_drawing/drawing_brush.h>
19 #include <native_drawing/drawing_canvas.h>
20 #include <native_drawing/drawing_color.h>
21 #include <native_drawing/drawing_filter.h>
22 #include <native_drawing/drawing_mask_filter.h>
23 #include <native_drawing/drawing_matrix.h>
24 #include <native_drawing/drawing_path.h>
25 #include <native_drawing/drawing_pen.h>
26 #include <native_drawing/drawing_point.h>
27 #include <native_drawing/drawing_round_rect.h>
28 #include <native_drawing/drawing_shader_effect.h>
29 #include <vector>
30 
31 #include "test_common.h"
32 
33 #include "common/log_common.h"
34 
35 constexpr static float K_RADIUS = 50.f;
36 constexpr static int K_LENGTH = 100;
37 constexpr static int K_PTS_PER_SIDE = (1 << 12);
38 
39 std::vector<OH_Drawing_Path*> fPaths;
40 
OnTestFunction(OH_Drawing_Canvas * canvas)41 void ConvexPaths::OnTestFunction(OH_Drawing_Canvas* canvas)
42 {
43     OH_Drawing_CanvasClear(canvas, 0xFF000000);
44     OH_Drawing_Brush* brush = OH_Drawing_BrushCreate();
45     OH_Drawing_BrushSetAntiAlias(brush, true);
46     MakePath();
47 
48     TestRend rand;
49     OH_Drawing_CanvasTranslate(canvas, 20, 20); // 20, 20坐标
50 
51     // As we've added more paths this has gotten pretty big. Scale the whole thing down.
52     OH_Drawing_CanvasScale(canvas, 2.0f / 3, 2.0f / 3); // float sx = 2.0f / 3;
53 
54     for (int i = 0; i < fPaths.size(); ++i) {
55         OH_Drawing_CanvasSave(canvas);
56         // position the path, and make it at off-integer coords.
57         float dxx = 200.0f * (i % 5) + 1.0f / 10;
58         float dyy = 200.0f * (i / 5) + 9.0f / 10;
59         OH_Drawing_CanvasTranslate(canvas, dxx, dyy);
60         uint32_t color = rand.nextU();
61         color |= 0xff000000;
62         OH_Drawing_BrushSetColor(brush, color);
63         OH_Drawing_CanvasAttachBrush(canvas, brush);
64         OH_Drawing_CanvasDrawPath(canvas, fPaths[i]);
65         OH_Drawing_CanvasRestore(canvas);
66     }
67     OH_Drawing_CanvasDetachBrush(canvas);
68     OH_Drawing_BrushDestroy(brush);
69 
70     for (int f = 0; f < fPaths.size(); ++f) {
71         OH_Drawing_PathDestroy(fPaths[f]);
72     }
73     fPaths.clear();
74 }
75 
MakePath1()76 void ConvexPaths::MakePath1()
77 {
78     OH_Drawing_Path* path_1 = OH_Drawing_PathCreate();
79     OH_Drawing_PathMoveTo(path_1, 0, 0);
80     OH_Drawing_PathQuadTo(path_1, 50, 100, 0, 100); // 50 100 坐标
81     OH_Drawing_PathLineTo(path_1, 0, 0);
82     fPaths.push_back(path_1);
83 
84     OH_Drawing_Path* path_2 = OH_Drawing_PathCreate();
85     OH_Drawing_PathMoveTo(path_2, 0, 50);           // 50 coordinate
86     OH_Drawing_PathQuadTo(path_2, 50, 0, 100, 50); // 50 100 coordinate
87     OH_Drawing_PathQuadTo(path_2, 50, 100, 0, 50);  // 50 100 coordinate
88     fPaths.push_back(path_2);
89 
90     OH_Drawing_Path* rect_path1 = OH_Drawing_PathCreate();
91     OH_Drawing_Path* rect_path2 = OH_Drawing_PathCreate();
92     DrawRect r = { 0, 0, 100, 100 }; // 100 coordinate
93     DrawRect r1 = { 0, 0, 50, 100 }; // 50 100 coordinate
94     DrawRect r2 = { 0, 0, 100, 5 };  // 5 100 coordinate
95     DrawRect r3 = { 0, 0, 1, 100 };  // 100 coordinate
96     OH_Drawing_PathAddRect(rect_path1, r.left, r.top, r.right, r.bottom, OH_Drawing_PathDirection::PATH_DIRECTION_CW);
97     OH_Drawing_PathAddRect(rect_path2, r.left, r.top, r.right, r.bottom, OH_Drawing_PathDirection::PATH_DIRECTION_CCW);
98     fPaths.push_back(rect_path1);
99     fPaths.push_back(rect_path2);
100 
101     OH_Drawing_Path* Circle_path = OH_Drawing_PathCreate();
102     OH_Drawing_PathAddCircle(Circle_path, 50, 50, 50, OH_Drawing_PathDirection::PATH_DIRECTION_CW); // 50 is radius
103     fPaths.push_back(Circle_path);
104 
105     OH_Drawing_Path* Oval_path1 = OH_Drawing_PathCreate();
106     OH_Drawing_Path* Oval_path2 = OH_Drawing_PathCreate();
107     OH_Drawing_Path* Oval_path3 = OH_Drawing_PathCreate();
108     auto Oval_bound1 = OH_Drawing_RectCreate(r1.left, r1.top, r1.right, r1.bottom);
109     auto Oval_bound2 = OH_Drawing_RectCreate(r2.left, r2.top, r2.right, r2.bottom);
110     auto Oval_bound3 = OH_Drawing_RectCreate(r3.left, r3.top, r3.right, r3.bottom);
111     OH_Drawing_PathAddOvalWithInitialPoint(Oval_path1, Oval_bound1, 0, OH_Drawing_PathDirection::PATH_DIRECTION_CW);
112     OH_Drawing_PathAddOvalWithInitialPoint(Oval_path2, Oval_bound2, 0, OH_Drawing_PathDirection::PATH_DIRECTION_CCW);
113     OH_Drawing_PathAddOvalWithInitialPoint(Oval_path3, Oval_bound3, 0, OH_Drawing_PathDirection::PATH_DIRECTION_CCW);
114     fPaths.push_back(Oval_path1);
115     fPaths.push_back(Oval_path2);
116     fPaths.push_back(Oval_path3);
117 }
118 
MakePath2()119 void ConvexPaths::MakePath2()
120 {
121     DrawRect r = { 0, 0, 100, 100 }; // 100 coordinate
122     OH_Drawing_Path* rrect_path = OH_Drawing_PathCreate();
123     OH_Drawing_Rect* rrect = OH_Drawing_RectCreate(r.left, r.top, r.right, r.bottom);
124     float xRad = 40;
125     float yRad = 20;
126     OH_Drawing_RoundRect* round_rect = OH_Drawing_RoundRectCreate(rrect, xRad, yRad);
127     OH_Drawing_PathAddRoundRect(rrect_path, round_rect, OH_Drawing_PathDirection::PATH_DIRECTION_CW);
128     fPaths.push_back(rrect_path);
129 
130     OH_Drawing_Path* path_3 = OH_Drawing_PathCreate();
131     OH_Drawing_PathMoveTo(path_3, 0, 0);
132     for (int i = 1; i < K_PTS_PER_SIDE; ++i) { // skip the first point due to moveTo.
133         OH_Drawing_PathLineTo(path_3, K_LENGTH * (float)i / K_PTS_PER_SIDE, 0);
134     }
135     for (int i = 0; i < K_PTS_PER_SIDE; ++i) {
136         OH_Drawing_PathLineTo(path_3, K_LENGTH, K_LENGTH * (float)i / K_PTS_PER_SIDE);
137     }
138     for (int i = K_PTS_PER_SIDE; i > 0; --i) {
139         OH_Drawing_PathLineTo(path_3, K_LENGTH * (float)i / K_PTS_PER_SIDE, K_LENGTH);
140     }
141     for (int i = K_PTS_PER_SIDE; i > 0; --i) {
142         OH_Drawing_PathLineTo(path_3, 0, K_LENGTH * (float)i / K_PTS_PER_SIDE);
143     }
144     fPaths.push_back(path_3);
145 
146     // Polygon 对应接口未知
147     OH_Drawing_Path* path_Polygon = OH_Drawing_PathCreate();
148     OH_Drawing_PathMoveTo(path_Polygon, 0, 0);
149     OH_Drawing_PathLineTo(path_Polygon, 100, 1);  // 100 1 coordinate
150     OH_Drawing_PathLineTo(path_Polygon, 98, 100); // 98 100 coordinate
151     OH_Drawing_PathLineTo(path_Polygon, 3, 96);   // 3 96 coordinate
152     OH_Drawing_PathClose(path_Polygon);
153     fPaths.push_back(path_Polygon);
154     // Polygon接口缺失,使用LineTo替换
155 
156     OH_Drawing_Path* rect_path3 = OH_Drawing_PathCreate();
157     OH_Drawing_PathArcTo(rect_path3, 0, 0, K_RADIUS, 2 * K_RADIUS, 25, 130); // 2,25,130 坐标
158     fPaths.push_back(rect_path3);
159 
160     // cubics
161     OH_Drawing_Path* cubic_path1 = OH_Drawing_PathCreate();
162     OH_Drawing_Path* cubic_path2 = OH_Drawing_PathCreate();
163     OH_Drawing_PathCubicTo(cubic_path1, 1, 1, 10, 90, 0, 100);    // 1 10 90 100 coordinate
164     OH_Drawing_PathCubicTo(cubic_path2, 100, 50, 20, 100, 0, 0); // 100 50 20 100 coordinate
165     fPaths.push_back(cubic_path1);
166     fPaths.push_back(cubic_path2);
167 }
168 
MakePath3()169 void ConvexPaths::MakePath3()
170 {
171     // path that has a cubic with a repeated first control point and
172     // a repeated last control point.
173     OH_Drawing_Path* path_4 = OH_Drawing_PathCreate();
174     OH_Drawing_PathMoveTo(path_4, 10, 10);                // 10 coordinate
175     OH_Drawing_PathCubicTo(path_4, 10, 10, 10, 0, 20, 0); // 10 20 coordinate
176     OH_Drawing_PathLineTo(path_4, 40, 0);                 // 40 coordinate
177     OH_Drawing_PathCubicTo(path_4, 40, 0, 50, 0, 50, 10); // 40 50 10 coordinate
178     fPaths.push_back(path_4);
179 
180     // path that has two cubics with repeated middle control points.
181     OH_Drawing_Path* path_5 = OH_Drawing_PathCreate();
182     OH_Drawing_PathMoveTo(path_5, 10, 10);                // 10 coordinate
183     OH_Drawing_PathCubicTo(path_5, 10, 0, 10, 0, 20, 0);  // 10 20 coordinate
184     OH_Drawing_PathLineTo(path_5, 40, 0);                 // 40 coordinate
185     OH_Drawing_PathCubicTo(path_5, 50, 0, 50, 0, 50, 10); // 50 10 coordinate
186     fPaths.push_back(path_5);
187 
188     // cubic where last three points are almost a line
189     OH_Drawing_Path* path_6 = OH_Drawing_PathCreate();
190     OH_Drawing_PathMoveTo(path_6, 0, 228.0f / 8); // 228.0f / 8 coordinate
191     OH_Drawing_PathCubicTo(path_6, 628.0f / 8, 82.0f / 8, 1255.0f / 8, 141.0f / 8, 1883.0f / 8,
192         202.0f / 8); // 8 dividend
193     fPaths.push_back(path_6);
194 
195     // flat cubic where the at end point tangents both point outward.
196     OH_Drawing_Path* path_7 = OH_Drawing_PathCreate();
197     OH_Drawing_PathMoveTo(path_7, 10, 0);               // 10 coordinate
198     OH_Drawing_PathCubicTo(path_7, 0, 1, 30, 1, 20, 0); // 1 30 20 coordinate
199     fPaths.push_back(path_7);
200 
201     // flat cubic where initial tangent is in, end tangent out
202     OH_Drawing_Path* path_8 = OH_Drawing_PathCreate();
203     OH_Drawing_PathMoveTo(path_8, 0, 0);
204     OH_Drawing_PathCubicTo(path_8, 10, 1, 30, 1, 20, 0); // 10 1 30 20 coordinate
205     fPaths.push_back(path_8);
206 }
207 
MakePath4()208 void ConvexPaths::MakePath4()
209 {
210     // flat cubic where initial tangent is out, end tangent in
211     OH_Drawing_Path* path_9 = OH_Drawing_PathCreate();
212     OH_Drawing_PathMoveTo(path_9, 10, 0);               // 10 coordinate
213     OH_Drawing_PathCubicTo(path_9, 0, 1, 20, 1, 30, 0); // 1 20 1 30 coordinate
214     fPaths.push_back(path_9);
215 
216     // triangle where one edge is a degenerate quad
217     OH_Drawing_Path* path_10 = OH_Drawing_PathCreate();
218     OH_Drawing_PathMoveTo(path_10, 8.59375f, 45);                // 8.59375f 45 coordinate
219     OH_Drawing_PathQuadTo(path_10, 16.9921875f, 45, 31.25f, 45); // 45 coordinate
220     OH_Drawing_PathLineTo(path_10, 100, 100);                    // 100 coordinate
221     OH_Drawing_PathLineTo(path_10, 8.59375f, 45);                // 45 coordinate
222     fPaths.push_back(path_10);
223 
224     // triangle where one edge is a quad with a repeated point
225     OH_Drawing_Path* path_11 = OH_Drawing_PathCreate();
226     OH_Drawing_PathMoveTo(path_11, 0, 25);          // 25 coordinate
227     OH_Drawing_PathLineTo(path_11, 50, 0);          // 50 coordinate
228     OH_Drawing_PathQuadTo(path_11, 50, 50, 50, 50); // 50 coordinate
229     fPaths.push_back(path_11);
230 
231     // triangle where one edge is a cubic with a 2x repeated point
232     OH_Drawing_Path* path_12 = OH_Drawing_PathCreate();
233     OH_Drawing_PathMoveTo(path_12, 0, 25);                  // 25 coordinate
234     OH_Drawing_PathLineTo(path_12, 50, 0);                  // 50 coordinate
235     OH_Drawing_PathCubicTo(path_12, 50, 0, 50, 50, 50, 50); // 50 coordinate
236     fPaths.push_back(path_12);
237 
238     // triangle where one edge is a quad with a nearly repeated point
239     OH_Drawing_Path* path_13 = OH_Drawing_PathCreate();
240     OH_Drawing_PathMoveTo(path_13, 0, 25);              // 25 coordinate
241     OH_Drawing_PathLineTo(path_13, 50, 0);              // 50 coordinate
242     OH_Drawing_PathQuadTo(path_13, 50, 49.95f, 50, 50); // 50 coordinate
243     fPaths.push_back(path_13);
244 
245     // triangle where one edge is a cubic with a 3x nearly repeated point
246     OH_Drawing_Path* path_14 = OH_Drawing_PathCreate();
247     OH_Drawing_PathMoveTo(path_14, 0, 25);                           // 25 coordinate
248     OH_Drawing_PathLineTo(path_14, 50, 0);                           // 50 coordinate
249     OH_Drawing_PathCubicTo(path_14, 50, 49.95f, 50, 49.97f, 50, 50); // 50 coordinate
250     fPaths.push_back(path_14);
251 }
252 
MakePath5()253 void ConvexPaths::MakePath5()
254 {
255     // triangle where there is a point degenerate cubic at one corner
256     OH_Drawing_Path* path_15 = OH_Drawing_PathCreate();
257     OH_Drawing_PathMoveTo(path_15, 0, 25);                   // 25 coordinate
258     OH_Drawing_PathLineTo(path_15, 50, 0);                   // 50 coordinate
259     OH_Drawing_PathLineTo(path_15, 50, 50);                  // 50 coordinate
260     OH_Drawing_PathCubicTo(path_15, 50, 50, 50, 50, 50, 50); // 50 coordinate
261     fPaths.push_back(path_15);
262 
263     // point line
264     // fPaths.push_back(SkPath::Line({50, 50}, {50, 50}));该接口调用Ploygon,待确定
265     OH_Drawing_Path* path_Polygon_2 = OH_Drawing_PathCreate();
266     OH_Drawing_PathLineTo(path_Polygon_2, 50, 50); // 50 coordinate
267     OH_Drawing_PathLineTo(path_Polygon_2, 50, 50); // 50 coordinate
268     fPaths.push_back(path_Polygon_2);
269     // Polygon接口缺失,LineTo替换
270 
271     // point quad
272     OH_Drawing_Path* path_16 = OH_Drawing_PathCreate();
273     OH_Drawing_PathMoveTo(path_16, 50, 50);         // 50 coordinate
274     OH_Drawing_PathQuadTo(path_16, 50, 50, 50, 50); // 50 coordinate
275     fPaths.push_back(path_16);
276 
277     // point cubic
278     OH_Drawing_Path* path_17 = OH_Drawing_PathCreate();
279     OH_Drawing_PathMoveTo(path_17, 50, 50);                  // 50 coordinate
280     OH_Drawing_PathCubicTo(path_17, 50, 50, 50, 50, 50, 50); // 50 coordinate
281     fPaths.push_back(path_17);
282 
283     // moveTo only paths
284     OH_Drawing_Path* path_18 = OH_Drawing_PathCreate();
285     OH_Drawing_PathMoveTo(path_18, 0, 0);
286     OH_Drawing_PathMoveTo(path_18, 0, 0);
287     OH_Drawing_PathMoveTo(path_18, 1, 1);   // 1 coordinate
288     OH_Drawing_PathMoveTo(path_18, 1, 1);   // 1 coordinate
289     OH_Drawing_PathMoveTo(path_18, 10, 10); // 10 coordinate
290     fPaths.push_back(path_18);
291 
292     OH_Drawing_Path* path_19 = OH_Drawing_PathCreate();
293     OH_Drawing_PathMoveTo(path_19, 0, 0);
294     OH_Drawing_PathMoveTo(path_19, 0, 0);
295     fPaths.push_back(path_19);
296 }
297 
MakePath6()298 void ConvexPaths::MakePath6()
299 {
300     // line degenerate
301     OH_Drawing_Path* path_20 = OH_Drawing_PathCreate();
302     OH_Drawing_PathLineTo(path_20, 100, 100); // 100 coordinate
303     fPaths.push_back(path_20);
304     OH_Drawing_Path* path_21 = OH_Drawing_PathCreate();
305     OH_Drawing_PathQuadTo(path_21, 100, 100, 0, 0); // 100 coordinate
306     fPaths.push_back(path_21);
307     OH_Drawing_Path* path_22 = OH_Drawing_PathCreate();
308     OH_Drawing_PathQuadTo(path_22, 100, 100, 50, 50); // 100 50 coordinate
309     fPaths.push_back(path_22);
310     OH_Drawing_Path* path_23 = OH_Drawing_PathCreate();
311     OH_Drawing_PathQuadTo(path_23, 50, 50, 100, 100); // 50 100 coordinate
312     fPaths.push_back(path_23);
313     OH_Drawing_Path* path_24 = OH_Drawing_PathCreate();
314     OH_Drawing_PathCubicTo(path_24, 0, 0, 0, 0, 100, 100); // 100 coordinate
315     fPaths.push_back(path_24);
316 
317     // skbug.com/8928
318     OH_Drawing_Path* path_25 = OH_Drawing_PathCreate();
319     OH_Drawing_PathMoveTo(path_25, 16.875f, 192.594f);
320     OH_Drawing_PathCubicTo(path_25, 45.625f, 192.594f, 74.375f, 192.594f, 103.125f, 192.594f);
321     OH_Drawing_PathCubicTo(path_25, 88.75f, 167.708f, 74.375f, 142.823f, 60, 117.938f); // 60 coordinate
322     OH_Drawing_PathCubicTo(path_25, 45.625f, 142.823f, 31.25f, 167.708f, 16.875f, 192.594f);
323     fPaths.push_back(path_25);
324 
325     OH_Drawing_Path* Matrix_path = fPaths.back();
326     OH_Drawing_Matrix* m1 = OH_Drawing_MatrixCreate();
327     OH_Drawing_MatrixSetMatrix(m1, 0.1f, 0, -1, 0, 0.115207f, -2.64977f, 0, 0, 1); // 1 coordinate
328     OH_Drawing_PathTransform(Matrix_path, m1);
329 
330     // small circle. This is listed last so that it has device coords far
331     // from the origin (small area relative to x,y values).
332     OH_Drawing_Path* Circle_path1 = OH_Drawing_PathCreate();
333     // auto Circle_bound1 = OH_Drawing_RectCreate(0, 0, 1.2, 1.2); // 1.2 矩形对象,边框
334     OH_Drawing_PathAddCircle(Circle_path1, 0, 0, 1.2, OH_Drawing_PathDirection::PATH_DIRECTION_CW); // 360 坐标
335     fPaths.push_back(Circle_path1);
336 }
337 
MakePath()338 void ConvexPaths::MakePath()
339 {
340     MakePath1();
341     MakePath2();
342     MakePath3();
343     MakePath4();
344     MakePath5();
345     MakePath6();
346 }
347 
~ConvexPaths()348 ConvexPaths::~ConvexPaths() {}