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() {}