Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / modules / canvaskit / tests / bazel / path_test.js
1 describe('Path Behavior', () => {
2     let container;
3
4     beforeEach(async () => {
5         await EverythingLoaded;
6         container = document.createElement('div');
7         container.innerHTML = `
8             <canvas width=600 height=600 id=test></canvas>
9             <canvas width=600 height=600 id=report></canvas>`;
10         document.body.appendChild(container);
11     });
12
13     afterEach(() => {
14         document.body.removeChild(container);
15     });
16
17     gm('path_api_example', (canvas) => {
18         const paint = new CanvasKit.Paint();
19         paint.setStrokeWidth(1.0);
20         paint.setAntiAlias(true);
21         paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
22         paint.setStyle(CanvasKit.PaintStyle.Stroke);
23
24         const path = new CanvasKit.Path();
25         path.moveTo(20, 5);
26         path.lineTo(30, 20);
27         path.lineTo(40, 10);
28         path.lineTo(50, 20);
29         path.lineTo(60, 0);
30         path.lineTo(20, 5);
31
32         path.moveTo(20, 80);
33         path.cubicTo(90, 10, 160, 150, 190, 10);
34
35         path.moveTo(36, 148);
36         path.quadTo(66, 188, 120, 136);
37         path.lineTo(36, 148);
38
39         path.moveTo(150, 180);
40         path.arcToTangent(150, 100, 50, 200, 20);
41         path.lineTo(160, 160);
42
43         path.moveTo(20, 120);
44         path.lineTo(20, 120);
45
46         path.transform([2, 0, 0,
47                         0, 2, 0,
48                         0, 0, 1 ]);
49
50         canvas.drawPath(path, paint);
51
52         const rrect = CanvasKit.RRectXY([100, 10, 140, 62], 10, 4);
53
54         const rrectPath = new CanvasKit.Path().addRRect(rrect, true);
55
56         canvas.drawPath(rrectPath, paint);
57
58         rrectPath.delete();
59         path.delete();
60         paint.delete();
61         // See PathKit for more tests, since they share implementation
62     });
63
64     it('can create a path from an SVG string', () => {
65         //.This is a parallelogram from
66         // https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg
67         const path = CanvasKit.Path.MakeFromSVGString(
68           'M 205,5 L 795,5 L 595,295 L 5,295 L 205,5 z');
69
70         const cmds = path.toCmds();
71         expect(cmds).toBeTruthy();
72         // 1 move, 4 lines, 1 close
73         // each element in cmds is an array, with index 0 being the verb, and the rest being args
74         expect(cmds).toEqual(Float32Array.of(
75             CanvasKit.MOVE_VERB, 205, 5,
76             CanvasKit.LINE_VERB, 795, 5,
77             CanvasKit.LINE_VERB, 595, 295,
78             CanvasKit.LINE_VERB, 5, 295,
79             CanvasKit.LINE_VERB, 205, 5,
80             CanvasKit.CLOSE_VERB));
81         path.delete();
82     });
83
84     it('can create a path by combining two other paths', () => {
85         // Get the intersection of two overlapping squares and verify that it is the smaller square.
86         const pathOne = new CanvasKit.Path();
87         pathOne.addRect([10, 10, 20, 20]);
88
89         const pathTwo = new CanvasKit.Path();
90         pathTwo.addRect([15, 15, 30, 30]);
91
92         const path = CanvasKit.Path.MakeFromOp(pathOne, pathTwo, CanvasKit.PathOp.Intersect);
93         const cmds = path.toCmds();
94         expect(cmds).toBeTruthy();
95         expect(cmds).toEqual(Float32Array.of(
96             CanvasKit.MOVE_VERB, 15, 15,
97             CanvasKit.LINE_VERB, 20, 15,
98             CanvasKit.LINE_VERB, 20, 20,
99             CanvasKit.LINE_VERB, 15, 20,
100             CanvasKit.CLOSE_VERB));
101         path.delete();
102         pathOne.delete();
103         pathTwo.delete();
104     });
105
106     it('can create an SVG string from a path', () => {
107         const cmds = [CanvasKit.MOVE_VERB, 205, 5,
108                    CanvasKit.LINE_VERB, 795, 5,
109                    CanvasKit.LINE_VERB, 595, 295,
110                    CanvasKit.LINE_VERB, 5, 295,
111                    CanvasKit.LINE_VERB, 205, 5,
112                    CanvasKit.CLOSE_VERB];
113         const path = CanvasKit.Path.MakeFromCmds(cmds);
114
115         const svgStr = path.toSVGString();
116         // We output it in terse form, which is different than Wikipedia's version
117         expect(svgStr).toEqual('M205 5L795 5L595 295L5 295L205 5Z');
118         path.delete();
119     });
120
121     it('can create a path with malloced verbs, points, weights', () => {
122         const mVerbs = CanvasKit.Malloc(Uint8Array, 6);
123         const mPoints = CanvasKit.Malloc(Float32Array, 18);
124         const mWeights = CanvasKit.Malloc(Float32Array, 1);
125         mVerbs.toTypedArray().set([CanvasKit.MOVE_VERB, CanvasKit.LINE_VERB,
126             CanvasKit.QUAD_VERB, CanvasKit.CONIC_VERB, CanvasKit.CUBIC_VERB, CanvasKit.CLOSE_VERB
127         ]);
128
129         mPoints.toTypedArray().set([
130           1,2, // moveTo
131           3,4, // lineTo
132           5,6,7,8, // quadTo
133           9,10,11,12, // conicTo
134           13,14,15,16,17,18, // cubicTo
135         ]);
136
137         mWeights.toTypedArray().set([117]);
138
139         let path = CanvasKit.Path.MakeFromVerbsPointsWeights(mVerbs, mPoints, mWeights);
140
141         let cmds = path.toCmds();
142         expect(cmds).toEqual(Float32Array.of(
143             CanvasKit.MOVE_VERB, 1, 2,
144             CanvasKit.LINE_VERB, 3, 4,
145             CanvasKit.QUAD_VERB, 5, 6, 7, 8,
146             CanvasKit.CONIC_VERB, 9, 10, 11, 12, 117,
147             CanvasKit.CUBIC_VERB, 13, 14, 15, 16, 17, 18,
148             CanvasKit.CLOSE_VERB,
149         ));
150         path.delete();
151
152         // If given insufficient points, it stops early (but doesn't read out of bounds).
153         path = CanvasKit.Path.MakeFromVerbsPointsWeights(mVerbs, mPoints.subarray(0, 10), mWeights);
154
155         cmds = path.toCmds();
156         expect(cmds).toEqual(Float32Array.of(
157             CanvasKit.MOVE_VERB, 1, 2,
158             CanvasKit.LINE_VERB, 3, 4,
159             CanvasKit.QUAD_VERB, 5, 6, 7, 8,
160         ));
161         path.delete();
162         CanvasKit.Free(mVerbs);
163         CanvasKit.Free(mPoints);
164         CanvasKit.Free(mWeights);
165     });
166
167     it('can create and update a path with verbs and points (no weights)', () => {
168         const path = CanvasKit.Path.MakeFromVerbsPointsWeights(
169           [CanvasKit.MOVE_VERB, CanvasKit.LINE_VERB],
170           [1,2, 3,4]);
171         let cmds = path.toCmds();
172         expect(cmds).toEqual(Float32Array.of(
173             CanvasKit.MOVE_VERB, 1, 2,
174             CanvasKit.LINE_VERB, 3, 4
175         ));
176
177         path.addVerbsPointsWeights(
178           [CanvasKit.QUAD_VERB, CanvasKit.CLOSE_VERB],
179           [5,6,7,8],
180         );
181
182         cmds = path.toCmds();
183         expect(cmds).toEqual(Float32Array.of(
184             CanvasKit.MOVE_VERB, 1, 2,
185             CanvasKit.LINE_VERB, 3, 4,
186             CanvasKit.QUAD_VERB, 5, 6, 7, 8,
187             CanvasKit.CLOSE_VERB
188         ));
189         path.delete();
190     });
191
192
193     it('can add points to a path in bulk', () => {
194         const mVerbs = CanvasKit.Malloc(Uint8Array, 6);
195         const mPoints = CanvasKit.Malloc(Float32Array, 18);
196         const mWeights = CanvasKit.Malloc(Float32Array, 1);
197         mVerbs.toTypedArray().set([CanvasKit.MOVE_VERB, CanvasKit.LINE_VERB,
198             CanvasKit.QUAD_VERB, CanvasKit.CONIC_VERB, CanvasKit.CUBIC_VERB, CanvasKit.CLOSE_VERB
199         ]);
200
201         mPoints.toTypedArray().set([
202             1,2, // moveTo
203             3,4, // lineTo
204             5,6,7,8, // quadTo
205             9,10,11,12, // conicTo
206             13,14,15,16,17,18, // cubicTo
207         ]);
208
209         mWeights.toTypedArray().set([117]);
210
211         const path = new CanvasKit.Path();
212         path.lineTo(77, 88);
213         path.addVerbsPointsWeights(mVerbs, mPoints, mWeights);
214
215         let cmds = path.toCmds();
216         expect(cmds).toEqual(Float32Array.of(
217             CanvasKit.MOVE_VERB, 0, 0,
218             CanvasKit.LINE_VERB, 77, 88,
219             CanvasKit.MOVE_VERB, 1, 2,
220             CanvasKit.LINE_VERB, 3, 4,
221             CanvasKit.QUAD_VERB, 5, 6, 7, 8,
222             CanvasKit.CONIC_VERB, 9, 10, 11, 12, 117,
223             CanvasKit.CUBIC_VERB, 13, 14, 15, 16, 17, 18,
224             CanvasKit.CLOSE_VERB,
225         ));
226
227         path.rewind();
228         cmds = path.toCmds();
229         expect(cmds).toEqual(new Float32Array(0));
230
231         path.delete();
232         CanvasKit.Free(mVerbs);
233         CanvasKit.Free(mPoints);
234         CanvasKit.Free(mWeights);
235     });
236
237     it('can retrieve points from a path', () => {
238         const path = new CanvasKit.Path();
239         path.addRect([10, 15, 20, 25]);
240
241         let pt = path.getPoint(0);
242         expect(pt[0]).toEqual(10);
243         expect(pt[1]).toEqual(15);
244
245         path.getPoint(2, pt);
246         expect(pt[0]).toEqual(20);
247         expect(pt[1]).toEqual(25);
248
249         path.getPoint(1000, pt); // off the end returns (0, 0) as per the docs.
250         expect(pt[0]).toEqual(0);
251         expect(pt[1]).toEqual(0);
252
253         path.delete();
254     });
255
256     gm('offset_path', (canvas) => {
257         const path = starPath(CanvasKit);
258
259         const paint = new CanvasKit.Paint();
260         paint.setStyle(CanvasKit.PaintStyle.Stroke);
261         paint.setStrokeWidth(5.0);
262         paint.setAntiAlias(true);
263         paint.setColor(CanvasKit.BLACK);
264
265         canvas.clear(CanvasKit.WHITE);
266
267         canvas.drawPath(path, paint);
268         path.offset(80, 40);
269         canvas.drawPath(path, paint);
270
271         path.delete();
272         paint.delete();
273     });
274
275     gm('oval_path', (canvas) => {
276         const paint = new CanvasKit.Paint();
277
278         paint.setStyle(CanvasKit.PaintStyle.Stroke);
279         paint.setStrokeWidth(5.0);
280         paint.setAntiAlias(true);
281         paint.setColor(CanvasKit.BLACK);
282
283         canvas.clear(CanvasKit.WHITE);
284
285         const path = new CanvasKit.Path();
286         path.moveTo(5, 5);
287         path.lineTo(10, 120);
288         path.addOval(CanvasKit.LTRBRect(10, 20, 100, 200), false, 3);
289         path.lineTo(300, 300);
290
291         canvas.drawPath(path, paint);
292
293         path.delete();
294         paint.delete();
295     });
296
297     gm('bounds_path', (canvas) => {
298         const paint = new CanvasKit.Paint();
299
300         paint.setStyle(CanvasKit.PaintStyle.Stroke);
301         paint.setStrokeWidth(5.0);
302         paint.setAntiAlias(true);
303         paint.setColor(CanvasKit.BLACK);
304
305         canvas.clear(CanvasKit.WHITE);
306
307         const path = new CanvasKit.Path();
308         // Arbitrary points to make an interesting curve.
309         path.moveTo(97, 225);
310         path.cubicTo(20, 400, 404, 75, 243, 271);
311
312         canvas.drawPath(path, paint);
313
314         const bounds = new Float32Array(4);
315         path.getBounds(bounds);
316
317         paint.setColor(CanvasKit.BLUE);
318         paint.setStrokeWidth(3.0);
319         canvas.drawRect(bounds, paint);
320
321         path.computeTightBounds(bounds);
322         paint.setColor(CanvasKit.RED);
323         paint.setStrokeWidth(3.0);
324         canvas.drawRect(bounds, paint);
325
326         path.delete();
327         paint.delete();
328     });
329
330     gm('arcto_path', (canvas) => {
331         const paint = new CanvasKit.Paint();
332
333         paint.setStyle(CanvasKit.PaintStyle.Stroke);
334         paint.setStrokeWidth(5.0);
335         paint.setAntiAlias(true);
336         paint.setColor(CanvasKit.BLACK);
337
338         canvas.clear(CanvasKit.WHITE);
339
340         const path = new CanvasKit.Path();
341
342         // - x1, y1, x2, y2, radius
343         path.arcToTangent(40, 0, 40, 40, 40);
344         // - oval (as Rect), startAngle, sweepAngle, forceMoveTo
345         path.arcToOval(CanvasKit.LTRBRect(90, 10, 120, 200), 30, 300, true);
346         // - rx, ry, xAxisRotate, useSmallArc, isCCW, x, y
347         path.moveTo(5, 105);
348         path.arcToRotated(24, 24, 45, true, false, 82, 156);
349
350         canvas.drawPath(path, paint);
351
352         path.delete();
353         paint.delete();
354     });
355
356     gm('path_relative', (canvas) => {
357         const paint = new CanvasKit.Paint();
358         paint.setStrokeWidth(1.0);
359         paint.setAntiAlias(true);
360         paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
361         paint.setStyle(CanvasKit.PaintStyle.Stroke);
362
363         const path = new CanvasKit.Path();
364         path.rMoveTo(20, 5)
365             .rLineTo(10, 15)  // 30, 20
366             .rLineTo(10, -5);  // 40, 10
367         path.rLineTo(10, 10);  // 50, 20
368         path.rLineTo(10, -20); // 60, 0
369         path.rLineTo(-40, 5);  // 20, 5
370
371         path.moveTo(20, 80)
372             .rCubicTo(70, -70, 140, 70, 170, -70); // 90, 10, 160, 150, 190, 10
373
374         path.moveTo(36, 148)
375             .rQuadTo(30, 40, 84, -12) // 66, 188, 120, 136
376             .lineTo(36, 148);
377
378         path.moveTo(150, 180)
379             .rArcTo(24, 24, 45, true, false, -68, -24); // 82, 156
380         path.lineTo(160, 160);
381
382         canvas.drawPath(path, paint);
383
384         path.delete();
385         paint.delete();
386     });
387
388     it('can measure the contours of a path',  () => {
389         const path = new CanvasKit.Path();
390         path.moveTo(10, 10)
391             .lineTo(40, 50); // should be length 50 because of the 3/4/5 triangle rule
392
393         path.moveTo(80, 0)
394             .lineTo(80, 10)
395             .lineTo(100, 5)
396             .lineTo(80, 0);
397
398         const meas = new CanvasKit.ContourMeasureIter(path, false, 1);
399         let cont = meas.next();
400         expect(cont).toBeTruthy();
401
402         expect(cont.length()).toBeCloseTo(50.0, 3);
403         const pt = cont.getPosTan(28.7); // arbitrary point
404         expect(pt[0]).toBeCloseTo(27.22, 3); // x
405         expect(pt[1]).toBeCloseTo(32.96, 3); // y
406         expect(pt[2]).toBeCloseTo(0.6, 3);   // dy
407         expect(pt[3]).toBeCloseTo(0.8, 3);   // dy
408
409         pt.set([-1, -1, -1, -1]); // fill with sentinel values.
410         cont.getPosTan(28.7, pt); // arbitrary point again, passing in an array to copy into.
411         expect(pt[0]).toBeCloseTo(27.22, 3); // x
412         expect(pt[1]).toBeCloseTo(32.96, 3); // y
413         expect(pt[2]).toBeCloseTo(0.6, 3);   // dy
414         expect(pt[3]).toBeCloseTo(0.8, 3);   // dy
415
416         const subpath = cont.getSegment(20, 40, true); // make sure this doesn't crash
417
418         cont.delete();
419         cont = meas.next();
420         expect(cont).toBeTruthy();
421         expect(cont.length()).toBeCloseTo(51.231, 3);
422
423         cont.delete();
424         expect(meas.next()).toBeFalsy();
425
426         meas.delete();
427         path.delete();
428     });
429
430     gm('drawpoly_path', (canvas) => {
431         const paint = new CanvasKit.Paint();
432         paint.setStrokeWidth(1.0);
433         paint.setAntiAlias(true);
434         paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
435         paint.setStyle(CanvasKit.PaintStyle.Stroke);
436
437         const points = [5, 5,  30, 20,  55, 5,  55, 50,  30, 30,  5, 50];
438
439         const pointsObj = CanvasKit.Malloc(Float32Array, 6 * 2);
440         const mPoints = pointsObj.toTypedArray();
441         mPoints.set([105, 105, 130, 120, 155, 105, 155, 150, 130, 130, 105, 150]);
442
443         const path = new CanvasKit.Path();
444         path.addPoly(points, true)
445             .moveTo(100, 0)
446             .addPoly(mPoints, true);
447
448         canvas.drawPath(path, paint);
449         CanvasKit.Free(pointsObj);
450
451         path.delete();
452         paint.delete();
453     });
454
455     // Test trim, adding paths to paths, and a bunch of other path methods.
456     gm('trim_path', (canvas) => {
457         canvas.clear(CanvasKit.WHITE);
458
459         const paint = new CanvasKit.Paint();
460         paint.setStrokeWidth(1.0);
461         paint.setAntiAlias(true);
462         paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
463         paint.setStyle(CanvasKit.PaintStyle.Stroke);
464
465         const arcpath = new CanvasKit.Path();
466         arcpath.arc(400, 400, 100, 0, -90, false) // x, y, radius, startAngle, endAngle, ccw
467                .dash(3, 1, 0)
468                .conicTo(10, 20, 30, 40, 5)
469                .rConicTo(60, 70, 80, 90, 5)
470                .trim(0.2, 1, false);
471
472         const path = new CanvasKit.Path();
473         path.addArc(CanvasKit.LTRBRect(10, 20, 100, 200), 30, 300)
474             .addRect(CanvasKit.LTRBRect(200, 200, 300, 300)) // test single arg, default cw
475             .addRect(CanvasKit.LTRBRect(240, 240, 260, 260), true) // test two arg, true means ccw
476             .addRect([260, 260, 290, 290], true) // test five arg, true means ccw
477             .addRRect([300, 10, 500, 290, // Rect in LTRB order
478                        60, 60, 60, 60, 60, 60, 60, 60], // all radii are the same
479                        false) // ccw
480             .addRRect(CanvasKit.RRectXY([350, 60, 450, 240], 20, 80), true) // Rect, rx, ry, ccw
481             .addPath(arcpath)
482             .transform(0.54, -0.84,  390.35,
483                        0.84,  0.54, -114.53,
484                           0,     0,       1);
485
486         canvas.drawPath(path, paint);
487
488         path.delete();
489         paint.delete();
490     });
491
492     gm('winding_example', (canvas) => {
493         // Inspired by https://fiddle.skia.org/c/@Path_FillType_a
494         const path = new CanvasKit.Path();
495         // Draw overlapping rects on top
496         path.addRect(CanvasKit.LTRBRect(10, 10, 30, 30), false);
497         path.addRect(CanvasKit.LTRBRect(20, 20, 40, 40), false);
498         // Draw overlapping rects on bottom, with different direction lines.
499         path.addRect(CanvasKit.LTRBRect(10, 60, 30, 80), false);
500         path.addRect(CanvasKit.LTRBRect(20, 70, 40, 90), true);
501
502         expect(path.getFillType()).toEqual(CanvasKit.FillType.Winding);
503
504         // Draw the two rectangles on the left side.
505         const paint = new CanvasKit.Paint();
506         paint.setStyle(CanvasKit.PaintStyle.Stroke);
507         canvas.drawPath(path, paint);
508
509         const clipRect = CanvasKit.LTRBRect(0, 0, 51, 100);
510         paint.setStyle(CanvasKit.PaintStyle.Fill);
511
512         for (const fillType of [CanvasKit.FillType.Winding, CanvasKit.FillType.EvenOdd]) {
513             canvas.translate(51, 0);
514             canvas.save();
515             canvas.clipRect(clipRect, CanvasKit.ClipOp.Intersect, false);
516             path.setFillType(fillType);
517             canvas.drawPath(path, paint);
518             canvas.restore();
519         }
520
521         path.delete();
522         paint.delete();
523     });
524
525     gm('as_winding', (canvas) => {
526         const evenOddPath = new CanvasKit.Path();
527         // Draw overlapping rects
528         evenOddPath.addRect(CanvasKit.LTRBRect(10, 10, 70, 70), false);
529         evenOddPath.addRect(CanvasKit.LTRBRect(30, 30, 50, 50), false);
530         evenOddPath.setFillType(CanvasKit.FillType.EvenOdd);
531
532         const evenOddCmds = evenOddPath.toCmds();
533         expect(evenOddCmds).toEqual(Float32Array.of(
534           CanvasKit.MOVE_VERB, 10, 10,
535           CanvasKit.LINE_VERB, 70, 10,
536           CanvasKit.LINE_VERB, 70, 70,
537           CanvasKit.LINE_VERB, 10, 70,
538           CanvasKit.CLOSE_VERB,
539           CanvasKit.MOVE_VERB, 30, 30, // This contour is drawn
540           CanvasKit.LINE_VERB, 50, 30, // clockwise, as specified.
541           CanvasKit.LINE_VERB, 50, 50,
542           CanvasKit.LINE_VERB, 30, 50,
543           CanvasKit.CLOSE_VERB
544         ));
545
546         const windingPath = evenOddPath.makeAsWinding();
547
548         expect(windingPath.getFillType()).toBe(CanvasKit.FillType.Winding);
549         const windingCmds = windingPath.toCmds();
550         expect(windingCmds).toEqual(Float32Array.of(
551           CanvasKit.MOVE_VERB, 10, 10,
552           CanvasKit.LINE_VERB, 70, 10,
553           CanvasKit.LINE_VERB, 70, 70,
554           CanvasKit.LINE_VERB, 10, 70,
555           CanvasKit.CLOSE_VERB,
556           CanvasKit.MOVE_VERB, 30, 50, // This contour has been
557           CanvasKit.LINE_VERB, 50, 50, // re-drawn counter-clockwise
558           CanvasKit.LINE_VERB, 50, 30, // so that it covers the same
559           CanvasKit.LINE_VERB, 30, 30, // area, but with the winding fill type.
560           CanvasKit.CLOSE_VERB
561         ));
562
563         const paint = new CanvasKit.Paint();
564         paint.setStyle(CanvasKit.PaintStyle.Fill);
565         const font = new CanvasKit.Font(null, 20);
566
567         canvas.drawText('Original path (even odd)', 5, 20, paint, font);
568         canvas.translate(0, 50);
569         canvas.drawPath(evenOddPath, paint);
570
571         canvas.translate(300, 0);
572         canvas.drawPath(windingPath, paint);
573
574         canvas.translate(0, -50);
575         canvas.drawText('makeAsWinding path', 5, 20, paint, font);
576
577         evenOddPath.delete();
578         windingPath.delete();
579     });
580 });