-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsvg2shape.js
141 lines (126 loc) · 5.44 KB
/
svg2shape.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//==============================================================================
// Welcome to scripting in Origami! Helpful links:
//
// Scripting Basics - https://origami.design/documentation/concepts/scriptingbasics
// Scripting API - https://origami.design/documentation/concepts/scriptingapi
//
// Script ID: 9D6FD210-D976-4226-A20C-FCE434A74110
//==============================================================================
var length = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }
var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig
function parse(path) {
var data = []
path.replace(segment, function(_, command, args) {
var type = command.toLowerCase()
args = parseValues(args)
// overloaded moveTo
if(type == 'm' && args.length > 2) {
data.push([command].concat(args.splice(0, 2)))
type = 'l'
command = command == 'm' ? 'l' : 'L'
}
while(true) {
if(args.length == length[type]) {
args.unshift(command)
return data.push(args)
}
if(args.length < length[type]) throw new Error('malformed path data')
data.push([command].concat(args.splice(0, length[type])))
}
})
return data
}
var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig
function parseValues(args) {
var numbers = args.match(number)
return numbers ? numbers.map(Number) : []
}
function svgToJSONPath(pathStr) {
const commands = parse(pathStr);
let cursor = { x: 0, y: 0 };
let object = new Array();
commands.forEach((command) => {
if(command[0] === 'M' || command[0] === 'm') { // Move to
if(command[0] === 'm') { // MoveTo relative mode
cursor = { "x": cursor.x + command[1], "y": cursor.y + command[2] };
} else {
cursor = { "x": command[1], "y": command[2] };
}
object.push({ "type": "moveTo", "point": cursor });
} else if(command[0] === 'L' || command[0] === 'l') { // Line to
if(command[0] === 'l') { // Line to relative mode
cursor = { "x": cursor.x + command[1], "y": cursor.y + command[2] };
} else {
cursor = { "x": command[1], "y": command[2] };
}
// cursor = {"x":command[1],"y":command[2]};
object.push({ "type": "lineTo", "point": cursor });
} else if(command[0] === 'H' || command[0] === 'h') { // Horizontal Line
if(command[0] === 'h') { // Horizontal relative mode
cursor = { "x": cursor.x + command[1], "y": cursor.y };
} else {
cursor = { "x": command[1], "y": cursor.y };
}
object.push({ "type": "lineTo", "point": cursor });
} else if(command[0] === 'V' || command[0] === 'v') { // Vertical Line
if(command[0] === 'v') { // Vertical relative mode
cursor = { "x": cursor.x, "y": command[1] + cursor.y };
} else {
cursor = { "x": cursor.x, "y": command[1] };
}
object.push({ "type": "lineTo", "point": cursor });
} else if(command[0] === 'Z' || command[0] === 'z') { // Close Path
object.push({ "type": "closePath" });
} else if(command[0] === 'C') { // Curve
object.push({ "type": "curveTo", "curveFrom": { "x": command[1], "y": command[2] }, "curveTo": { "x": command[3], "y": command[4] }, "point": { "x": command[5], "y": command[6] } });
cursor = { "x": command[5], "y": command[6] };
} else if(command[0] === 'c') { // Curve relative mode
command[1] += cursor.x
command[2] += cursor.y
command[3] += cursor.x
command[4] += cursor.y
command[5] += cursor.x
command[6] += cursor.y
object.push({ "type": "curveTo", "curveFrom": { "x": command[1], "y": command[2] }, "curveTo": { "x": command[3], "y": command[4] }, "point": { "x": command[5], "y": command[6] } });
cursor = { "x": command[5], "y": command[6] };
} else if(command[0] === 'S') { // Spline
const lastPiece = object[object.length - 1];
if(lastPiece.type !== "curveTo") {
throw new Error(`Unsupported spline after non-curve`);
}
const fromX = lastPiece.point.x + (lastPiece.point.x - lastPiece.curveTo.x)
const fromY = lastPiece.point.y + (lastPiece.point.y - lastPiece.curveTo.y)
object.push({ "type": "curveTo", "curveFrom": { "x": fromX, "y": fromY }, "curveTo": { "x": command[1], "y": command[2] }, "point": { "x": command[3], "y": command[4] } });
cursor = { "x": command[3], "y": command[4] };
} else if(command[0] === 's') { // Spline relative mode
command[1] += cursor.x
command[2] += cursor.y
command[3] += cursor.x
command[4] += cursor.y
const lastPiece = object[object.length - 1];
if(lastPiece.type !== "curveTo") {
throw new Error(`Unsupported spline after non-curve`);
}
const fromX = lastPiece.point.x + (lastPiece.point.x - lastPiece.curveTo.x)
const fromY = lastPiece.point.y + (lastPiece.point.y - lastPiece.curveTo.y)
object.push({ "type": "curveTo", "curveFrom": { "x": fromX, "y": fromY }, "curveTo": { "x": command[1], "y": command[2] }, "point": { "x": command[3], "y": command[4] } });
cursor = { "x": command[3], "y": command[4] };
} else {
throw new Error(`Unsupported Command ${command[0]}`);
}
});
return { "path": object };
}
var patch = new Patch();
// Set Inputs and Outputs.
patch.inputs = [
new PatchInput("SVG", types.STRING, ""),
];
patch.outputs = [
new PatchOutput("JSON", types.JSON),
];
// Add your logic in this function.
patch.evaluate = function() {
patch.outputs[0].value = svgToJSONPath(patch.inputs[0].value);
}
return patch;