123 lines
2.7 KiB
JavaScript
123 lines
2.7 KiB
JavaScript
'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
|
|
]
|
|
}
|