'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 ] }