kymostudio-core 0.3.3__tar.gz
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.
- kymostudio_core-0.3.3/.gitignore +4 -0
- kymostudio_core-0.3.3/Cargo.lock +712 -0
- kymostudio_core-0.3.3/Cargo.toml +54 -0
- kymostudio_core-0.3.3/PKG-INFO +82 -0
- kymostudio_core-0.3.3/README.md +65 -0
- kymostudio_core-0.3.3/pyproject.toml +27 -0
- kymostudio_core-0.3.3/src/lib.rs +73 -0
- kymostudio_core-0.3.3/src/main.rs +139 -0
- kymostudio_core-0.3.3/src/python.rs +23 -0
- kymostudio_core-0.3.3/src/wasm.rs +19 -0
- kymostudio_core-0.3.3/tests/render.rs +31 -0
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "adler2"
|
|
7
|
+
version = "2.0.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "arrayref"
|
|
13
|
+
version = "0.3.9"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "arrayvec"
|
|
19
|
+
version = "0.7.6"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "autocfg"
|
|
25
|
+
version = "1.5.1"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "base64"
|
|
31
|
+
version = "0.22.1"
|
|
32
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
33
|
+
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|
34
|
+
|
|
35
|
+
[[package]]
|
|
36
|
+
name = "bitflags"
|
|
37
|
+
version = "2.13.0"
|
|
38
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
39
|
+
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|
40
|
+
|
|
41
|
+
[[package]]
|
|
42
|
+
name = "bumpalo"
|
|
43
|
+
version = "3.20.3"
|
|
44
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
45
|
+
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "bytemuck"
|
|
49
|
+
version = "1.25.0"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "byteorder-lite"
|
|
55
|
+
version = "0.1.0"
|
|
56
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
|
+
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "cfg-if"
|
|
61
|
+
version = "1.0.4"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "color_quant"
|
|
67
|
+
version = "1.1.0"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
|
70
|
+
|
|
71
|
+
[[package]]
|
|
72
|
+
name = "core_maths"
|
|
73
|
+
version = "0.1.1"
|
|
74
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
75
|
+
checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
|
|
76
|
+
dependencies = [
|
|
77
|
+
"libm",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[[package]]
|
|
81
|
+
name = "crc32fast"
|
|
82
|
+
version = "1.5.0"
|
|
83
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
84
|
+
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
|
85
|
+
dependencies = [
|
|
86
|
+
"cfg-if",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[[package]]
|
|
90
|
+
name = "data-url"
|
|
91
|
+
version = "0.3.2"
|
|
92
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
93
|
+
checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376"
|
|
94
|
+
|
|
95
|
+
[[package]]
|
|
96
|
+
name = "euclid"
|
|
97
|
+
version = "0.22.14"
|
|
98
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
99
|
+
checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06"
|
|
100
|
+
dependencies = [
|
|
101
|
+
"num-traits",
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[[package]]
|
|
105
|
+
name = "fdeflate"
|
|
106
|
+
version = "0.3.7"
|
|
107
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
108
|
+
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
|
109
|
+
dependencies = [
|
|
110
|
+
"simd-adler32",
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
[[package]]
|
|
114
|
+
name = "flate2"
|
|
115
|
+
version = "1.1.9"
|
|
116
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
117
|
+
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
|
118
|
+
dependencies = [
|
|
119
|
+
"crc32fast",
|
|
120
|
+
"miniz_oxide",
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
[[package]]
|
|
124
|
+
name = "float-cmp"
|
|
125
|
+
version = "0.9.0"
|
|
126
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
127
|
+
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
|
128
|
+
|
|
129
|
+
[[package]]
|
|
130
|
+
name = "fontconfig-parser"
|
|
131
|
+
version = "0.5.8"
|
|
132
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
133
|
+
checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646"
|
|
134
|
+
dependencies = [
|
|
135
|
+
"roxmltree 0.20.0",
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[[package]]
|
|
139
|
+
name = "fontdb"
|
|
140
|
+
version = "0.23.0"
|
|
141
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
142
|
+
checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905"
|
|
143
|
+
dependencies = [
|
|
144
|
+
"fontconfig-parser",
|
|
145
|
+
"log",
|
|
146
|
+
"memmap2",
|
|
147
|
+
"slotmap",
|
|
148
|
+
"tinyvec",
|
|
149
|
+
"ttf-parser",
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
[[package]]
|
|
153
|
+
name = "gif"
|
|
154
|
+
version = "0.14.2"
|
|
155
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
156
|
+
checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159"
|
|
157
|
+
dependencies = [
|
|
158
|
+
"color_quant",
|
|
159
|
+
"weezl",
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
[[package]]
|
|
163
|
+
name = "heck"
|
|
164
|
+
version = "0.5.0"
|
|
165
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
166
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
167
|
+
|
|
168
|
+
[[package]]
|
|
169
|
+
name = "image-webp"
|
|
170
|
+
version = "0.2.4"
|
|
171
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
172
|
+
checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"
|
|
173
|
+
dependencies = [
|
|
174
|
+
"byteorder-lite",
|
|
175
|
+
"quick-error",
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
[[package]]
|
|
179
|
+
name = "imagesize"
|
|
180
|
+
version = "0.14.0"
|
|
181
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
182
|
+
checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c"
|
|
183
|
+
|
|
184
|
+
[[package]]
|
|
185
|
+
name = "kurbo"
|
|
186
|
+
version = "0.13.1"
|
|
187
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
188
|
+
checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2"
|
|
189
|
+
dependencies = [
|
|
190
|
+
"arrayvec",
|
|
191
|
+
"euclid",
|
|
192
|
+
"polycool",
|
|
193
|
+
"smallvec",
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
[[package]]
|
|
197
|
+
name = "kymostudio-core"
|
|
198
|
+
version = "0.3.5"
|
|
199
|
+
dependencies = [
|
|
200
|
+
"pyo3",
|
|
201
|
+
"resvg",
|
|
202
|
+
"wasm-bindgen",
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
[[package]]
|
|
206
|
+
name = "libc"
|
|
207
|
+
version = "0.2.186"
|
|
208
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
209
|
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
210
|
+
|
|
211
|
+
[[package]]
|
|
212
|
+
name = "libm"
|
|
213
|
+
version = "0.2.16"
|
|
214
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
215
|
+
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
|
216
|
+
|
|
217
|
+
[[package]]
|
|
218
|
+
name = "log"
|
|
219
|
+
version = "0.4.32"
|
|
220
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
221
|
+
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
|
222
|
+
|
|
223
|
+
[[package]]
|
|
224
|
+
name = "memchr"
|
|
225
|
+
version = "2.8.1"
|
|
226
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
227
|
+
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
|
228
|
+
|
|
229
|
+
[[package]]
|
|
230
|
+
name = "memmap2"
|
|
231
|
+
version = "0.9.10"
|
|
232
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
233
|
+
checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
|
|
234
|
+
dependencies = [
|
|
235
|
+
"libc",
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
[[package]]
|
|
239
|
+
name = "miniz_oxide"
|
|
240
|
+
version = "0.8.9"
|
|
241
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
242
|
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
243
|
+
dependencies = [
|
|
244
|
+
"adler2",
|
|
245
|
+
"simd-adler32",
|
|
246
|
+
]
|
|
247
|
+
|
|
248
|
+
[[package]]
|
|
249
|
+
name = "num-traits"
|
|
250
|
+
version = "0.2.19"
|
|
251
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
252
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
253
|
+
dependencies = [
|
|
254
|
+
"autocfg",
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
[[package]]
|
|
258
|
+
name = "once_cell"
|
|
259
|
+
version = "1.21.4"
|
|
260
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
261
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
262
|
+
|
|
263
|
+
[[package]]
|
|
264
|
+
name = "pico-args"
|
|
265
|
+
version = "0.5.0"
|
|
266
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
267
|
+
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
|
268
|
+
|
|
269
|
+
[[package]]
|
|
270
|
+
name = "png"
|
|
271
|
+
version = "0.18.1"
|
|
272
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
273
|
+
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
|
274
|
+
dependencies = [
|
|
275
|
+
"bitflags",
|
|
276
|
+
"crc32fast",
|
|
277
|
+
"fdeflate",
|
|
278
|
+
"flate2",
|
|
279
|
+
"miniz_oxide",
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
[[package]]
|
|
283
|
+
name = "polycool"
|
|
284
|
+
version = "0.4.0"
|
|
285
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
286
|
+
checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6"
|
|
287
|
+
dependencies = [
|
|
288
|
+
"arrayvec",
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
[[package]]
|
|
292
|
+
name = "portable-atomic"
|
|
293
|
+
version = "1.13.1"
|
|
294
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
295
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
296
|
+
|
|
297
|
+
[[package]]
|
|
298
|
+
name = "proc-macro2"
|
|
299
|
+
version = "1.0.106"
|
|
300
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
301
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
302
|
+
dependencies = [
|
|
303
|
+
"unicode-ident",
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
[[package]]
|
|
307
|
+
name = "pyo3"
|
|
308
|
+
version = "0.28.3"
|
|
309
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
310
|
+
checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
|
|
311
|
+
dependencies = [
|
|
312
|
+
"libc",
|
|
313
|
+
"once_cell",
|
|
314
|
+
"portable-atomic",
|
|
315
|
+
"pyo3-build-config",
|
|
316
|
+
"pyo3-ffi",
|
|
317
|
+
"pyo3-macros",
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
[[package]]
|
|
321
|
+
name = "pyo3-build-config"
|
|
322
|
+
version = "0.28.3"
|
|
323
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
324
|
+
checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
|
|
325
|
+
dependencies = [
|
|
326
|
+
"target-lexicon",
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
[[package]]
|
|
330
|
+
name = "pyo3-ffi"
|
|
331
|
+
version = "0.28.3"
|
|
332
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
333
|
+
checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
|
|
334
|
+
dependencies = [
|
|
335
|
+
"libc",
|
|
336
|
+
"pyo3-build-config",
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
[[package]]
|
|
340
|
+
name = "pyo3-macros"
|
|
341
|
+
version = "0.28.3"
|
|
342
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
343
|
+
checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
|
|
344
|
+
dependencies = [
|
|
345
|
+
"proc-macro2",
|
|
346
|
+
"pyo3-macros-backend",
|
|
347
|
+
"quote",
|
|
348
|
+
"syn",
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
[[package]]
|
|
352
|
+
name = "pyo3-macros-backend"
|
|
353
|
+
version = "0.28.3"
|
|
354
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
355
|
+
checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
|
|
356
|
+
dependencies = [
|
|
357
|
+
"heck",
|
|
358
|
+
"proc-macro2",
|
|
359
|
+
"pyo3-build-config",
|
|
360
|
+
"quote",
|
|
361
|
+
"syn",
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
[[package]]
|
|
365
|
+
name = "quick-error"
|
|
366
|
+
version = "2.0.1"
|
|
367
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
368
|
+
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
|
369
|
+
|
|
370
|
+
[[package]]
|
|
371
|
+
name = "quote"
|
|
372
|
+
version = "1.0.45"
|
|
373
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
374
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
375
|
+
dependencies = [
|
|
376
|
+
"proc-macro2",
|
|
377
|
+
]
|
|
378
|
+
|
|
379
|
+
[[package]]
|
|
380
|
+
name = "resvg"
|
|
381
|
+
version = "0.47.0"
|
|
382
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
383
|
+
checksum = "9be183ad6a216aa96f33e4c8033b0988b8b3ea6fd2359d19af5bac4643fd8e81"
|
|
384
|
+
dependencies = [
|
|
385
|
+
"gif",
|
|
386
|
+
"image-webp",
|
|
387
|
+
"log",
|
|
388
|
+
"pico-args",
|
|
389
|
+
"rgb",
|
|
390
|
+
"svgtypes",
|
|
391
|
+
"tiny-skia",
|
|
392
|
+
"usvg",
|
|
393
|
+
"zune-jpeg",
|
|
394
|
+
]
|
|
395
|
+
|
|
396
|
+
[[package]]
|
|
397
|
+
name = "rgb"
|
|
398
|
+
version = "0.8.53"
|
|
399
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
400
|
+
checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
|
|
401
|
+
dependencies = [
|
|
402
|
+
"bytemuck",
|
|
403
|
+
]
|
|
404
|
+
|
|
405
|
+
[[package]]
|
|
406
|
+
name = "roxmltree"
|
|
407
|
+
version = "0.20.0"
|
|
408
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
409
|
+
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
|
|
410
|
+
|
|
411
|
+
[[package]]
|
|
412
|
+
name = "roxmltree"
|
|
413
|
+
version = "0.21.1"
|
|
414
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
415
|
+
checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb"
|
|
416
|
+
dependencies = [
|
|
417
|
+
"memchr",
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
[[package]]
|
|
421
|
+
name = "rustversion"
|
|
422
|
+
version = "1.0.22"
|
|
423
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
424
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
425
|
+
|
|
426
|
+
[[package]]
|
|
427
|
+
name = "rustybuzz"
|
|
428
|
+
version = "0.20.1"
|
|
429
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
430
|
+
checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702"
|
|
431
|
+
dependencies = [
|
|
432
|
+
"bitflags",
|
|
433
|
+
"bytemuck",
|
|
434
|
+
"core_maths",
|
|
435
|
+
"log",
|
|
436
|
+
"smallvec",
|
|
437
|
+
"ttf-parser",
|
|
438
|
+
"unicode-bidi-mirroring",
|
|
439
|
+
"unicode-ccc",
|
|
440
|
+
"unicode-properties",
|
|
441
|
+
"unicode-script",
|
|
442
|
+
]
|
|
443
|
+
|
|
444
|
+
[[package]]
|
|
445
|
+
name = "simd-adler32"
|
|
446
|
+
version = "0.3.9"
|
|
447
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
448
|
+
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
|
449
|
+
|
|
450
|
+
[[package]]
|
|
451
|
+
name = "simplecss"
|
|
452
|
+
version = "0.2.2"
|
|
453
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
454
|
+
checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c"
|
|
455
|
+
dependencies = [
|
|
456
|
+
"log",
|
|
457
|
+
]
|
|
458
|
+
|
|
459
|
+
[[package]]
|
|
460
|
+
name = "siphasher"
|
|
461
|
+
version = "1.0.3"
|
|
462
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
463
|
+
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
|
464
|
+
|
|
465
|
+
[[package]]
|
|
466
|
+
name = "slotmap"
|
|
467
|
+
version = "1.1.1"
|
|
468
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
469
|
+
checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038"
|
|
470
|
+
dependencies = [
|
|
471
|
+
"version_check",
|
|
472
|
+
]
|
|
473
|
+
|
|
474
|
+
[[package]]
|
|
475
|
+
name = "smallvec"
|
|
476
|
+
version = "1.15.1"
|
|
477
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
478
|
+
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
479
|
+
|
|
480
|
+
[[package]]
|
|
481
|
+
name = "strict-num"
|
|
482
|
+
version = "0.1.1"
|
|
483
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
484
|
+
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
|
485
|
+
dependencies = [
|
|
486
|
+
"float-cmp",
|
|
487
|
+
]
|
|
488
|
+
|
|
489
|
+
[[package]]
|
|
490
|
+
name = "svgtypes"
|
|
491
|
+
version = "0.16.1"
|
|
492
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
493
|
+
checksum = "695b5790b3131dafa99b3bbfd25a216edb3d216dad9ca208d4657bfb8f2abc3d"
|
|
494
|
+
dependencies = [
|
|
495
|
+
"kurbo",
|
|
496
|
+
"siphasher",
|
|
497
|
+
]
|
|
498
|
+
|
|
499
|
+
[[package]]
|
|
500
|
+
name = "syn"
|
|
501
|
+
version = "2.0.117"
|
|
502
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
503
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
504
|
+
dependencies = [
|
|
505
|
+
"proc-macro2",
|
|
506
|
+
"quote",
|
|
507
|
+
"unicode-ident",
|
|
508
|
+
]
|
|
509
|
+
|
|
510
|
+
[[package]]
|
|
511
|
+
name = "target-lexicon"
|
|
512
|
+
version = "0.13.5"
|
|
513
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
514
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
515
|
+
|
|
516
|
+
[[package]]
|
|
517
|
+
name = "tiny-skia"
|
|
518
|
+
version = "0.12.0"
|
|
519
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
520
|
+
checksum = "47ffee5eaaf5527f630fb0e356b90ebdec84d5d18d937c5e440350f88c5a91ea"
|
|
521
|
+
dependencies = [
|
|
522
|
+
"arrayref",
|
|
523
|
+
"arrayvec",
|
|
524
|
+
"bytemuck",
|
|
525
|
+
"cfg-if",
|
|
526
|
+
"log",
|
|
527
|
+
"png",
|
|
528
|
+
"tiny-skia-path",
|
|
529
|
+
]
|
|
530
|
+
|
|
531
|
+
[[package]]
|
|
532
|
+
name = "tiny-skia-path"
|
|
533
|
+
version = "0.12.0"
|
|
534
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
535
|
+
checksum = "edca365c3faccca67d06593c5980fa6c57687de727a03131735bb85f01fdeeb9"
|
|
536
|
+
dependencies = [
|
|
537
|
+
"arrayref",
|
|
538
|
+
"bytemuck",
|
|
539
|
+
"strict-num",
|
|
540
|
+
]
|
|
541
|
+
|
|
542
|
+
[[package]]
|
|
543
|
+
name = "tinyvec"
|
|
544
|
+
version = "1.11.0"
|
|
545
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
546
|
+
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
|
|
547
|
+
dependencies = [
|
|
548
|
+
"tinyvec_macros",
|
|
549
|
+
]
|
|
550
|
+
|
|
551
|
+
[[package]]
|
|
552
|
+
name = "tinyvec_macros"
|
|
553
|
+
version = "0.1.1"
|
|
554
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
555
|
+
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|
556
|
+
|
|
557
|
+
[[package]]
|
|
558
|
+
name = "ttf-parser"
|
|
559
|
+
version = "0.25.1"
|
|
560
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
561
|
+
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
|
562
|
+
dependencies = [
|
|
563
|
+
"core_maths",
|
|
564
|
+
]
|
|
565
|
+
|
|
566
|
+
[[package]]
|
|
567
|
+
name = "unicode-bidi"
|
|
568
|
+
version = "0.3.18"
|
|
569
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
570
|
+
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
|
|
571
|
+
|
|
572
|
+
[[package]]
|
|
573
|
+
name = "unicode-bidi-mirroring"
|
|
574
|
+
version = "0.4.0"
|
|
575
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
576
|
+
checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe"
|
|
577
|
+
|
|
578
|
+
[[package]]
|
|
579
|
+
name = "unicode-ccc"
|
|
580
|
+
version = "0.4.0"
|
|
581
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
582
|
+
checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e"
|
|
583
|
+
|
|
584
|
+
[[package]]
|
|
585
|
+
name = "unicode-ident"
|
|
586
|
+
version = "1.0.24"
|
|
587
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
588
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
589
|
+
|
|
590
|
+
[[package]]
|
|
591
|
+
name = "unicode-properties"
|
|
592
|
+
version = "0.1.4"
|
|
593
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
594
|
+
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
|
|
595
|
+
|
|
596
|
+
[[package]]
|
|
597
|
+
name = "unicode-script"
|
|
598
|
+
version = "0.5.8"
|
|
599
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
600
|
+
checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee"
|
|
601
|
+
|
|
602
|
+
[[package]]
|
|
603
|
+
name = "unicode-vo"
|
|
604
|
+
version = "0.1.0"
|
|
605
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
606
|
+
checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
|
|
607
|
+
|
|
608
|
+
[[package]]
|
|
609
|
+
name = "usvg"
|
|
610
|
+
version = "0.47.0"
|
|
611
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
612
|
+
checksum = "d46cf96c5f498d36b7a9693bc6a7075c0bb9303189d61b2249b0dc3d309c07de"
|
|
613
|
+
dependencies = [
|
|
614
|
+
"base64",
|
|
615
|
+
"data-url",
|
|
616
|
+
"flate2",
|
|
617
|
+
"fontdb",
|
|
618
|
+
"imagesize",
|
|
619
|
+
"kurbo",
|
|
620
|
+
"log",
|
|
621
|
+
"pico-args",
|
|
622
|
+
"roxmltree 0.21.1",
|
|
623
|
+
"rustybuzz",
|
|
624
|
+
"simplecss",
|
|
625
|
+
"siphasher",
|
|
626
|
+
"strict-num",
|
|
627
|
+
"svgtypes",
|
|
628
|
+
"tiny-skia-path",
|
|
629
|
+
"ttf-parser",
|
|
630
|
+
"unicode-bidi",
|
|
631
|
+
"unicode-script",
|
|
632
|
+
"unicode-vo",
|
|
633
|
+
"xmlwriter",
|
|
634
|
+
]
|
|
635
|
+
|
|
636
|
+
[[package]]
|
|
637
|
+
name = "version_check"
|
|
638
|
+
version = "0.9.5"
|
|
639
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
640
|
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
641
|
+
|
|
642
|
+
[[package]]
|
|
643
|
+
name = "wasm-bindgen"
|
|
644
|
+
version = "0.2.122"
|
|
645
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
646
|
+
checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
|
|
647
|
+
dependencies = [
|
|
648
|
+
"cfg-if",
|
|
649
|
+
"once_cell",
|
|
650
|
+
"rustversion",
|
|
651
|
+
"wasm-bindgen-macro",
|
|
652
|
+
"wasm-bindgen-shared",
|
|
653
|
+
]
|
|
654
|
+
|
|
655
|
+
[[package]]
|
|
656
|
+
name = "wasm-bindgen-macro"
|
|
657
|
+
version = "0.2.122"
|
|
658
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
659
|
+
checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
|
|
660
|
+
dependencies = [
|
|
661
|
+
"quote",
|
|
662
|
+
"wasm-bindgen-macro-support",
|
|
663
|
+
]
|
|
664
|
+
|
|
665
|
+
[[package]]
|
|
666
|
+
name = "wasm-bindgen-macro-support"
|
|
667
|
+
version = "0.2.122"
|
|
668
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
669
|
+
checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
|
|
670
|
+
dependencies = [
|
|
671
|
+
"bumpalo",
|
|
672
|
+
"proc-macro2",
|
|
673
|
+
"quote",
|
|
674
|
+
"syn",
|
|
675
|
+
"wasm-bindgen-shared",
|
|
676
|
+
]
|
|
677
|
+
|
|
678
|
+
[[package]]
|
|
679
|
+
name = "wasm-bindgen-shared"
|
|
680
|
+
version = "0.2.122"
|
|
681
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
682
|
+
checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
|
|
683
|
+
dependencies = [
|
|
684
|
+
"unicode-ident",
|
|
685
|
+
]
|
|
686
|
+
|
|
687
|
+
[[package]]
|
|
688
|
+
name = "weezl"
|
|
689
|
+
version = "0.1.12"
|
|
690
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
691
|
+
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
|
692
|
+
|
|
693
|
+
[[package]]
|
|
694
|
+
name = "xmlwriter"
|
|
695
|
+
version = "0.1.0"
|
|
696
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
697
|
+
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
|
698
|
+
|
|
699
|
+
[[package]]
|
|
700
|
+
name = "zune-core"
|
|
701
|
+
version = "0.5.1"
|
|
702
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
703
|
+
checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
|
|
704
|
+
|
|
705
|
+
[[package]]
|
|
706
|
+
name = "zune-jpeg"
|
|
707
|
+
version = "0.5.15"
|
|
708
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
709
|
+
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
|
710
|
+
dependencies = [
|
|
711
|
+
"zune-core",
|
|
712
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "kymostudio-core"
|
|
3
|
+
version = "0.3.5"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
rust-version = "1.74"
|
|
6
|
+
description = "Type it. See it appear. Watch it animate."
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
repository = "https://github.com/kymostudio/kymostudio"
|
|
9
|
+
homepage = "https://github.com/kymostudio/kymostudio"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
keywords = ["svg", "png", "rasterizer", "diagram", "resvg"]
|
|
12
|
+
categories = ["multimedia::images", "command-line-utilities", "wasm"]
|
|
13
|
+
|
|
14
|
+
# rlib -> native CLI + tests; cdylib -> Python (pyo3) and wasm (wasm-bindgen).
|
|
15
|
+
[lib]
|
|
16
|
+
name = "kymostudio_core"
|
|
17
|
+
path = "src/lib.rs"
|
|
18
|
+
crate-type = ["rlib", "cdylib"]
|
|
19
|
+
|
|
20
|
+
# The `kymo` CLI (native only — built under default features).
|
|
21
|
+
[[bin]]
|
|
22
|
+
name = "kymo"
|
|
23
|
+
path = "src/main.rs"
|
|
24
|
+
|
|
25
|
+
[dependencies]
|
|
26
|
+
# Core SVG engine. system-fonts + memmap-fonts pull in fs/mmap (no good on
|
|
27
|
+
# wasm) so they live behind the `system-fonts` feature, OFF for the wasm build.
|
|
28
|
+
resvg = { version = "0.47", default-features = false, features = ["text", "raster-images"] }
|
|
29
|
+
|
|
30
|
+
# Binding deps — each pulled in only by its feature.
|
|
31
|
+
pyo3 = { version = "0.28", features = ["extension-module", "abi3-py310"], optional = true }
|
|
32
|
+
wasm-bindgen = { version = "0.2", optional = true }
|
|
33
|
+
|
|
34
|
+
[features]
|
|
35
|
+
# Native builds (CLI, tests, Python wheel) load system fonts so <text> renders.
|
|
36
|
+
default = ["system-fonts"]
|
|
37
|
+
system-fonts = ["resvg/system-fonts", "resvg/memmap-fonts"]
|
|
38
|
+
|
|
39
|
+
# Python extension module (maturin builds the cdylib with this on).
|
|
40
|
+
python = ["dep:pyo3", "system-fonts"]
|
|
41
|
+
|
|
42
|
+
# wasm (browser + Node) — deliberately NO system-fonts (no fs/mmap on wasm).
|
|
43
|
+
wasm = ["dep:wasm-bindgen"]
|
|
44
|
+
|
|
45
|
+
[profile.release]
|
|
46
|
+
opt-level = 3
|
|
47
|
+
lto = true
|
|
48
|
+
strip = true
|
|
49
|
+
|
|
50
|
+
# wasm-pack post-processing. wasm-opt is disabled for deterministic builds
|
|
51
|
+
# across environments (the prebuilt binary is flaky on some hosts); re-enable
|
|
52
|
+
# once a pinned wasm-opt is wired into CI to shrink the ~2.4 MB module.
|
|
53
|
+
[package.metadata.wasm-pack.profile.release]
|
|
54
|
+
wasm-opt = false
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kymostudio-core
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
7
|
+
Summary: Type it. See it appear. Watch it animate.
|
|
8
|
+
Keywords: svg,png,rasterizer,diagram,resvg
|
|
9
|
+
Home-Page: https://github.com/kymostudio/kymostudio
|
|
10
|
+
Author-email: rain1024 <anhv.ict91@gmail.com>
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
14
|
+
Project-URL: Homepage, https://github.com/kymostudio/kymostudio
|
|
15
|
+
Project-URL: Repository, https://github.com/kymostudio/kymostudio
|
|
16
|
+
|
|
17
|
+
# kymostudio-core (Rust)
|
|
18
|
+
|
|
19
|
+
Pure-Rust SVG → PNG rasterizer core for **kymostudio**, built on
|
|
20
|
+
[`resvg`](https://github.com/linebender/resvg). No browser, no headless Chrome,
|
|
21
|
+
no C/Cairo/Skia system dependencies.
|
|
22
|
+
|
|
23
|
+
One core crate, compiled to **four targets** from a single source via feature
|
|
24
|
+
flags — so the Rust CLI, the Python package, and the JS/browser playground all
|
|
25
|
+
share the exact same resvg engine (`resvg` is **CSS-class-aware**, the reason the
|
|
26
|
+
project avoids cairosvg):
|
|
27
|
+
|
|
28
|
+
| Target | Feature | Build tool | Consumer |
|
|
29
|
+
|--------|---------|-----------|----------|
|
|
30
|
+
| Native lib + `kymo` CLI | `system-fonts` (default) | `cargo` | standalone CLI |
|
|
31
|
+
| Python extension (abi3) | `python` | `maturin` → wheel | `packages/python` |
|
|
32
|
+
| wasm (browser + Node) | `wasm` | `wasm-pack` → pkg | `packages/js`, website playground |
|
|
33
|
+
|
|
34
|
+
`svg_to_png(svg: &[u8], scale: f32) -> Result<Vec<u8>, RenderError>` is the one
|
|
35
|
+
core function; each binding (`src/python.rs`, `src/wasm.rs`) is a thin façade.
|
|
36
|
+
|
|
37
|
+
## CLI — `kymo`
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
kymo -i in.svg out.png # rasterize at intrinsic size
|
|
41
|
+
kymo -i diagram.svg # output defaults to diagram.png
|
|
42
|
+
kymo -i diagram.svg -s 2 hi.png # 2× resolution
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| Flag | Meaning |
|
|
46
|
+
|------|---------|
|
|
47
|
+
| `-i, --input <FILE>` | Input SVG (required) |
|
|
48
|
+
| `-o, --output <FILE>` | Output PNG (or pass it positionally) |
|
|
49
|
+
| `-s, --scale <N>` | Scale factor, `1.0` = intrinsic size (default `1`) |
|
|
50
|
+
| `-h, --help` / `-V, --version` | Help / version |
|
|
51
|
+
|
|
52
|
+
## Build each target
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Native (CLI + lib + tests)
|
|
56
|
+
cargo test
|
|
57
|
+
cargo build --release --bin kymo # -> target/release/kymo
|
|
58
|
+
|
|
59
|
+
# Python wheel (abi3, one wheel for CPython ≥ 3.10)
|
|
60
|
+
maturin build --release --out dist # -> dist/kymostudio_core-*-abi3-*.whl
|
|
61
|
+
# import _kymostudio_core; _kymostudio_core.svg_to_png(svg_bytes, scale)
|
|
62
|
+
|
|
63
|
+
# wasm (browser + Node) — system-fonts OFF (no fs/mmap on wasm)
|
|
64
|
+
wasm-pack build --target web --out-dir pkg --out-name kymostudio_core \
|
|
65
|
+
-- --no-default-features --features wasm
|
|
66
|
+
# import { svgToPng } from './pkg/kymostudio_core.js'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
CI builds and smoke-tests all of the above across Linux/macOS/Windows —
|
|
70
|
+
see `.github/workflows/rust.yml`.
|
|
71
|
+
|
|
72
|
+
## Library use (Rust)
|
|
73
|
+
|
|
74
|
+
```rust
|
|
75
|
+
let svg = std::fs::read("in.svg")?;
|
|
76
|
+
let png: Vec<u8> = kymostudio_core::svg_to_png(&svg, 1.0)?;
|
|
77
|
+
std::fs::write("out.png", png)?;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The version is kept in **lockstep** with the rest of the monorepo
|
|
81
|
+
(`Cargo.toml` → `version`).
|
|
82
|
+
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# kymostudio-core (Rust)
|
|
2
|
+
|
|
3
|
+
Pure-Rust SVG → PNG rasterizer core for **kymostudio**, built on
|
|
4
|
+
[`resvg`](https://github.com/linebender/resvg). No browser, no headless Chrome,
|
|
5
|
+
no C/Cairo/Skia system dependencies.
|
|
6
|
+
|
|
7
|
+
One core crate, compiled to **four targets** from a single source via feature
|
|
8
|
+
flags — so the Rust CLI, the Python package, and the JS/browser playground all
|
|
9
|
+
share the exact same resvg engine (`resvg` is **CSS-class-aware**, the reason the
|
|
10
|
+
project avoids cairosvg):
|
|
11
|
+
|
|
12
|
+
| Target | Feature | Build tool | Consumer |
|
|
13
|
+
|--------|---------|-----------|----------|
|
|
14
|
+
| Native lib + `kymo` CLI | `system-fonts` (default) | `cargo` | standalone CLI |
|
|
15
|
+
| Python extension (abi3) | `python` | `maturin` → wheel | `packages/python` |
|
|
16
|
+
| wasm (browser + Node) | `wasm` | `wasm-pack` → pkg | `packages/js`, website playground |
|
|
17
|
+
|
|
18
|
+
`svg_to_png(svg: &[u8], scale: f32) -> Result<Vec<u8>, RenderError>` is the one
|
|
19
|
+
core function; each binding (`src/python.rs`, `src/wasm.rs`) is a thin façade.
|
|
20
|
+
|
|
21
|
+
## CLI — `kymo`
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
kymo -i in.svg out.png # rasterize at intrinsic size
|
|
25
|
+
kymo -i diagram.svg # output defaults to diagram.png
|
|
26
|
+
kymo -i diagram.svg -s 2 hi.png # 2× resolution
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Flag | Meaning |
|
|
30
|
+
|------|---------|
|
|
31
|
+
| `-i, --input <FILE>` | Input SVG (required) |
|
|
32
|
+
| `-o, --output <FILE>` | Output PNG (or pass it positionally) |
|
|
33
|
+
| `-s, --scale <N>` | Scale factor, `1.0` = intrinsic size (default `1`) |
|
|
34
|
+
| `-h, --help` / `-V, --version` | Help / version |
|
|
35
|
+
|
|
36
|
+
## Build each target
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Native (CLI + lib + tests)
|
|
40
|
+
cargo test
|
|
41
|
+
cargo build --release --bin kymo # -> target/release/kymo
|
|
42
|
+
|
|
43
|
+
# Python wheel (abi3, one wheel for CPython ≥ 3.10)
|
|
44
|
+
maturin build --release --out dist # -> dist/kymostudio_core-*-abi3-*.whl
|
|
45
|
+
# import _kymostudio_core; _kymostudio_core.svg_to_png(svg_bytes, scale)
|
|
46
|
+
|
|
47
|
+
# wasm (browser + Node) — system-fonts OFF (no fs/mmap on wasm)
|
|
48
|
+
wasm-pack build --target web --out-dir pkg --out-name kymostudio_core \
|
|
49
|
+
-- --no-default-features --features wasm
|
|
50
|
+
# import { svgToPng } from './pkg/kymostudio_core.js'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
CI builds and smoke-tests all of the above across Linux/macOS/Windows —
|
|
54
|
+
see `.github/workflows/rust.yml`.
|
|
55
|
+
|
|
56
|
+
## Library use (Rust)
|
|
57
|
+
|
|
58
|
+
```rust
|
|
59
|
+
let svg = std::fs::read("in.svg")?;
|
|
60
|
+
let png: Vec<u8> = kymostudio_core::svg_to_png(&svg, 1.0)?;
|
|
61
|
+
std::fs::write("out.png", png)?;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The version is kept in **lockstep** with the rest of the monorepo
|
|
65
|
+
(`Cargo.toml` → `version`).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.7,<2"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "kymostudio-core"
|
|
7
|
+
version = "0.3.3"
|
|
8
|
+
description = "Type it. See it appear. Watch it animate."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "rain1024", email = "anhv.ict91@gmail.com" }]
|
|
13
|
+
keywords = ["svg", "png", "rasterizer", "diagram", "resvg"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Rust",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Topic :: Multimedia :: Graphics",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/kymostudio/kymostudio"
|
|
22
|
+
Repository = "https://github.com/kymostudio/kymostudio"
|
|
23
|
+
|
|
24
|
+
[tool.maturin]
|
|
25
|
+
# Build the `python` feature; ship a single abi3 wheel (cp310-abi3).
|
|
26
|
+
features = ["python"]
|
|
27
|
+
module-name = "_kymostudio_core"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//! kymostudio core — pure-Rust SVG rasterization built on [`resvg`].
|
|
2
|
+
//!
|
|
3
|
+
//! No browser, no headless Chrome, no C dependencies. This mirrors what the
|
|
4
|
+
//! Python package does via `resvg-py` (`to_webp.py`) so SVG→PNG output stays
|
|
5
|
+
//! consistent across implementations — `resvg` is CSS-class-aware, which is why
|
|
6
|
+
//! the project avoids cairosvg.
|
|
7
|
+
|
|
8
|
+
use resvg::{tiny_skia, usvg};
|
|
9
|
+
|
|
10
|
+
// Language-binding facades — each compiled only when its feature is on.
|
|
11
|
+
#[cfg(feature = "python")]
|
|
12
|
+
mod python;
|
|
13
|
+
#[cfg(feature = "wasm")]
|
|
14
|
+
mod wasm;
|
|
15
|
+
|
|
16
|
+
/// Something went wrong turning SVG bytes into PNG bytes.
|
|
17
|
+
#[derive(Debug)]
|
|
18
|
+
pub enum RenderError {
|
|
19
|
+
/// The SVG could not be parsed.
|
|
20
|
+
Parse(usvg::Error),
|
|
21
|
+
/// The requested raster size was degenerate (zero / overflow).
|
|
22
|
+
Size { width: u32, height: u32 },
|
|
23
|
+
/// PNG encoding failed.
|
|
24
|
+
Encode(String),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl std::fmt::Display for RenderError {
|
|
28
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
29
|
+
match self {
|
|
30
|
+
RenderError::Parse(e) => write!(f, "invalid SVG: {e}"),
|
|
31
|
+
RenderError::Size { width, height } => {
|
|
32
|
+
write!(f, "invalid raster size {width}x{height}")
|
|
33
|
+
}
|
|
34
|
+
RenderError::Encode(e) => write!(f, "PNG encoding failed: {e}"),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl std::error::Error for RenderError {}
|
|
40
|
+
|
|
41
|
+
impl From<usvg::Error> for RenderError {
|
|
42
|
+
fn from(e: usvg::Error) -> Self {
|
|
43
|
+
RenderError::Parse(e)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Render SVG bytes to PNG bytes at the given `scale` (1.0 = intrinsic size).
|
|
48
|
+
///
|
|
49
|
+
/// On native builds (`system-fonts` feature, the default) system fonts are
|
|
50
|
+
/// loaded so `<text>` elements rasterize correctly. On wasm that feature is
|
|
51
|
+
/// off — supply fonts in the SVG, or the caller resolves them.
|
|
52
|
+
pub fn svg_to_png(svg: &[u8], scale: f32) -> Result<Vec<u8>, RenderError> {
|
|
53
|
+
#[allow(unused_mut)]
|
|
54
|
+
let mut opt = usvg::Options::default();
|
|
55
|
+
#[cfg(feature = "system-fonts")]
|
|
56
|
+
opt.fontdb_mut().load_system_fonts();
|
|
57
|
+
|
|
58
|
+
let tree = usvg::Tree::from_data(svg, &opt)?;
|
|
59
|
+
let size = tree.size();
|
|
60
|
+
|
|
61
|
+
let width = ((size.width() * scale).round() as i64).clamp(1, u32::MAX as i64) as u32;
|
|
62
|
+
let height = ((size.height() * scale).round() as i64).clamp(1, u32::MAX as i64) as u32;
|
|
63
|
+
|
|
64
|
+
let mut pixmap =
|
|
65
|
+
tiny_skia::Pixmap::new(width, height).ok_or(RenderError::Size { width, height })?;
|
|
66
|
+
|
|
67
|
+
let transform = tiny_skia::Transform::from_scale(scale, scale);
|
|
68
|
+
resvg::render(&tree, transform, &mut pixmap.as_mut());
|
|
69
|
+
|
|
70
|
+
pixmap
|
|
71
|
+
.encode_png()
|
|
72
|
+
.map_err(|e| RenderError::Encode(e.to_string()))
|
|
73
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
//! `kymo` CLI — rasterize an SVG to PNG.
|
|
2
|
+
//!
|
|
3
|
+
//! kymo -i in.svg out.png
|
|
4
|
+
//! kymo -i in.svg -o out.png --scale 2
|
|
5
|
+
//!
|
|
6
|
+
//! Pure Rust (resvg) — no browser, no system image libraries.
|
|
7
|
+
|
|
8
|
+
use std::path::PathBuf;
|
|
9
|
+
use std::process::ExitCode;
|
|
10
|
+
|
|
11
|
+
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
12
|
+
|
|
13
|
+
const HELP: &str = "\
|
|
14
|
+
kymo — rasterize an SVG to PNG (pure Rust, no browser)
|
|
15
|
+
|
|
16
|
+
USAGE:
|
|
17
|
+
kymo -i <input.svg> [output.png] [options]
|
|
18
|
+
|
|
19
|
+
ARGS:
|
|
20
|
+
<output.png> Output path (positional). Defaults to the input
|
|
21
|
+
path with its extension swapped to .png.
|
|
22
|
+
|
|
23
|
+
OPTIONS:
|
|
24
|
+
-i, --input <FILE> Input SVG file (required)
|
|
25
|
+
-o, --output <FILE> Output PNG file (alternative to the positional arg)
|
|
26
|
+
-s, --scale <N> Scale factor, 1.0 = intrinsic size (default: 1)
|
|
27
|
+
-h, --help Print this help
|
|
28
|
+
-V, --version Print version
|
|
29
|
+
|
|
30
|
+
EXAMPLES:
|
|
31
|
+
kymo -i in.svg out.png
|
|
32
|
+
kymo -i diagram.svg # -> diagram.png
|
|
33
|
+
kymo -i diagram.svg -s 2 hi.png # 2x resolution
|
|
34
|
+
";
|
|
35
|
+
|
|
36
|
+
struct Args {
|
|
37
|
+
input: PathBuf,
|
|
38
|
+
output: PathBuf,
|
|
39
|
+
scale: f32,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
enum Parsed {
|
|
43
|
+
Run(Args),
|
|
44
|
+
Help,
|
|
45
|
+
Version,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fn parse(argv: &[String]) -> Result<Parsed, String> {
|
|
49
|
+
let mut input: Option<PathBuf> = None;
|
|
50
|
+
let mut output: Option<PathBuf> = None;
|
|
51
|
+
let mut scale: f32 = 1.0;
|
|
52
|
+
let mut positionals: Vec<String> = Vec::new();
|
|
53
|
+
|
|
54
|
+
let mut it = argv.iter();
|
|
55
|
+
while let Some(arg) = it.next() {
|
|
56
|
+
match arg.as_str() {
|
|
57
|
+
"-h" | "--help" => return Ok(Parsed::Help),
|
|
58
|
+
"-V" | "--version" => return Ok(Parsed::Version),
|
|
59
|
+
"-i" | "--input" => {
|
|
60
|
+
let v = it.next().ok_or("missing value for --input")?;
|
|
61
|
+
input = Some(PathBuf::from(v));
|
|
62
|
+
}
|
|
63
|
+
"-o" | "--output" => {
|
|
64
|
+
let v = it.next().ok_or("missing value for --output")?;
|
|
65
|
+
output = Some(PathBuf::from(v));
|
|
66
|
+
}
|
|
67
|
+
"-s" | "--scale" => {
|
|
68
|
+
let v = it.next().ok_or("missing value for --scale")?;
|
|
69
|
+
scale = v.parse().map_err(|_| format!("invalid scale: {v}"))?;
|
|
70
|
+
if !scale.is_finite() || scale <= 0.0 {
|
|
71
|
+
return Err(format!("scale must be positive, got {v}"));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
s if s.starts_with('-') && s.len() > 1 => {
|
|
75
|
+
return Err(format!("unknown option: {s}"));
|
|
76
|
+
}
|
|
77
|
+
_ => positionals.push(arg.clone()),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Allow input as a bare positional too: `kymo in.svg out.png`.
|
|
82
|
+
if input.is_none() && !positionals.is_empty() {
|
|
83
|
+
input = Some(PathBuf::from(positionals.remove(0)));
|
|
84
|
+
}
|
|
85
|
+
if output.is_none() && !positionals.is_empty() {
|
|
86
|
+
output = Some(PathBuf::from(positionals.remove(0)));
|
|
87
|
+
}
|
|
88
|
+
if let Some(extra) = positionals.first() {
|
|
89
|
+
return Err(format!("unexpected argument: {extra}"));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let input = input.ok_or("missing required input (use -i <file.svg>)")?;
|
|
93
|
+
let output = output.unwrap_or_else(|| input.with_extension("png"));
|
|
94
|
+
Ok(Parsed::Run(Args {
|
|
95
|
+
input,
|
|
96
|
+
output,
|
|
97
|
+
scale,
|
|
98
|
+
}))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fn run(args: Args) -> Result<(), String> {
|
|
102
|
+
let svg = std::fs::read(&args.input)
|
|
103
|
+
.map_err(|e| format!("cannot read {}: {e}", args.input.display()))?;
|
|
104
|
+
let png = kymostudio_core::svg_to_png(&svg, args.scale).map_err(|e| e.to_string())?;
|
|
105
|
+
std::fs::write(&args.output, &png)
|
|
106
|
+
.map_err(|e| format!("cannot write {}: {e}", args.output.display()))?;
|
|
107
|
+
eprintln!(
|
|
108
|
+
"{} -> {} ({} bytes)",
|
|
109
|
+
args.input.display(),
|
|
110
|
+
args.output.display(),
|
|
111
|
+
png.len()
|
|
112
|
+
);
|
|
113
|
+
Ok(())
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fn main() -> ExitCode {
|
|
117
|
+
let argv: Vec<String> = std::env::args().skip(1).collect();
|
|
118
|
+
match parse(&argv) {
|
|
119
|
+
Ok(Parsed::Help) => {
|
|
120
|
+
print!("{HELP}");
|
|
121
|
+
ExitCode::SUCCESS
|
|
122
|
+
}
|
|
123
|
+
Ok(Parsed::Version) => {
|
|
124
|
+
println!("kymo {VERSION}");
|
|
125
|
+
ExitCode::SUCCESS
|
|
126
|
+
}
|
|
127
|
+
Ok(Parsed::Run(args)) => match run(args) {
|
|
128
|
+
Ok(()) => ExitCode::SUCCESS,
|
|
129
|
+
Err(e) => {
|
|
130
|
+
eprintln!("kymo: {e}");
|
|
131
|
+
ExitCode::FAILURE
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
Err(e) => {
|
|
135
|
+
eprintln!("kymo: {e}\n\nTry 'kymo --help'.");
|
|
136
|
+
ExitCode::FAILURE
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//! Python binding (PyO3). Built by maturin under the `python` feature.
|
|
2
|
+
//!
|
|
3
|
+
//! Exposes module `_kymostudio_core` with:
|
|
4
|
+
//! svg_to_png(svg: bytes, scale: float = 1.0) -> bytes
|
|
5
|
+
|
|
6
|
+
use pyo3::prelude::*;
|
|
7
|
+
use pyo3::types::PyBytes;
|
|
8
|
+
|
|
9
|
+
/// Rasterize `svg` (bytes) to PNG bytes at `scale` (1.0 = intrinsic size).
|
|
10
|
+
#[pyfunction]
|
|
11
|
+
#[pyo3(signature = (svg, scale = 1.0))]
|
|
12
|
+
fn svg_to_png<'py>(py: Python<'py>, svg: &[u8], scale: f32) -> PyResult<Bound<'py, PyBytes>> {
|
|
13
|
+
let png = crate::svg_to_png(svg, scale)
|
|
14
|
+
.map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))?;
|
|
15
|
+
Ok(PyBytes::new(py, &png))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#[pymodule]
|
|
19
|
+
fn _kymostudio_core(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
20
|
+
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
|
|
21
|
+
m.add_function(wrap_pyfunction!(svg_to_png, m)?)?;
|
|
22
|
+
Ok(())
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//! wasm binding (wasm-bindgen). Built by wasm-pack under the `wasm` feature.
|
|
2
|
+
//! Runs in the browser (website/playground) and in Node.
|
|
3
|
+
//!
|
|
4
|
+
//! JS surface:
|
|
5
|
+
//! svgToPng(svg: Uint8Array, scale?: number): Uint8Array
|
|
6
|
+
|
|
7
|
+
use wasm_bindgen::prelude::*;
|
|
8
|
+
|
|
9
|
+
/// Rasterize `svg` bytes to PNG bytes at `scale` (1.0 = intrinsic size).
|
|
10
|
+
#[wasm_bindgen(js_name = svgToPng)]
|
|
11
|
+
pub fn svg_to_png(svg: &[u8], scale: Option<f32>) -> Result<Vec<u8>, JsError> {
|
|
12
|
+
crate::svg_to_png(svg, scale.unwrap_or(1.0)).map_err(|e| JsError::new(&e.to_string()))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// The crate version, exposed to JS as `version()`.
|
|
16
|
+
#[wasm_bindgen]
|
|
17
|
+
pub fn version() -> String {
|
|
18
|
+
env!("CARGO_PKG_VERSION").to_string()
|
|
19
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//! Integration tests for the SVG→PNG core.
|
|
2
|
+
|
|
3
|
+
const PNG_MAGIC: &[u8] = b"\x89PNG\r\n\x1a\n";
|
|
4
|
+
|
|
5
|
+
const SQUARE: &[u8] =
|
|
6
|
+
br##"<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><rect width="20" height="20" fill="#7cb342"/></svg>"##;
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn renders_valid_png() {
|
|
10
|
+
let png = kymostudio_core::svg_to_png(SQUARE, 1.0).expect("render");
|
|
11
|
+
assert!(png.starts_with(PNG_MAGIC), "output is not a PNG");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[test]
|
|
15
|
+
fn scale_changes_pixel_dimensions() {
|
|
16
|
+
// PNG IHDR stores width/height as big-endian u32 at byte offset 16.
|
|
17
|
+
let dims = |png: &[u8]| {
|
|
18
|
+
let w = u32::from_be_bytes(png[16..20].try_into().unwrap());
|
|
19
|
+
let h = u32::from_be_bytes(png[20..24].try_into().unwrap());
|
|
20
|
+
(w, h)
|
|
21
|
+
};
|
|
22
|
+
let base = kymostudio_core::svg_to_png(SQUARE, 1.0).unwrap();
|
|
23
|
+
let big = kymostudio_core::svg_to_png(SQUARE, 3.0).unwrap();
|
|
24
|
+
assert_eq!(dims(&base), (20, 20));
|
|
25
|
+
assert_eq!(dims(&big), (60, 60));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[test]
|
|
29
|
+
fn rejects_garbage() {
|
|
30
|
+
assert!(kymostudio_core::svg_to_png(b"not an svg at all", 1.0).is_err());
|
|
31
|
+
}
|