• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1describe('CanvasKit\'s Path Behavior', function() {
2    let container = document.createElement('div');
3    document.body.appendChild(container);
4    const CANVAS_WIDTH = 600;
5    const CANVAS_HEIGHT = 600;
6
7    beforeEach(function() {
8        container.innerHTML = `
9            <canvas width=600 height=600 id=test></canvas>
10            <canvas width=600 height=600 id=report></canvas>`;
11    });
12
13    afterEach(function() {
14        container.innerHTML = '';
15    });
16
17    it('can draw a path', function(done) {
18        LoadCanvasKit.then(catchException(done, () => {
19            // This is taken from example.html
20            const surface = CanvasKit.MakeCanvasSurface('test');
21            expect(surface).toBeTruthy('Could not make surface')
22            if (!surface) {
23                done();
24                return;
25            }
26            const canvas = surface.getCanvas();
27            const paint = new CanvasKit.SkPaint();
28            paint.setStrokeWidth(1.0);
29            paint.setAntiAlias(true);
30            paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
31            paint.setStyle(CanvasKit.PaintStyle.Stroke);
32
33            const path = new CanvasKit.SkPath();
34            path.moveTo(20, 5);
35            path.lineTo(30, 20);
36            path.lineTo(40, 10);
37            path.lineTo(50, 20);
38            path.lineTo(60, 0);
39            path.lineTo(20, 5);
40
41            path.moveTo(20, 80);
42            path.cubicTo(90, 10, 160, 150, 190, 10);
43
44            path.moveTo(36, 148);
45            path.quadTo(66, 188, 120, 136);
46            path.lineTo(36, 148);
47
48            path.moveTo(150, 180);
49            path.arcTo(150, 100, 50, 200, 20);
50            path.lineTo(160, 160);
51
52            path.moveTo(20, 120);
53            path.lineTo(20, 120);
54
55            path.transform([2, 0, 0,
56                            0, 2, 0,
57                            0, 0, 1 ])
58
59            canvas.drawPath(path, paint);
60
61            let rrect = new CanvasKit.SkPath()
62                               .addRoundRect(100, 10, 140, 62,
63                                             10, 4, true);
64
65            canvas.drawPath(rrect, paint);
66            rrect.delete();
67
68            surface.flush();
69
70            path.delete();
71            paint.delete();
72
73            reportSurface(surface, 'path_api_example', done);
74        }));
75        // See PathKit for more tests, since they share implementation
76    });
77
78    it('can create a path from an SVG string', function(done) {
79        LoadCanvasKit.then(catchException(done, () => {
80            //.This is a parallelagram from
81            // https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg
82            let path = CanvasKit.MakePathFromSVGString('M 205,5 L 795,5 L 595,295 L 5,295 L 205,5 z');
83
84            let cmds = path.toCmds();
85            expect(cmds).toBeTruthy();
86            // 1 move, 4 lines, 1 close
87            // each element in cmds is an array, with index 0 being the verb, and the rest being args
88            expect(cmds.length).toBe(6);
89            expect(cmds).toEqual([[CanvasKit.MOVE_VERB, 205, 5],
90                                  [CanvasKit.LINE_VERB, 795, 5],
91                                  [CanvasKit.LINE_VERB, 595, 295],
92                                  [CanvasKit.LINE_VERB, 5, 295],
93                                  [CanvasKit.LINE_VERB, 205, 5],
94                                  [CanvasKit.CLOSE_VERB]]);
95            path.delete();
96            done();
97        }));
98    });
99
100    it('can create an SVG string from a path', function(done) {
101        LoadCanvasKit.then(catchException(done, () => {
102            let cmds = [[CanvasKit.MOVE_VERB, 205, 5],
103                       [CanvasKit.LINE_VERB, 795, 5],
104                       [CanvasKit.LINE_VERB, 595, 295],
105                       [CanvasKit.LINE_VERB, 5, 295],
106                       [CanvasKit.LINE_VERB, 205, 5],
107                       [CanvasKit.CLOSE_VERB]];
108            let path = CanvasKit.MakePathFromCmds(cmds);
109
110            let svgStr = path.toSVGString();
111            // We output it in terse form, which is different than Wikipedia's version
112            expect(svgStr).toEqual('M205 5L795 5L595 295L5 295L205 5Z');
113            path.delete();
114            done();
115        }));
116    });
117
118    it('uses offset to transform the path with dx,dy', function(done) {
119        LoadCanvasKit.then(catchException(done, () => {
120            const surface = CanvasKit.MakeCanvasSurface('test');
121            expect(surface).toBeTruthy('Could not make surface')
122            if (!surface) {
123                done();
124                return;
125            }
126            const canvas = surface.getCanvas();
127            const path = starPath(CanvasKit);
128
129            const paint = new CanvasKit.SkPaint();
130
131            paint.setStyle(CanvasKit.PaintStyle.Stroke);
132            paint.setStrokeWidth(5.0);
133            paint.setAntiAlias(true);
134            paint.setColor(CanvasKit.BLACK);
135
136            canvas.clear(CanvasKit.WHITE);
137
138            canvas.drawPath(path, paint);
139            path.offset(80, 40);
140            canvas.drawPath(path, paint);
141            surface.flush();
142            path.delete();
143            paint.delete();
144
145            reportSurface(surface, 'offset_path', done);
146        }));
147    });
148
149    it('draws ovals', function(done) {
150        LoadCanvasKit.then(catchException(done, () => {
151            const surface = CanvasKit.MakeCanvasSurface('test');
152            expect(surface).toBeTruthy('Could not make surface')
153            if (!surface) {
154                done();
155                return;
156            }
157            const canvas = surface.getCanvas();
158            const paint = new CanvasKit.SkPaint();
159
160            paint.setStyle(CanvasKit.PaintStyle.Stroke);
161            paint.setStrokeWidth(5.0);
162            paint.setAntiAlias(true);
163            paint.setColor(CanvasKit.BLACK);
164
165            canvas.clear(CanvasKit.WHITE);
166
167            const path = new CanvasKit.SkPath();
168            path.moveTo(5, 5);
169            path.lineTo(10, 120);
170            path.addOval(CanvasKit.LTRBRect(10, 20, 100, 200), false, 3);
171            path.lineTo(300, 300);
172
173            canvas.drawPath(path, paint);
174            surface.flush();
175            path.delete();
176            paint.delete();
177
178            reportSurface(surface, 'oval_path', done);
179        }));
180    });
181
182    it('draws arcTo in a multitude of ways', function(done) {
183        LoadCanvasKit.then(catchException(done, () => {
184            const surface = CanvasKit.MakeCanvasSurface('test');
185            expect(surface).toBeTruthy('Could not make surface')
186            if (!surface) {
187                done();
188                return;
189            }
190            const canvas = surface.getCanvas();
191            const paint = new CanvasKit.SkPaint();
192
193            paint.setStyle(CanvasKit.PaintStyle.Stroke);
194            paint.setStrokeWidth(5.0);
195            paint.setAntiAlias(true);
196            paint.setColor(CanvasKit.BLACK);
197
198            canvas.clear(CanvasKit.WHITE);
199
200            const path = new CanvasKit.SkPath();
201            //path.moveTo(5, 5);
202            // takes 4, 5 or 7 args
203            // - 5 x1, y1, x2, y2, radius
204            path.arcTo(40, 0, 40, 40, 40);
205            // - 4 oval (as Rect), startAngle, sweepAngle, forceMoveTo
206            path.arcTo(CanvasKit.LTRBRect(90, 10, 120, 200), 30, 300, true);
207            // - 7 rx, ry, xAxisRotate, useSmallArc, isCCW, x, y
208            path.moveTo(5, 105);
209            path.arcTo(24, 24, 45, true, false, 82, 156);
210
211            canvas.drawPath(path, paint);
212            surface.flush();
213            path.delete();
214            paint.delete();
215
216            reportSurface(surface, 'arcto_path', done);
217        }));
218    });
219
220    it('can draw a path using relative functions', function(done) {
221        LoadCanvasKit.then(catchException(done, () => {
222            // This is taken from example.html
223            const surface = CanvasKit.MakeCanvasSurface('test');
224            expect(surface).toBeTruthy('Could not make surface')
225            if (!surface) {
226                done();
227                return;
228            }
229            const canvas = surface.getCanvas();
230            const paint = new CanvasKit.SkPaint();
231            paint.setStrokeWidth(1.0);
232            paint.setAntiAlias(true);
233            paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
234            paint.setStyle(CanvasKit.PaintStyle.Stroke);
235
236            const path = new CanvasKit.SkPath();
237            path.rMoveTo(20, 5)
238                .rLineTo(10, 15)  // 30, 20
239                .rLineTo(10, -5);  // 40, 10
240            path.rLineTo(10, 10);  // 50, 20
241            path.rLineTo(10, -20); // 60, 0
242            path.rLineTo(-40, 5);  // 20, 5
243
244            path.moveTo(20, 80)
245                .rCubicTo(70, -70, 140, 70, 170, -70); // 90, 10, 160, 150, 190, 10
246
247            path.moveTo(36, 148)
248                .rQuadTo(30, 40, 84, -12) // 66, 188, 120, 136
249                .lineTo(36, 148);
250
251            path.moveTo(150, 180)
252                .rArcTo(24, 24, 45, true, false, -68, -24); // 82, 156
253            path.lineTo(160, 160);
254
255            canvas.drawPath(path, paint);
256
257            surface.flush();
258            path.delete();
259            paint.delete();
260
261            reportSurface(surface, 'path_relative', done);
262        }));
263    });
264
265    it('can measure a path', function(done) {
266        LoadCanvasKit.then(catchException(done, () => {
267
268            const path = new CanvasKit.SkPath();
269            path.moveTo(10, 10)
270                .lineTo(40, 50); // should be length 50 because of the 3/4/5 triangle rule
271
272            path.moveTo(80, 0)
273                .lineTo(80, 10)
274                .lineTo(100, 5)
275                .lineTo(80, 0);
276
277            const meas = new CanvasKit.SkPathMeasure(path, false, 1);
278            expect(meas.getLength()).toBeCloseTo(50.0, 3);
279            const pt = meas.getPosTan(28.7); // arbitrary point
280            expect(pt[0]).toBeCloseTo(27.22, 3); // x
281            expect(pt[1]).toBeCloseTo(32.96, 3); // y
282            expect(pt[2]).toBeCloseTo(0.6, 3);   // dy
283            expect(pt[3]).toBeCloseTo(0.8, 3);   // dy
284            const subpath = meas.getSegment(20, 40, true); // make sure this doesn't crash
285
286            expect(meas.nextContour()).toBeTruthy();
287            expect(meas.getLength()).toBeCloseTo(51.231, 3);
288
289            expect(meas.nextContour()).toBeFalsy();
290
291            path.delete();
292            done();
293        }));
294    });
295
296    it('can measure the contours of a path', function(done) {
297        LoadCanvasKit.then(catchException(done, () => {
298
299            const path = new CanvasKit.SkPath();
300            path.moveTo(10, 10)
301                .lineTo(40, 50); // should be length 50 because of the 3/4/5 triangle rule
302
303            path.moveTo(80, 0)
304                .lineTo(80, 10)
305                .lineTo(100, 5)
306                .lineTo(80, 0);
307
308            const meas = new CanvasKit.SkContourMeasureIter(path, false, 1);
309            let cont = meas.next();
310            expect(cont).toBeTruthy();
311
312            expect(cont.length()).toBeCloseTo(50.0, 3);
313            const pt = cont.getPosTan(28.7); // arbitrary point
314            expect(pt[0]).toBeCloseTo(27.22, 3); // x
315            expect(pt[1]).toBeCloseTo(32.96, 3); // y
316            expect(pt[2]).toBeCloseTo(0.6, 3);   // dy
317            expect(pt[3]).toBeCloseTo(0.8, 3);   // dy
318            const subpath = cont.getSegment(20, 40, true); // make sure this doesn't crash
319
320            cont.delete();
321            cont = meas.next();
322            expect(cont).toBeTruthy()
323            expect(cont.length()).toBeCloseTo(51.231, 3);
324
325            cont.delete();
326            expect(meas.next()).toBeFalsy();
327
328            meas.delete();
329            path.delete();
330            done();
331        }));
332    });
333
334    it('can draw a polygon', function(done) {
335        LoadCanvasKit.then(catchException(done, () => {
336            // This is taken from example.html
337            const surface = CanvasKit.MakeCanvasSurface('test');
338            expect(surface).toBeTruthy('Could not make surface')
339            if (!surface) {
340                done();
341                return;
342            }
343            const canvas = surface.getCanvas();
344            const paint = new CanvasKit.SkPaint();
345            paint.setStrokeWidth(1.0);
346            paint.setAntiAlias(true);
347            paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
348            paint.setStyle(CanvasKit.PaintStyle.Stroke);
349
350            const points = [[5, 5], [30, 20], [55, 5], [55, 50], [30, 30], [5, 50]];
351
352            const mPoints = CanvasKit.Malloc(Float32Array, 6 * 2);
353            mPoints.set([105, 105, 130, 120, 155, 105, 155, 150, 130, 130, 105, 150]);
354
355            const path = new CanvasKit.SkPath();
356            path.addPoly(points, true)
357                .moveTo(100, 0)
358                .addPoly(mPoints, true);
359
360            canvas.drawPath(path, paint);
361
362            surface.flush();
363            path.delete();
364            paint.delete();
365
366            reportSurface(surface, 'drawpoly_path', done);
367        }));
368    });
369});
370