forked from jkroso/normalize-svg-path
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
122 lines (110 loc) · 2.61 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict'
module.exports = normalize
var arcToCurve = require('svg-arc-to-cubic-bezier')
function normalize(path){
// init state
var prev
var result = []
var bezierX = 0
var bezierY = 0
var startX = 0
var startY = 0
var quadX = null
var quadY = null
var x = 0
var y = 0
for (var i = 0, len = path.length; i < len; i++) {
var seg = path[i]
var command = seg[0]
switch (command) {
case 'M':
startX = seg[1]
startY = seg[2]
break
case 'A':
var curves = arcToCurve({
px: x,
py: y,
cx: seg[6],
cy: seg[7],
rx: seg[1],
ry: seg[2],
xAxisRotation: seg[3],
largeArcFlag: seg[4],
sweepFlag: seg[5]
})
// null-curves
if (!curves.length) continue
for (var j = 0, c; j < curves.length; j++) {
c = curves[j]
seg = ['C', c.x1, c.y1, c.x2, c.y2, c.x, c.y]
if (j < curves.length - 1) result.push(seg)
}
break
case 'S':
// default control point
var cx = x
var cy = y
if (prev == 'C' || prev == 'S') {
cx += cx - bezierX // reflect the previous command's control
cy += cy - bezierY // point relative to the current point
}
seg = ['C', cx, cy, seg[1], seg[2], seg[3], seg[4]]
break
case 'T':
if (prev == 'Q' || prev == 'T') {
quadX = x * 2 - quadX // as with 'S' reflect previous control point
quadY = y * 2 - quadY
} else {
quadX = x
quadY = y
}
seg = quadratic(x, y, quadX, quadY, seg[1], seg[2])
break
case 'Q':
quadX = seg[1]
quadY = seg[2]
seg = quadratic(x, y, seg[1], seg[2], seg[3], seg[4])
break
case 'L':
seg = line(x, y, seg[1], seg[2])
break
case 'H':
seg = line(x, y, seg[1], y)
break
case 'V':
seg = line(x, y, x, seg[1])
break
case 'Z':
seg = line(x, y, startX, startY)
break
}
// update state
prev = command
x = seg[seg.length - 2]
y = seg[seg.length - 1]
if (seg.length > 4) {
bezierX = seg[seg.length - 4]
bezierY = seg[seg.length - 3]
} else {
bezierX = x
bezierY = y
}
result.push(seg)
}
return result
}
function line(x1, y1, x2, y2){
return ['C', x1, y1, x2, y2, x2, y2]
}
function quadratic(x1, y1, cx, cy, x2, y2){
return [
'C',
x1/3 + (2/3) * cx,
y1/3 + (2/3) * cy,
x2/3 + (2/3) * cx,
y2/3 + (2/3) * cy,
x2,
y2
]
}