svg-pathdata
Advanced tools
Comparing version 3.0.0 to 3.1.0
@@ -60,3 +60,3 @@ ## Usage | ||
```js | ||
var pathData = new SVGPathData (` | ||
const pathData = new SVGPathData (` | ||
M 10 10 | ||
@@ -75,3 +75,3 @@ H 60 | ||
```js | ||
var encoder = new SVGPathData.Encoder(); | ||
const encoder = new SVGPathData.Encoder(); | ||
encoder.setEncoding('utf8'); | ||
@@ -106,9 +106,8 @@ | ||
console.log( | ||
new SVGPathData ('\ | ||
m 10,10 \ | ||
h 60 \ | ||
v 60 \ | ||
l 10,60 \ | ||
z' | ||
) | ||
new SVGPathData (` | ||
m 10,10 | ||
h 60 | ||
v 60 | ||
l 10,60 | ||
z`) | ||
.toAbs() | ||
@@ -152,3 +151,3 @@ .encode() | ||
process.stdin.pipe(new SVGPathData.Parser()) | ||
.pipe(new SVGPathData.Transformer(SET_X_TO(25)) | ||
.pipe(new SVGPathData.Transformer(SET_X_TO(25))) | ||
.pipe(new SVGPathData.Encoder()) | ||
@@ -155,0 +154,0 @@ .pipe(process.stdout); |
@@ -0,1 +1,6 @@ | ||
<a name="3.1.0"></a> | ||
# [3.1.0](https://github.com/nfroidure/SVGPathData/compare/v3.0.0...v3.1.0) (2017-05-19) | ||
<a name="3.0.0"></a> | ||
@@ -2,0 +7,0 @@ # [3.0.0](https://github.com/nfroidure/SVGPathData/compare/v2.0.3...v3.0.0) (2017-05-02) |
{ | ||
"name": "svg-pathdata", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "Manipulate SVG path data (path[d] attribute content) simply and efficiently.", | ||
@@ -5,0 +5,0 @@ "main": "src/SVGPathData.js", |
@@ -76,3 +76,3 @@ <!-- | ||
```js | ||
var pathData = new SVGPathData (` | ||
const pathData = new SVGPathData (` | ||
M 10 10 | ||
@@ -91,3 +91,3 @@ H 60 | ||
```js | ||
var encoder = new SVGPathData.Encoder(); | ||
const encoder = new SVGPathData.Encoder(); | ||
encoder.setEncoding('utf8'); | ||
@@ -122,9 +122,8 @@ | ||
console.log( | ||
new SVGPathData ('\ | ||
m 10,10 \ | ||
h 60 \ | ||
v 60 \ | ||
l 10,60 \ | ||
z' | ||
) | ||
new SVGPathData (` | ||
m 10,10 | ||
h 60 | ||
v 60 | ||
l 10,60 | ||
z`) | ||
.toAbs() | ||
@@ -168,3 +167,3 @@ .encode() | ||
process.stdin.pipe(new SVGPathData.Parser()) | ||
.pipe(new SVGPathData.Transformer(SET_X_TO(25)) | ||
.pipe(new SVGPathData.Transformer(SET_X_TO(25))) | ||
.pipe(new SVGPathData.Encoder()) | ||
@@ -171,0 +170,0 @@ .pipe(process.stdout); |
121
src/a2c.js
@@ -8,13 +8,53 @@ /* eslint-disable */ | ||
module.exports = a2c; | ||
// LOL | ||
const PI = Math.PI; | ||
const math = Math; | ||
const abs = Math.abs; | ||
const split = 'split'; | ||
const concat = 'concat'; | ||
const apply = 'apply'; | ||
const has = 'hasOwnProperty'; | ||
/** | ||
* https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes | ||
* Fixes rX and rY. | ||
* Ensures lArcFlag and sweepFlag are 0 or 1 | ||
* Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative) | ||
* Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true | ||
*/ | ||
function annotateArcCommand(c, x1, y1) { | ||
function rotate([x, y], rad) { | ||
return [ | ||
x * Math.cos(rad) - y * Math.sin(rad), | ||
x * Math.sin(rad) + y * Math.cos(rad), | ||
]; | ||
} | ||
c.lArcFlag = (c.lArcFlag == 0) ? 0 : 1 | ||
c.sweepFlag = (c.sweepFlag == 0) ? 0 : 1 | ||
//noinspection TsLint | ||
let {rX, rY, x, y} = c | ||
rX = Math.abs(c.rX) | ||
rY = Math.abs(c.rY) | ||
const [x1_, y1_] = rotate([(x1 - x) / 2, (y1 - y) / 2], -c.xRot / 180 * Math.PI) | ||
const testValue = Math.pow(x1_, 2) / Math.pow(rX, 2) + Math.pow(y1_, 2) / Math.pow(rY, 2) | ||
if (testValue > 1) { | ||
rX *= Math.sqrt(testValue) | ||
rY *= Math.sqrt(testValue) | ||
} | ||
c.rX = rX | ||
c.rY = rY | ||
const c_ScaleTemp = (Math.pow(rX, 2) * Math.pow(y1_, 2) + Math.pow(rY, 2) * Math.pow(x1_, 2)) | ||
const c_Scale = | ||
(c.lArcFlag != c.sweepFlag ? 1 : -1) * Math.sqrt(Math.max(0, (Math.pow(rX, 2) * Math.pow(rY, 2) - c_ScaleTemp) / c_ScaleTemp)) | ||
const cx_ = rY * y1_ / rY * c_Scale | ||
const cy_ = -rY * x1_ / rX * c_Scale | ||
const cRot = rotate([cx_, cy_], c.xRot / 180 * Math.PI) | ||
c.cX = cRot[0] + (x1 + x) / 2 | ||
c.cY = cRot[1] + (y1 + y) / 2 | ||
c.phi1 = Math.atan2((y1_ - cy_) / rY, (x1_ - cx_) / rX) | ||
c.phi2 = Math.atan2((-y1_ - cy_) / rY, (-x1_ - cx_) / rX) | ||
if (c.sweepFlag == 0 && c.phi2 > c.phi1) { | ||
c.phi2 -= 2 * Math.PI | ||
} | ||
if (c.sweepFlag == 1 && c.phi2 < c.phi1) { | ||
c.phi2 += 2 * Math.PI | ||
} | ||
c.phi1 *= 180 / Math.PI | ||
c.phi2 *= 180 / Math.PI | ||
} | ||
function a2c(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { | ||
@@ -27,9 +67,6 @@ // for more information of where this math came from visit: | ||
xy, | ||
rotate = cacher((x, y, rad) => { | ||
let X = x * math.cos(rad) - y * math.sin(rad), | ||
Y = x * math.sin(rad) + y * math.cos(rad); | ||
rotate = (x, y, rad) => { | ||
return { x: x * Math.cos(rad) - y * Math.sin(rad), y: x * Math.sin(rad) + y * Math.cos(rad) }; | ||
}; | ||
return { x: X, y: Y }; | ||
}); | ||
if(!recursive) { | ||
@@ -42,4 +79,4 @@ xy = rotate(x1, y1, -rad); | ||
y2 = xy.y; | ||
let cos = math.cos(PI / 180 * angle), | ||
sin = math.sin(PI / 180 * angle), | ||
let cos = Math.cos(PI / 180 * angle), | ||
sin = Math.sin(PI / 180 * angle), | ||
x = (x1 - x2) / 2, | ||
@@ -50,3 +87,3 @@ y = (y1 - y2) / 2; | ||
if(1 < h) { | ||
h = math.sqrt(h); | ||
h = Math.sqrt(h); | ||
rx = h * rx; | ||
@@ -58,7 +95,7 @@ ry = h * ry; | ||
k = (large_arc_flag == sweep_flag ? -1 : 1) * | ||
math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), | ||
Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), | ||
cx = k * rx * y / ry + (x1 + x2) / 2, | ||
cy = k * -ry * x / rx + (y1 + y2) / 2, | ||
f1 = math.asin(((y1 - cy) / ry).toFixed(9)), | ||
f2 = math.asin(((y2 - cy) / ry).toFixed(9)); | ||
f1 = Math.asin(((y1 - cy) / ry).toFixed(9)), | ||
f2 = Math.asin(((y2 - cy) / ry).toFixed(9)); | ||
@@ -83,3 +120,3 @@ f1 = x1 < cx ? PI - f1 : f1; | ||
if(abs(df) > _120) { | ||
if(Math.abs(df) > _120) { | ||
let f2old = f2, | ||
@@ -90,12 +127,12 @@ x2old = x2, | ||
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); | ||
x2 = cx + rx * math.cos(f2); | ||
y2 = cy + ry * math.sin(f2); | ||
x2 = cx + rx * Math.cos(f2); | ||
y2 = cy + ry * Math.sin(f2); | ||
res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); | ||
} | ||
df = f2 - f1; | ||
let c1 = math.cos(f1), | ||
s1 = math.sin(f1), | ||
c2 = math.cos(f2), | ||
s2 = math.sin(f2), | ||
t = math.tan(df / 4), | ||
let c1 = Math.cos(f1), | ||
s1 = Math.sin(f1), | ||
c2 = Math.cos(f2), | ||
s2 = Math.sin(f2), | ||
t = Math.tan(df / 4), | ||
hx = 4 / 3 * rx * t, | ||
@@ -111,5 +148,5 @@ hy = 4 / 3 * ry * t, | ||
if(recursive) { | ||
return [m2, m3, m4][concat](res); | ||
return [m2, m3, m4]['concat'](res); | ||
} | ||
res = [m2, m3, m4][concat](res).join()[split](','); | ||
res = [m2, m3, m4]['concat'](res).join()['split'](','); | ||
const newres = []; | ||
@@ -123,25 +160,3 @@ | ||
} | ||
function cacher(f, scope, postprocessor) { | ||
function newf() { | ||
let arg = Array.prototype.slice.call(arguments, 0), | ||
args = arg.join('\u2400'), | ||
cache = newf.cache = newf.cache || {}, | ||
count = newf.count = newf.count || []; | ||
if(cache[has](args)) { | ||
repush(count, args); | ||
return postprocessor ? postprocessor(cache[args]) : cache[args]; | ||
} | ||
1e3 <= count.length && delete cache[count.shift()]; | ||
count.push(args); | ||
cache[args] = f[apply](scope, arg); | ||
return postprocessor ? postprocessor(cache[args]) : cache[args]; | ||
} | ||
return newf; | ||
} | ||
function repush(array, item) { | ||
for(let i = 0, ii = array.length; i < ii; i++) { if(array[i] === item) { | ||
return array.push(array.splice(i, 1)[0]); | ||
} } | ||
} | ||
module.exports = {a2c, annotateArcCommand}; |
@@ -77,2 +77,6 @@ /* eslint-disable new-cap,max-params */ | ||
annotateArcs() { | ||
return this.transform(SVGPathData.Transformer.ANNOTATE_ARCS()); | ||
}, | ||
transform(transformFunction) { | ||
@@ -79,0 +83,0 @@ const newCommands = []; |
@@ -9,3 +9,3 @@ /* eslint-disable complexity,prefer-reflect,max-params */ | ||
// a2c utility | ||
const a2c = require('./a2c.js'); | ||
const { a2c, annotateArcCommand } = require('./a2c.js'); | ||
@@ -97,3 +97,3 @@ // Access to SVGPathData constructor | ||
SVGPathDataTransformer.TO_ABS = function toAbsGenerator() { | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY) => { | ||
if(command.relative) { | ||
@@ -129,3 +129,3 @@ // x1/y1 values | ||
SVGPathDataTransformer.TO_REL = function toRelGenerator() { | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY) => { | ||
if(!command.relative) { | ||
@@ -162,3 +162,3 @@ // x1/y1 values | ||
function normalizeHVZGenerator(normalizeZ = true, normalizeH = true, normalizeV = true) { | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY, pathStartX, pathStartY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY, pathStartX, pathStartY) => { | ||
if(isNaN(pathStartX) && !(command.type & SVGPathData.MOVE_TO)) { | ||
@@ -201,3 +201,3 @@ throw new Error('path must start with moveto'); | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY) => { | ||
if(command.type & SVGPathData.SMOOTH_CURVE_TO) { | ||
@@ -249,3 +249,3 @@ command.type = SVGPathData.CURVE_TO; | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY) => { | ||
if(command.type & SVGPathData.SMOOTH_QUAD_TO) { | ||
@@ -278,29 +278,29 @@ command.type = SVGPathData.QUAD_TO; | ||
SVGPathDataTransformer.INFO = function(f) { | ||
let prevX = 0; | ||
let prevY = 0; | ||
let pathStartX = NaN; | ||
let pathStartY = NaN; | ||
let prevXAbs = 0; | ||
let prevYAbs = 0; | ||
let pathStartXAbs = NaN; | ||
let pathStartYAbs = NaN; | ||
return function transform(command) { | ||
if(isNaN(pathStartX) && !(command.type & SVGPathData.MOVE_TO)) { | ||
if(isNaN(pathStartXAbs) && !(command.type & SVGPathData.MOVE_TO)) { | ||
throw new Error('path must start with moveto'); | ||
} | ||
const result = f(command, prevX, prevY, pathStartX, pathStartY); | ||
const result = f(command, prevXAbs, prevYAbs, pathStartXAbs, pathStartYAbs); | ||
if(command.type & SVGPathData.CLOSE_PATH) { | ||
prevX = pathStartX; | ||
prevY = pathStartY; | ||
prevXAbs = pathStartXAbs; | ||
prevYAbs = pathStartYAbs; | ||
} | ||
if('undefined' !== typeof command.x) { | ||
prevX = (command.relative ? prevX + command.x : command.x); | ||
prevXAbs = (command.relative ? prevXAbs + command.x : command.x); | ||
} | ||
if('undefined' !== typeof command.y) { | ||
prevY = (command.relative ? prevY + command.y : command.y); | ||
prevYAbs = (command.relative ? prevYAbs + command.y : command.y); | ||
} | ||
if(command.type & SVGPathData.MOVE_TO) { | ||
pathStartX = prevX; | ||
pathStartY = prevY; | ||
pathStartXAbs = prevXAbs; | ||
pathStartYAbs = prevYAbs; | ||
} | ||
@@ -322,3 +322,3 @@ | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY, pathStartX, pathStartY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY, pathStartX, pathStartY) => { | ||
const abs = Math.abs; | ||
@@ -399,3 +399,3 @@ let skip = false; | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY, pathStartX) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY, pathStartX) => { | ||
const origX1 = command.x1; | ||
@@ -555,3 +555,3 @@ const origX2 = command.x2; | ||
SVGPathDataTransformer.A_TO_C = function a2CGenerator() { | ||
return SVGPathDataTransformer.INFO(function(command, prevX, prevY) { | ||
return SVGPathDataTransformer.INFO((command, prevX, prevY) => { | ||
if(SVGPathData.ARC === command.type) { | ||
@@ -583,2 +583,16 @@ const args = a2c(command.relative ? 0 : prevX, command.relative ? 0 : prevY, | ||
// @see annotateArcCommand | ||
SVGPathDataTransformer.ANNOTATE_ARCS = function() { | ||
return SVGPathDataTransformer.INFO((c, x1, y1) => { | ||
if(c.relative) { | ||
x1 = 0; | ||
y1 = 0; | ||
} | ||
if(SVGPathData.ARC === c.type) { | ||
annotateArcCommand(c, x1, y1); | ||
} | ||
return c; | ||
}); | ||
}; | ||
module.exports = SVGPathDataTransformer; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
365886
59
3502
0
183