UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

135 lines (131 loc) 5.81 kB
import { getPathSegmentsInfo, parsePath, makePathSimpler, getRegularPolygonPath, joinPath, } from '.'; import type { TSimplePathData } from './typedefs'; describe('Path Utils', () => { describe('parsePath', () => { const path = 'M 2 5 l 2 -2 L 4 4 h 3 H 9 C 8 3 10 3 10 3 c 1 -1 2 0 1 1 S 8 5 9 7 v 1 s 2 -1 1 2 Q 9 10 10 11 T 12 11 t -1 -1 v 2 T 10 12 S 9 12 7 11 c 0 -1 0 -1 -2 -2 z m 0 2 l 1 0 l 0 1 l -1 0 z M 1 1 a 1 1 30 1 0 2 2 A 2 2 30 1 0 6 6'; test('can parse path string', () => { const parsed = parsePath(path); expect(parsed).toMatchSnapshot(); const simplified = makePathSimpler(parsed); expect(simplified).toMatchSnapshot(); }); test('Path written with uncommon scenario', () => { const path = 'a10.56 10.56 0 00-1.484-.133a10.56 , 10.56 0, 0,0-1.484-.133a10.56 , 10.56 0, 0,0-1.484-.133a1.056e+1 , 105.6e-1,0,0,0-1.484-.133'; const parsed = parsePath(path); expect(parsed[0]).toEqual(parsed[1]); expect(parsed[1]).toEqual(parsed[2]); expect(parsed[2]).toEqual(parsed[3]); expect(parsed).toMatchSnapshot(); }); test('fabric.util.parsePath can parse arcs correctly when no spaces between flags', () => { const pathWithWeirdArc = 'a10.56 10.56 0 00-1.484-.133'; const expected = ['a', 10.56, 10.56, 0, 0, 0, -1.484, -0.133]; const parsed = parsePath(pathWithWeirdArc); const command = parsed[0]; expect(command).toEqual(expected); }); test('getPathSegmentsInfo', () => { const parsed = makePathSimpler(parsePath(path)); const infos = getPathSegmentsInfo(parsed); // 'the command 0 a M has a length 0'); expect(infos[0].length).toBe(0); // 'the command 1 a L has a length 2.828', expect(infos[1].length.toFixed(5)).toBe('2.82843'); // 'the command 2 a L with one step on Y has a length 1', expect(infos[2].length).toBe(1); // 'the command 3 a L with 3 step on X has a length 3' expect(infos[3].length).toBe(3); // 'the command 4 a L with 2 step on X has a length 0', expect(infos[4].length).toBe(2); // 'the command 5 a C has a approximated length of 2.062', expect(infos[5].length.toFixed(5)).toBe('2.06242'); // 'the command 6 a C has a approximated length of 2.828', expect(infos[6].length.toFixed(5)).toBe('2.82832'); // 'the command 7 a C has a approximated length of 4.189', expect(infos[7].length.toFixed(5)).toBe('4.18970'); // 'the command 8 a L with 1 step on the Y has an exact length of 1', expect(infos[8].length).toBe(1); // 'the command 9 a C has a approximated length of 3.227', expect(infos[9].length.toFixed(5)).toBe('3.22727'); // 'the command 10 a Q has a approximated length of 1.540', expect(infos[10].length.toFixed(5)).toBe('1.54026'); // 'the command 11 a Q has a approximated length of 2.295', expect(infos[11].length.toFixed(5)).toBe('2.29556'); }); test('fabric.util.getPathSegmentsInfo test Z command', () => { const parsed = makePathSimpler(parsePath('M 0 0 h 20, v 20 L 0, 20 Z')); const infos = getPathSegmentsInfo(parsed); // 'the command 0 a M has a length 0' expect(infos[0].length).toBe(0); // 'the command 1 a L has length 20' expect(infos[1].length).toBe(20); // 'the command 2 a L has length 20' expect(infos[2].length).toBe(20); // 'the command 3 a L has length 20' expect(infos[3].length).toBe(20); // 'the command 4 a Z has length 20' expect(infos[4].length).toBe(20); }); }); test('fabric.util.getRegularPolygonPath', () => { const penta = getRegularPolygonPath(5, 50); const hexa = getRegularPolygonPath(6, 50); // 'regular pentagon should match', expect(penta).toMatchSnapshot(); // 'regular hexagon should match', expect(hexa).toMatchSnapshot(); }); test('fabric.util.joinPath', () => { const pathData: TSimplePathData = [ ['M', 3.12345678, 2.12345678], ['L', 1.00001111, 2.40001111], ['Z'], ] as const; const digit = 2; const expected = 'M 3.12 2.12 L 1 2.4 Z'; const result = joinPath(pathData, digit); expect(result).toBe(expected); }); test('fabric.util.joinPath without rounding', () => { const pathData: TSimplePathData = [ ['M', 3.12345678, 2.12345678], ['L', 1.00001111, 2.40001111], ['Z'], ] as const; const expected = 'M 3.12345678 2.12345678 L 1.00001111 2.40001111 Z'; const result = joinPath(pathData); expect(result).toBe(expected); }); describe('makePathSimpler', () => { test('can parse paths that return NaN segments', () => { expect( makePathSimpler( parsePath( 'M22,6.58a1.21,1.21,0,0,1-.38-.12c0-.2.12-.2.09-.5l0-.06c0,.09,0,.1-.06,0s-.1-.29-.07-.44.18.19.14-.18c-.07,0-.21-.2-.21,0h.05v.45c0-.16-.07.11-.12-.15,0-.05.06-.05.08-.09s-.11,0-.15-.07l.06.09a.35.35,0,0,1-.16.24h-.06c0-.1-.11-.11-.1-.29s.07.07.05,0c0-.24-.06,0-.11-.21,0,.15-.05.24,0,.41-.05-.1-.07.15-.14,0a.32.32,0,0,1,0,.12s-.05,0-.07.06l0,0s0,0,0,0,0-.21.06-.35h0s.06,0,0,0l0-.1c0-.27.07-.54.09-.66v.14c0-.34.13,0,.14-.27,0,0,0,.07,0,.08s0-.44.14-.23l0,.16a1.17,1.17,0,0,0,0-.32c0,.06,0,.13-.1.1a1.13,1.13,0,0,1,0-.23l0,0v0l0,0a.11.11,0,0,0,0,0,.11.11,0,0,1,0-.06', ), ), ).toMatchSnapshot(); }); }); describe('getPathSegmentsInfo', () => { test('operates as expected', () => { const data = getPathSegmentsInfo([ ['M', 50, 50], ['Q', 50, 50, 75, 75], ['Q', 100, 100, 75, 150], ['Q', 50, 200, 225, 175], ['Q', 400, 150, 450, 325], ['L', 500, 500], ]); expect(data).toMatchSnapshot(); }); }); });