svg-pathdata
Version:
Manipulate SVG path data (path[d] attribute content) simply and efficiently.
105 lines (85 loc) • 3.68 kB
text/typescript
import { describe, test, expect } from '@jest/globals';
import { SVGPathData } from '../index.js';
function testNormalizeHVZ(input, expected) {
expect(new SVGPathData(input).normalizeHVZ().encode()).toEqual(
new SVGPathData(expected).encode(),
);
}
describe('HVZA normalization', () => {
// currently z/Z is always absolute
test('should transform relative h v z', () => {
testNormalizeHVZ(
'm 10 10 h 100 v 100 z',
'm 10 10 l 100 0 l 0 100 L 10 10',
);
});
test('should transform absolute h v z', () => {
testNormalizeHVZ(
'M 10 10 H 100 V 100 Z',
'M 10 10 L 100 10 L 100 100 L 10 10',
);
});
test('should transform degenerate arcs', () => {
testNormalizeHVZ(
'M 10 10 A 0 10 0 0 0 100 100 a 20 0 0 0 0 20 0',
'M 10 10 L 100 100 l 20 0',
);
});
test('should transform bezier curves that are lines', () => {
// Cubic bezier with all control points on the same line
// M10,10 C40,20 70,30 100,40 (start at 10,10, end at 100,40, control points at 40,20 and 70,30)
// This is a straight line because all points are collinear
testNormalizeHVZ('M 10 10 C 40 20 70 30 100 40', 'M 10 10 L 100 40');
// Same test with relative coordinates
testNormalizeHVZ('M 10 10 c 30 10 60 20 90 30', 'M 10 10 l 90 30');
// Simple horizontal line
testNormalizeHVZ('M 10 10 C 40 10 70 10 100 10', 'M 10 10 L 100 10');
// Simple vertical line
testNormalizeHVZ('M 10 10 C 10 40 10 70 10 100', 'M 10 10 L 10 100');
// Control points on line but outside the segment - should NOT be linearized
testNormalizeHVZ(
'M 50 50 C 0 0 150 150 100 100',
'M 50 50 C 0 0 150 150 100 100',
);
// Control points not on line - should not be linearized
testNormalizeHVZ(
'M 10 10 C 40 60 70 -10 100 40',
'M 10 10 C 40 60 70 -10 100 40',
);
// One control point on line, the other not - should not be linearized
testNormalizeHVZ(
'M 10 10 C 40 20 70 60 100 40',
'M 10 10 C 40 20 70 60 100 40',
);
});
test('should transform quad curves that are lines', () => {
// Quadratic bezier with control point on the same line
// M10,10 Q55,25 100,40 (start at 10,10, end at 100,40, control point at 55,25)
// This is a straight line because all points are collinear
testNormalizeHVZ('M 10 10 Q 55 25 100 40', 'M 10 10 L 100 40');
// Same test with relative coordinates
testNormalizeHVZ('M 10 10 q 45 15 90 30', 'M 10 10 l 90 30');
// Simple horizontal line
testNormalizeHVZ('M 10 10 Q 55 10 100 10', 'M 10 10 L 100 10');
// Simple vertical line
testNormalizeHVZ('M 10 10 Q 10 55 10 100', 'M 10 10 L 10 100');
// Control point on line but outside the segment - should NOT be linearized
testNormalizeHVZ('M 50 50 Q 150 150 100 100', 'M 50 50 Q 150 150 100 100');
// Control point not on line - should not be linearized
testNormalizeHVZ('M 10 10 Q 55 60 100 40', 'M 10 10 Q 55 60 100 40');
});
test('should properly handle edge cases for curve normalization', () => {
// Closed shape with multiple curve segments
testNormalizeHVZ(
'M 10 10 C 20 10 30 10 40 10 C 40 20 40 30 40 40 C 30 40 20 40 10 40 C 10 30 10 20 10 10 Z',
'M 10 10 L 40 10 L 40 40 L 10 40L10 10 L 10 10',
);
// Nearly collinear but with minor deviation - should not be linearized
testNormalizeHVZ(
'M 10 10 C 40 20.001 70 30.001 100 40',
'M 10 10 C 40 20.001 70 30.001 100 40',
);
// Zero-length segment with collinear control points - should be linearized
testNormalizeHVZ('M 50 50 C 50 50 50 50 50 50', 'M 50 50 L 50 50');
});
});