xref: /aosp_15_r20/external/skia/modules/pathkit/tests/path.spec.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Workerdescribe('PathKit\'s Path Behavior', function() {
2*c8dee2aaSAndroid Build Coastguard Worker
3*c8dee2aaSAndroid Build Coastguard Worker    describe('Basic Path Features', function() {
4*c8dee2aaSAndroid Build Coastguard Worker        function drawSimplePath() {
5*c8dee2aaSAndroid Build Coastguard Worker            let path = PathKit.NewPath();
6*c8dee2aaSAndroid Build Coastguard Worker            path.moveTo(0, 0);
7*c8dee2aaSAndroid Build Coastguard Worker            path.lineTo(10, 0);
8*c8dee2aaSAndroid Build Coastguard Worker            path.lineTo(10, 10);
9*c8dee2aaSAndroid Build Coastguard Worker            path.close();
10*c8dee2aaSAndroid Build Coastguard Worker            return path;
11*c8dee2aaSAndroid Build Coastguard Worker        }
12*c8dee2aaSAndroid Build Coastguard Worker
13*c8dee2aaSAndroid Build Coastguard Worker        it('supports.equals()', function(done) {
14*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
15*c8dee2aaSAndroid Build Coastguard Worker                let path = drawSimplePath();
16*c8dee2aaSAndroid Build Coastguard Worker                let otherPath = drawSimplePath();
17*c8dee2aaSAndroid Build Coastguard Worker                let blank = PathKit.NewPath();
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker                expect(path.equals(path)).toBe(true);
20*c8dee2aaSAndroid Build Coastguard Worker                expect(otherPath.equals(path)).toBe(true);
21*c8dee2aaSAndroid Build Coastguard Worker                expect(path.equals(otherPath)).toBe(true);
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker                expect(path.equals(blank)).toBe(false);
24*c8dee2aaSAndroid Build Coastguard Worker                expect(otherPath.equals(blank)).toBe(false);
25*c8dee2aaSAndroid Build Coastguard Worker                expect(blank.equals(path)).toBe(false);
26*c8dee2aaSAndroid Build Coastguard Worker                expect(blank.equals(otherPath)).toBe(false);
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker                path.delete();
29*c8dee2aaSAndroid Build Coastguard Worker                otherPath.delete();
30*c8dee2aaSAndroid Build Coastguard Worker                blank.delete();
31*c8dee2aaSAndroid Build Coastguard Worker                done();
32*c8dee2aaSAndroid Build Coastguard Worker            }));
33*c8dee2aaSAndroid Build Coastguard Worker        });
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker        it('has a copy constructor', function(done) {
36*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
37*c8dee2aaSAndroid Build Coastguard Worker                let orig = drawSimplePath();
38*c8dee2aaSAndroid Build Coastguard Worker                let copy = new PathKit.SkPath(orig);
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.toSVGString()).toEqual(copy.toSVGString());
41*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.equals(copy)).toBe(true);
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker                orig.delete();
44*c8dee2aaSAndroid Build Coastguard Worker                copy.delete();
45*c8dee2aaSAndroid Build Coastguard Worker                done();
46*c8dee2aaSAndroid Build Coastguard Worker            }));
47*c8dee2aaSAndroid Build Coastguard Worker        });
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker        it('has a copy method', function(done) {
50*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
51*c8dee2aaSAndroid Build Coastguard Worker                let orig = drawSimplePath();
52*c8dee2aaSAndroid Build Coastguard Worker                let copy = orig.copy();
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.toSVGString()).toEqual(copy.toSVGString());
55*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.equals(copy)).toBe(true);
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker                orig.delete();
58*c8dee2aaSAndroid Build Coastguard Worker                copy.delete();
59*c8dee2aaSAndroid Build Coastguard Worker                done();
60*c8dee2aaSAndroid Build Coastguard Worker            }));
61*c8dee2aaSAndroid Build Coastguard Worker        });
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker        it('can create a copy with MakePath', function(done) {
64*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
65*c8dee2aaSAndroid Build Coastguard Worker                let orig = drawSimplePath();
66*c8dee2aaSAndroid Build Coastguard Worker                let copy = PathKit.NewPath(orig);
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.toSVGString()).toEqual(copy.toSVGString());
69*c8dee2aaSAndroid Build Coastguard Worker                expect(orig.equals(copy)).toBe(true);
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker                orig.delete();
72*c8dee2aaSAndroid Build Coastguard Worker                copy.delete();
73*c8dee2aaSAndroid Build Coastguard Worker                done();
74*c8dee2aaSAndroid Build Coastguard Worker            }));
75*c8dee2aaSAndroid Build Coastguard Worker        });
76*c8dee2aaSAndroid Build Coastguard Worker    });
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker    function ExpectRectsToBeEqual(actual, expected) {
79*c8dee2aaSAndroid Build Coastguard Worker        if (PathKit.usingWasm) {
80*c8dee2aaSAndroid Build Coastguard Worker            // exact match
81*c8dee2aaSAndroid Build Coastguard Worker            expect(actual).toEqual(expected);
82*c8dee2aaSAndroid Build Coastguard Worker        } else {
83*c8dee2aaSAndroid Build Coastguard Worker            // floats get rounded a little bit
84*c8dee2aaSAndroid Build Coastguard Worker            expect(actual.fLeft).toBeCloseTo(expected.fLeft, 4);
85*c8dee2aaSAndroid Build Coastguard Worker            expect(actual.fTop).toBeCloseTo(expected.fTop, 4);
86*c8dee2aaSAndroid Build Coastguard Worker            expect(actual.fRight).toBeCloseTo(expected.fRight, 4);
87*c8dee2aaSAndroid Build Coastguard Worker            expect(actual.fBottom).toBeCloseTo(expected.fBottom, 4);
88*c8dee2aaSAndroid Build Coastguard Worker        }
89*c8dee2aaSAndroid Build Coastguard Worker    }
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker    function bits2float(str) {
92*c8dee2aaSAndroid Build Coastguard Worker        return PathKit.SkBits2FloatUnsigned(parseInt(str))
93*c8dee2aaSAndroid Build Coastguard Worker    }
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker    describe('bounds and rect', function(){
96*c8dee2aaSAndroid Build Coastguard Worker        it('dynamically updates getBounds()', function(done){
97*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
98*c8dee2aaSAndroid Build Coastguard Worker                // Based on test_bounds_crbug_513799
99*c8dee2aaSAndroid Build Coastguard Worker                let path = PathKit.NewPath();
100*c8dee2aaSAndroid Build Coastguard Worker                expect(path.getBounds()).toEqual(PathKit.LTRBRect(0, 0, 0, 0));
101*c8dee2aaSAndroid Build Coastguard Worker                path.moveTo(-5, -8);
102*c8dee2aaSAndroid Build Coastguard Worker                expect(path.getBounds()).toEqual(PathKit.LTRBRect(-5, -8, -5, -8));
103*c8dee2aaSAndroid Build Coastguard Worker                path.rect(1, 2, 2, 2);
104*c8dee2aaSAndroid Build Coastguard Worker                expect(path.getBounds()).toEqual(PathKit.LTRBRect(-5, -8, 3, 4));
105*c8dee2aaSAndroid Build Coastguard Worker                path.moveTo(1, 2);
106*c8dee2aaSAndroid Build Coastguard Worker                expect(path.getBounds()).toEqual(PathKit.LTRBRect(-5, -8, 3, 4));
107*c8dee2aaSAndroid Build Coastguard Worker                path.delete();
108*c8dee2aaSAndroid Build Coastguard Worker                done();
109*c8dee2aaSAndroid Build Coastguard Worker            }));
110*c8dee2aaSAndroid Build Coastguard Worker        });
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker        it('has getBounds() and computeTightBounds()', function(done){
113*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
114*c8dee2aaSAndroid Build Coastguard Worker                // Based on PathOpsTightBoundsIllBehaved
115*c8dee2aaSAndroid Build Coastguard Worker                let path = PathKit.NewPath();
116*c8dee2aaSAndroid Build Coastguard Worker                path.moveTo(1, 1);
117*c8dee2aaSAndroid Build Coastguard Worker                path.quadraticCurveTo(4, 3, 2, 2);
118*c8dee2aaSAndroid Build Coastguard Worker                expect(path.getBounds()).toEqual(PathKit.LTRBRect(1, 1, 4, 3));
119*c8dee2aaSAndroid Build Coastguard Worker                ExpectRectsToBeEqual(path.computeTightBounds(),
120*c8dee2aaSAndroid Build Coastguard Worker                                     PathKit.LTRBRect(1, 1,
121*c8dee2aaSAndroid Build Coastguard Worker                                        bits2float("0x40333334"),  // 2.8
122*c8dee2aaSAndroid Build Coastguard Worker                                        bits2float("0x40155556"))); // 2.3333333
123*c8dee2aaSAndroid Build Coastguard Worker                path.delete();
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker                done();
126*c8dee2aaSAndroid Build Coastguard Worker            }));
127*c8dee2aaSAndroid Build Coastguard Worker        });
128*c8dee2aaSAndroid Build Coastguard Worker    });
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker    function ExpectCmdsToBeEqual(actual, expected) {
131*c8dee2aaSAndroid Build Coastguard Worker        if (PathKit.usingWasm) {
132*c8dee2aaSAndroid Build Coastguard Worker            // exact match
133*c8dee2aaSAndroid Build Coastguard Worker            expect(actual).toEqual(expected);
134*c8dee2aaSAndroid Build Coastguard Worker        } else {
135*c8dee2aaSAndroid Build Coastguard Worker            // lossy match
136*c8dee2aaSAndroid Build Coastguard Worker            actual.every((cmd, cmdIdx) => {
137*c8dee2aaSAndroid Build Coastguard Worker                cmd.every((arg, argIdx) => {
138*c8dee2aaSAndroid Build Coastguard Worker                    // The asm.js code is close to the wasm/c++ output, but not quite.
139*c8dee2aaSAndroid Build Coastguard Worker                    expect(arg).toBeCloseTo(expected[cmdIdx][argIdx], 4)
140*c8dee2aaSAndroid Build Coastguard Worker                });
141*c8dee2aaSAndroid Build Coastguard Worker            });
142*c8dee2aaSAndroid Build Coastguard Worker        }
143*c8dee2aaSAndroid Build Coastguard Worker    }
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker    describe('Command arrays', function(){
146*c8dee2aaSAndroid Build Coastguard Worker        it('does NOT approximates conics when dumping as toCmds', function(done) {
147*c8dee2aaSAndroid Build Coastguard Worker            LoadPathKit.then(catchException(done, () => {
148*c8dee2aaSAndroid Build Coastguard Worker                let path = PathKit.NewPath();
149*c8dee2aaSAndroid Build Coastguard Worker                path.moveTo(20, 120);
150*c8dee2aaSAndroid Build Coastguard Worker                path.arc(20, 120, 18, 0, 1.75 * Math.PI);
151*c8dee2aaSAndroid Build Coastguard Worker                path.lineTo(20, 120);
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker                let expectedCmds = [
154*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.MOVE_VERB, 20, 120],
155*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.LINE_VERB, 38, 120],
156*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.CONIC_VERB, 38, 138, 20, 138, bits2float("0x3f3504f3)")], // 0.707107f
157*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.CONIC_VERB, 2, 138, 2, 120, bits2float("0x3f3504f3)")],   // 0.707107f
158*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.CONIC_VERB, 2, 102, 20, 102, bits2float("0x3f3504f3)")],  // 0.707107f
159*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.CONIC_VERB, bits2float("0x41dba58e"), 102, bits2float("0x4202e962"), bits2float("0x42d68b4d"), bits2float("0x3f6c8361")],  // 27.4558, 102, 32.7279, 107.272, 0.92388
160*c8dee2aaSAndroid Build Coastguard Worker                    [PathKit.LINE_VERB, 20, 120],
161*c8dee2aaSAndroid Build Coastguard Worker                ];
162*c8dee2aaSAndroid Build Coastguard Worker                ExpectCmdsToBeEqual(path.toCmds(), expectedCmds);
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker                path.delete();
165*c8dee2aaSAndroid Build Coastguard Worker                done();
166*c8dee2aaSAndroid Build Coastguard Worker            }));
167*c8dee2aaSAndroid Build Coastguard Worker        });
168*c8dee2aaSAndroid Build Coastguard Worker    });
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker});
171