xref: /aosp_15_r20/external/skia/modules/pathkit/tests/effects.spec.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1
2describe('PathKit\'s Path Behavior', function() {
3    // see https://fiddle.skia.org/c/@discrete_path
4    function drawStar() {
5        let path = PathKit.NewPath();
6        let R = 115.2, C = 128.0;
7        path.moveTo(C + R + 22, C);
8        for (let i = 1; i < 8; i++) {
9            let a = 2.6927937 * i;
10            path.lineTo(C + R * Math.cos(a) + 22, C + R * Math.sin(a));
11        }
12        path.closePath();
13        return path;
14    }
15
16    describe('Dash Path Effect', function() {
17        it('performs dash in-place with start, stop, phase', function(done) {
18            LoadPathKit.then(catchException(done, () => {
19                let orig = drawStar();
20                let dashed = drawStar();
21                let notACopy = dashed.dash(10, 3, 0);
22                let phased = drawStar().dash(10, 3, 2);
23
24                expect(dashed === notACopy).toBe(true);
25                expect(dashed.equals(phased)).toBe(false);
26                expect(dashed.equals(orig)).toBe(false);
27
28                reportPath(dashed, 'dashed_no_phase', () => {
29                    reportPath(phased, 'dashed_with_phase', done);
30                    orig.delete();
31                    dashed.delete();
32                    phased.delete();
33                });
34            }));
35        });
36    });
37
38    describe('Trim Path Effect', function() {
39        it('performs trim in-place with start, stop, phase', function(done) {
40            LoadPathKit.then(catchException(done, () => {
41                let orig = drawStar();
42                let trimmed = drawStar();
43                let notACopy = trimmed.trim(0.25, .8);
44                let complement = drawStar().trim(.1, .9, true);
45
46                expect(trimmed === notACopy).toBe(true);
47                expect(trimmed.equals(complement)).toBe(false);
48                expect(trimmed.equals(orig)).toBe(false);
49                expect(complement.equals(orig)).toBe(false);
50
51                reportPath(trimmed, 'trimmed_non_complement', () => {
52                    reportPath(complement, 'trimmed_complement', done);
53                    orig.delete();
54                    trimmed.delete();
55                    complement.delete();
56                });
57            }));
58        });
59    });
60
61    describe('Transform Path Effect', function() {
62        it('performs matrix transform in-place', function(done) {
63            LoadPathKit.then(catchException(done, () => {
64                let orig = drawStar();
65                let scaled = drawStar();
66                let notACopy = scaled.transform(3, 0, 0,
67                                                0, 3, 0,
68                                                0, 0, 1);
69
70                let scaled2 = drawStar().transform([3, 0, 0,
71                                                    0, 3, 0,
72                                                    0, 0, 1]);
73
74                expect(scaled === notACopy).toBe(true);
75                expect(scaled.equals(scaled2)).toBe(true);
76                expect(scaled.equals(orig)).toBe(false);
77
78                reportPath(scaled, 'transformed_scale', () => {
79                    reportPath(scaled2, 'transformed_scale2', done);
80                    orig.delete();
81                    scaled.delete();
82                    scaled2.delete();
83                });
84            }));
85        });
86    });
87
88    describe('Stroke Path Effect', function() {
89        it('creates a stroked path in-place', function(done) {
90            LoadPathKit.then(catchException(done, () => {
91                let orig = drawStar();
92                let stroked = drawStar();
93                let notACopy = stroked.stroke({
94                    width: 15,
95                    join: PathKit.StrokeJoin.BEVEL,
96                    cap: PathKit.StrokeCap.BUTT,
97                    miter_limit: 2,
98                });
99
100                // Don't have to specify all of the fields, defaults will
101                // be used instead.
102                let rounded = drawStar().stroke({
103                    width: 10,
104                    join: PathKit.StrokeJoin.ROUND,
105                    cap:PathKit.StrokeCap.SQUARE,
106                });
107
108                expect(stroked === notACopy).toBe(true);
109                expect(stroked.equals(rounded)).toBe(false);
110                expect(stroked.equals(orig)).toBe(false);
111
112                reportPath(stroked, 'stroke_bevel_butt', () => {
113                    reportPath(rounded, 'stroke_round_square', done);
114                    orig.delete();
115                    stroked.delete();
116                    rounded.delete();
117                });
118            }));
119        });
120
121        it('can use res_scale for more precision', function(done) {
122            LoadPathKit.then(catchException(done, () => {
123                let canvas = document.createElement('canvas');
124                let ctx = canvas.getContext('2d');
125                // Set canvas size and make it a bit bigger to zoom in on the lines
126                standardizedCanvasSize(ctx);
127
128                const circle = PathKit.NewPath();
129                circle.ellipse(0, 0, 1, 1, 0, 0, Math.PI * 2);
130
131                let scales = [1, 3, 5,
132                              10, 30, 100];
133
134                // White background
135                ctx.fillStyle = 'white';
136                ctx.fillRect(0, 0, canvas.width, canvas.height);
137
138                for (let i = 0; i < scales.length; i++) {
139                    ctx.save();
140                    const row = Math.floor(i / 3);
141                    const col = i % 3;
142                    ctx.translate(100 * col + 50, 100 * row + 50);
143                    ctx.scale(30, 30);
144
145                    // Grey circle
146                    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
147                    ctx.beginPath();
148                    circle.toCanvas(ctx);
149                    ctx.fill();
150
151                    // Pink stroke, with given res_scale option
152                    const line = circle.copy().stroke({
153                        width: 0.5,
154                        res_scale: scales[i],
155                    });
156                    ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
157                    ctx.beginPath();
158                    line.toCanvas(ctx);
159                    ctx.fill();
160
161                    line.delete();
162                    ctx.restore();
163                }
164                ctx.fillStyle = 'black';
165                ctx.font = '14px serif';
166                ctx.fillText('notice for lower res_scale values, the stroked circles ' +
167                             '(pink) are not round',
168                             10, 200);
169
170                circle.delete();
171                reportCanvas(canvas, 'res_scale').then(() => {
172                    done();
173                }).catch(reportError(done));
174            }));
175        });
176    });
177
178});
179