@jscad/svg-serializer 2.3.18 → 3.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -233
- package/LICENSE +1 -1
- package/README.md +4 -2
- package/dist/jscad-svg-serializer.es.js +13 -0
- package/dist/jscad-svg-serializer.min.js +14 -0
- package/package.json +22 -12
- package/rollup.config.js +27 -0
- package/{index.js → src/index.js} +16 -34
- package/tests/geom2.test.js +39 -38
- package/tests/path2.test.js +12 -12
|
@@ -1,21 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
JSCAD Object to SVG Format Serialization
|
|
3
|
-
|
|
4
|
-
## License
|
|
5
|
-
|
|
6
|
-
Copyright (c) 2018 JSCAD Organization https://github.com/jscad
|
|
7
|
-
|
|
8
|
-
All code released under MIT license
|
|
9
|
-
|
|
10
|
-
Notes:
|
|
11
|
-
1) geom2 conversion to:
|
|
12
|
-
SVG GROUP containing a continous SVG PATH that contains the outlines of the geometry
|
|
13
|
-
2) geom3 conversion to:
|
|
14
|
-
none
|
|
15
|
-
3) path2 conversion to:
|
|
16
|
-
SVG GROUP containing a SVG PATH for each path
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
1
|
/**
|
|
20
2
|
* Serializer of JSCAD geometries to SVG source (XML).
|
|
21
3
|
*
|
|
@@ -31,11 +13,11 @@ Notes:
|
|
|
31
13
|
* const { serializer, mimeType } = require('@jscad/svg-serializer')
|
|
32
14
|
*/
|
|
33
15
|
|
|
34
|
-
|
|
16
|
+
import { geom2, flatten, measureBoundingBox, path2, vec3 } from '@jscad/modeling'
|
|
35
17
|
|
|
36
|
-
|
|
18
|
+
import { stringify } from '@jscad/io-utils'
|
|
37
19
|
|
|
38
|
-
const version =
|
|
20
|
+
const version = '[VI]{version}[/VI]' // version is injected by rollup
|
|
39
21
|
|
|
40
22
|
const mimeType = 'image/svg+xml'
|
|
41
23
|
|
|
@@ -61,10 +43,10 @@ const serialize = (options, ...objects) => {
|
|
|
61
43
|
}
|
|
62
44
|
options = Object.assign({}, defaults, options)
|
|
63
45
|
|
|
64
|
-
objects =
|
|
46
|
+
objects = flatten(objects)
|
|
65
47
|
|
|
66
48
|
// convert only 2D geometries
|
|
67
|
-
const objects2d = objects.filter((object) =>
|
|
49
|
+
const objects2d = objects.filter((object) => geom2.isA(object) || path2.isA(object))
|
|
68
50
|
|
|
69
51
|
if (objects2d.length === 0) throw new Error('only 2D geometries can be serialized to SVG')
|
|
70
52
|
if (objects.length !== objects2d.length) console.warn('some objects could not be serialized to SVG')
|
|
@@ -112,14 +94,14 @@ ${stringify(body, 2)}`
|
|
|
112
94
|
* Measure the bounds of the given objects, which is required to offset all points to positive X/Y values.
|
|
113
95
|
*/
|
|
114
96
|
const getBounds = (objects) => {
|
|
115
|
-
const allbounds =
|
|
97
|
+
const allbounds = measureBoundingBox(objects)
|
|
116
98
|
|
|
117
99
|
if (objects.length === 1) return allbounds
|
|
118
100
|
|
|
119
101
|
// create a sum of the bounds
|
|
120
102
|
const sumofbounds = allbounds.reduce((sum, bounds) => {
|
|
121
|
-
|
|
122
|
-
|
|
103
|
+
vec3.min(sum[0], sum[0], bounds[0])
|
|
104
|
+
vec3.max(sum[1], sum[1], bounds[1])
|
|
123
105
|
return sum
|
|
124
106
|
}, [[0, 0, 0], [0, 0, 0]])
|
|
125
107
|
return sumofbounds
|
|
@@ -133,10 +115,10 @@ const convertObjects = (objects, bounds, options) => {
|
|
|
133
115
|
objects.forEach((object, i) => {
|
|
134
116
|
options.statusCallback && options.statusCallback({ progress: 100 * i / objects.length })
|
|
135
117
|
|
|
136
|
-
if (
|
|
118
|
+
if (geom2.isA(object)) {
|
|
137
119
|
contents.push(convertGeom2(object, [xoffset, yoffset], options))
|
|
138
120
|
}
|
|
139
|
-
if (
|
|
121
|
+
if (path2.isA(object)) {
|
|
140
122
|
contents.push(convertPaths([object], [xoffset, yoffset], options))
|
|
141
123
|
}
|
|
142
124
|
})
|
|
@@ -153,8 +135,8 @@ const reflect = (x, y, px, py) => {
|
|
|
153
135
|
}
|
|
154
136
|
|
|
155
137
|
const convertGeom2 = (object, offsets, options) => {
|
|
156
|
-
const outlines =
|
|
157
|
-
const paths = outlines.map((outline) =>
|
|
138
|
+
const outlines = geom2.toOutlines(object)
|
|
139
|
+
const paths = outlines.map((outline) => path2.fromPoints({ closed: true }, outline))
|
|
158
140
|
|
|
159
141
|
options.color = 'black' // SVG initial color
|
|
160
142
|
if (object.color) options.color = convertColor(object.color)
|
|
@@ -203,9 +185,9 @@ const convertPath = (path, offsets, options) => {
|
|
|
203
185
|
return str
|
|
204
186
|
}
|
|
205
187
|
|
|
206
|
-
const convertColor = (color) => `
|
|
188
|
+
const convertColor = (color) => `rgb(${color[0] * 255},${color[1] * 255},${color[2] * 255},${color[3] * 255})`
|
|
207
189
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
190
|
+
export {
|
|
191
|
+
mimeType,
|
|
192
|
+
serialize
|
|
211
193
|
}
|
package/tests/geom2.test.js
CHANGED
|
@@ -1,63 +1,64 @@
|
|
|
1
|
-
|
|
1
|
+
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { center, colorize, geom2, rectangle } from '@jscad/modeling'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { serialize } from '../src/index.js'
|
|
6
6
|
|
|
7
7
|
test('serialize 2D geometries (simple) to svg', (t) => {
|
|
8
|
-
const cag1 =
|
|
8
|
+
const cag1 = geom2.create()
|
|
9
9
|
|
|
10
|
-
const observed1 =
|
|
10
|
+
const observed1 = serialize({}, cag1)
|
|
11
11
|
t.deepEqual([expected1], observed1)
|
|
12
12
|
|
|
13
|
-
const cag2 =
|
|
13
|
+
const cag2 = rectangle({ size: [10, 20] })
|
|
14
14
|
|
|
15
|
-
const observed2 =
|
|
15
|
+
const observed2 = serialize({}, cag2)
|
|
16
16
|
t.deepEqual([expected2], observed2)
|
|
17
17
|
|
|
18
|
-
const cag3 =
|
|
19
|
-
const cag4 =
|
|
18
|
+
const cag3 = center({ relativeTo: [-30, -30, 0] }, rectangle({ size: [10, 20] }))
|
|
19
|
+
const cag4 = center({ relativeTo: [30, 30, 0] }, rectangle({ size: [10, 20] }))
|
|
20
20
|
|
|
21
|
-
const observed3 =
|
|
21
|
+
const observed3 = serialize({}, cag3, cag4)
|
|
22
22
|
t.deepEqual([expected3], observed3)
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
test('serialize 2D geometries (color) to svg', (t) => {
|
|
26
|
-
let cag2 =
|
|
27
|
-
cag2 =
|
|
26
|
+
let cag2 = rectangle({ size: [10, 20] })
|
|
27
|
+
cag2 = colorize([0.5, 0.5, 0.5, 0.5], cag2)
|
|
28
28
|
cag2.id = 'r2'
|
|
29
29
|
cag2.class = 'gray-rect'
|
|
30
30
|
|
|
31
|
-
const observed2 =
|
|
31
|
+
const observed2 = serialize({}, cag2)
|
|
32
32
|
t.deepEqual([expected4], observed2)
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
test('serialize 2D geometries (complex) to svg', (t) => {
|
|
36
|
-
let shape =
|
|
37
|
-
[
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
[
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
36
|
+
let shape = geom2.create([
|
|
37
|
+
[
|
|
38
|
+
[-75, -75],
|
|
39
|
+
[75, -75],
|
|
40
|
+
[75, 75],
|
|
41
|
+
[40, 75],
|
|
42
|
+
[40, 0],
|
|
43
|
+
[-40, 0],
|
|
44
|
+
[-40, 75],
|
|
45
|
+
[-75, 75]
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
[15, -40],
|
|
49
|
+
[8, -40],
|
|
50
|
+
[8, -25],
|
|
51
|
+
[-8, -25],
|
|
52
|
+
[-8, -40],
|
|
53
|
+
[-15, -40],
|
|
54
|
+
[-15, -10],
|
|
55
|
+
[15, -10]
|
|
56
|
+
],
|
|
57
|
+
[[-2, -19], [2, -19], [2, -15], [-2, -15]]
|
|
57
58
|
])
|
|
58
|
-
shape =
|
|
59
|
+
shape = colorize([0.5, 0.5, 0.5, 0.5], shape)
|
|
59
60
|
|
|
60
|
-
const observed =
|
|
61
|
+
const observed = serialize({}, shape)
|
|
61
62
|
t.deepEqual([expected5], observed)
|
|
62
63
|
})
|
|
63
64
|
|
|
@@ -99,7 +100,7 @@ const expected4 = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
99
100
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
|
|
100
101
|
<svg width="10mm" height="20mm" viewBox="0 0 10 20" fill="none" fill-rule="evenodd" stroke-width="0.1px" version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
101
102
|
<g>
|
|
102
|
-
<path fill="
|
|
103
|
+
<path fill="rgb(127.5,127.5,127.5,127.5)" d="M0 20L10 20L10 0L0 0L0 20" id="r2" class="gray-rect"/>
|
|
103
104
|
</g>
|
|
104
105
|
</svg>
|
|
105
106
|
`
|
|
@@ -109,7 +110,7 @@ const expected5 = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
109
110
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
|
|
110
111
|
<svg width="150mm" height="150mm" viewBox="0 0 150 150" fill="none" fill-rule="evenodd" stroke-width="0.1px" version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
111
112
|
<g>
|
|
112
|
-
<path fill="
|
|
113
|
+
<path fill="rgb(127.5,127.5,127.5,127.5)" d="M0 150L150 150L150 0L115 0L115 75L35 75L35 0L0 0L0 150M90 115L83 115L83 100L67 100L67 115L60 115L60 85L90 85L90 115M73 94L77 94L77 90L73 90L73 94"/>
|
|
113
114
|
</g>
|
|
114
115
|
</svg>
|
|
115
116
|
`
|
package/tests/path2.test.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { colorize, line, path2 } from '@jscad/modeling'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { serialize } from '../src/index.js'
|
|
6
6
|
|
|
7
7
|
test('serialize 2D path (simple) objects to svg', (t) => {
|
|
8
8
|
// simple open path
|
|
9
|
-
const object1 =
|
|
10
|
-
let observed =
|
|
9
|
+
const object1 = line([[0, 0], [1, 1], [-3, 3]])
|
|
10
|
+
let observed = serialize({}, object1)
|
|
11
11
|
t.deepEqual(observed, [expected1])
|
|
12
12
|
|
|
13
13
|
// simple closed path
|
|
14
|
-
let object3 =
|
|
14
|
+
let object3 = path2.fromPoints({}, [
|
|
15
15
|
[42.33333, 0],
|
|
16
16
|
[21.166665, -56.44443999999999],
|
|
17
17
|
[63.49999499999999, -56.44443999999999]
|
|
18
18
|
])
|
|
19
|
-
object3 =
|
|
19
|
+
object3 = path2.close(object3)
|
|
20
20
|
|
|
21
|
-
observed =
|
|
21
|
+
observed = serialize({}, object3)
|
|
22
22
|
t.deepEqual(observed, [expected3])
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
test('serialize 2D path (color) objects to svg', (t) => {
|
|
26
26
|
// simple open path
|
|
27
|
-
let object1 =
|
|
28
|
-
object1 =
|
|
27
|
+
let object1 = line([[0, 0], [1, 1], [-3, 3]])
|
|
28
|
+
object1 = colorize([0.5, 0.5, 0.5, 0.5], object1)
|
|
29
29
|
object1.id = 'l1'
|
|
30
30
|
object1.class = 'gray-line'
|
|
31
|
-
const observed =
|
|
31
|
+
const observed = serialize({}, object1)
|
|
32
32
|
t.deepEqual(observed, [expected4])
|
|
33
33
|
})
|
|
34
34
|
|
|
@@ -61,7 +61,7 @@ const expected4 = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
61
61
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
|
|
62
62
|
<svg width="4mm" height="3mm" viewBox="0 0 4 3" fill="none" fill-rule="evenodd" stroke-width="0.1px" version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
63
63
|
<g>
|
|
64
|
-
<path d="M3 3L4 2L0 0" stroke="
|
|
64
|
+
<path d="M3 3L4 2L0 0" stroke="rgb(127.5,127.5,127.5,127.5)" id="l1" class="gray-line"/>
|
|
65
65
|
</g>
|
|
66
66
|
</svg>
|
|
67
67
|
`
|