New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

normalize-svg-path

Package Overview
Dependencies
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

normalize-svg-path - npm Package Compare versions

Comparing version 0.1.0 to 1.0.0

.eslintrc.json

288

index.js

@@ -0,200 +1,122 @@

'use strict'
var π = Math.PI
var _120 = radians(120)
module.exports = normalize
/**
* describe `path` in terms of cubic bézier
* curves and move commands
*
* @param {Array} path
* @return {Array}
*/
var arcToCurve = require('svg-arc-to-cubic-bezier').default
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
// 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':
seg = arc(x, y,seg[1],seg[2],radians(seg[3]),seg[4],seg[5],seg[6],seg[7])
// split multi part
seg.unshift('C')
if (seg.length > 7) {
result.push(seg.splice(0, 7))
seg.unshift('C')
}
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
}
for (var i = 0, len = path.length; i < len; i++) {
var seg = path[i]
var command = seg[0]
// 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)
}
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]
})
return result
}
// null-curves
if (!curves.length) continue
function line(x1, y1, x2, y2){
return ['C', x1, y1, x2, y2, x2, y2]
}
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)
}
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
]
}
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
}
// This function is ripped from
// github.com/DmitryBaranovskiy/raphael/blob/4d97d4/raphael.js#L2216-L2304
// which references w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
// TODO: make it human readable
// 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)
}
function arc(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
if (!recursive) {
var xy = rotate(x1, y1, -angle)
x1 = xy.x
y1 = xy.y
xy = rotate(x2, y2, -angle)
x2 = xy.x
y2 = xy.y
var x = (x1 - x2) / 2
var y = (y1 - y2) / 2
var h = (x * x) / (rx * rx) + (y * y) / (ry * ry)
if (h > 1) {
h = Math.sqrt(h)
rx = h * rx
ry = h * ry
}
var rx2 = rx * rx
var ry2 = ry * ry
var k = (large_arc_flag == sweep_flag ? -1 : 1)
* Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)))
if (k == Infinity) k = 1 // neutralize
var cx = k * rx * y / ry + (x1 + x2) / 2
var cy = k * -ry * x / rx + (y1 + y2) / 2
var f1 = Math.asin(((y1 - cy) / ry).toFixed(9))
var f2 = Math.asin(((y2 - cy) / ry).toFixed(9))
f1 = x1 < cx ? π - f1 : f1
f2 = x2 < cx ? π - f2 : f2
if (f1 < 0) f1 = π * 2 + f1
if (f2 < 0) f2 = π * 2 + f2
if (sweep_flag && f1 > f2) f1 = f1 - π * 2
if (!sweep_flag && f2 > f1) f2 = f2 - π * 2
} else {
f1 = recursive[0]
f2 = recursive[1]
cx = recursive[2]
cy = recursive[3]
}
// greater than 120 degrees requires multiple segments
if (Math.abs(f2 - f1) > _120) {
var f2old = f2
var x2old = x2
var y2old = y2
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1)
x2 = cx + rx * Math.cos(f2)
y2 = cy + ry * Math.sin(f2)
var res = arc(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy])
}
var t = Math.tan((f2 - f1) / 4)
var hx = 4 / 3 * rx * t
var hy = 4 / 3 * ry * t
var curve = [
2 * x1 - (x1 + hx * Math.sin(f1)),
2 * y1 - (y1 - hy * Math.cos(f1)),
x2 + hx * Math.sin(f2),
y2 - hy * Math.cos(f2),
x2,
y2
]
if (recursive) return curve
if (res) curve = curve.concat(res)
for (var i = 0; i < curve.length;) {
var rot = rotate(curve[i], curve[i+1], angle)
curve[i++] = rot.x
curve[i++] = rot.y
}
return curve
return result
}
function rotate(x, y, rad){
return {
x: x * Math.cos(rad) - y * Math.sin(rad),
y: x * Math.sin(rad) + y * Math.cos(rad)
}
function line(x1, y1, x2, y2){
return ['C', x1, y1, x2, y2, x2, y2]
}
function radians(degress){
return degress * (π / 180)
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
]
}
{
"name": "normalize-svg-path",
"version": "0.1.0",
"description": "convert all segments in a path to curves",
"keywords": ["svg","path","normalize"],
"dependencies": {},
"version": "1.0.0",
"description": "Convert all segments in a path to curves",
"keywords": [
"svg",
"path",
"normalize"
],
"dependencies": {
"svg-arc-to-cubic-bezier": "^2.0.0"
},
"devDependencies": {
"serve": "jkroso/serve",
"dom": "component/dom",
"parse-svg-path": "*",
"equals": "*",
"mocha": "*",
"jsmd": "*"
"parse-svg-path": "^0.1.2",
"tape": "^4.7.0"
},

@@ -18,4 +20,3 @@ "repository": "git://github.com/jkroso/normalize-svg-path.git",

"author": "Jake Rosoman",
"files": ["index.js"],
"license": "MIT"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc