summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.envrc1
-rw-r--r--.gitignore1
-rw-r--r--.luarc.json4
-rw-r--r--Cargo.lock759
-rw-r--r--Cargo.toml10
-rw-r--r--TODO.md4
-rw-r--r--cairo-renderer/Cargo.toml14
-rw-r--r--cairo-renderer/src/drawing/cairo/mod.rs35
-rw-r--r--cairo-renderer/src/drawing/mod.rs8
-rw-r--r--cairo-renderer/src/lib.rs111
-rw-r--r--cli/Cargo.toml12
-rw-r--r--cli/src/main.rs188
-rw-r--r--core/Cargo.toml10
-rw-r--r--core/src/colors.rs34
-rw-r--r--core/src/complex_shapes.rs285
-rw-r--r--core/src/core_shapes.rs86
-rw-r--r--core/src/lib.rs19
-rw-r--r--core/src/mod.rs90
-rw-r--r--core/src/rendering.rs86
-rw-r--r--core/src/runtime.rs95
-rw-r--r--core/src/solving.rs279
-rw-r--r--core/src/styles.rs161
-rw-r--r--core/src/text.rs81
-rw-r--r--core/src/types.rs316
-rw-r--r--examples/lib-dfscq-log/Cargo.toml15
-rw-r--r--examples/lib-dfscq-log/dfscq-log.lua124
-rw-r--r--examples/lib-dfscq-log/src/block_list.rs183
-rw-r--r--examples/lib-dfscq-log/src/blocks.rs72
-rw-r--r--examples/lib-dfscq-log/src/bracket.rs42
-rw-r--r--examples/lib-dfscq-log/src/explode.rs86
-rw-r--r--examples/lib-dfscq-log/src/labeled.rs64
-rw-r--r--examples/lib-dfscq-log/src/labeled_delimiter.rs121
-rw-r--r--examples/lib-dfscq-log/src/layer.rs169
-rw-r--r--examples/lib-dfscq-log/src/main.rs642
-rw-r--r--examples/lib-dfscq-log/src/main2.rs61
-rw-r--r--examples/lib-dfscq-log/src/spacer.rs133
-rw-r--r--flake.lock27
-rw-r--r--flake.nix22
-rw-r--r--lua-bindings/Cargo.toml15
-rw-r--r--lua-bindings/src/lib.rs116
l---------result1
-rw-r--r--shell.nix10
-rw-r--r--test.svg377
-rw-r--r--z3-solver/Cargo.toml12
-rw-r--r--z3-solver/src/lib.rs691
-rw-r--r--z3-solver/src/solving/mod.rs9
-rw-r--r--z3-solver/src/solving/z3/mod.rs44
47 files changed, 5725 insertions, 0 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..051d09d
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
eval "$(lorri direnv)"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
/target
diff --git a/.luarc.json b/.luarc.json
new file mode 100644
index 0000000..e1b9d70
--- /dev/null
+++ b/.luarc.json
@@ -0,0 +1,4 @@
1{
2 "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
3 "Lua.workspace.checkThirdParty": false
4} \ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..f39c0de
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,759 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "anyhow"
7version = "1.0.36"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "68803225a7b13e47191bab76f2687382b60d259e8cf37f6e1893658b84bb9479"
10
11[[package]]
12name = "approx"
13version = "0.3.2"
14source = "registry+https://github.com/rust-lang/crates.io-index"
15checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
16dependencies = [
17 "num-traits",
18]
19
20[[package]]
21name = "autocfg"
22version = "1.0.1"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
25
26[[package]]
27name = "bitflags"
28version = "1.2.1"
29source = "registry+https://github.com/rust-lang/crates.io-index"
30checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
31
32[[package]]
33name = "bstr"
34version = "0.2.17"
35source = "registry+https://github.com/rust-lang/crates.io-index"
36checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
37dependencies = [
38 "memchr",
39]
40
41[[package]]
42name = "cairo-rs"
43version = "0.9.1"
44source = "registry+https://github.com/rust-lang/crates.io-index"
45checksum = "c5c0f2e047e8ca53d0ff249c54ae047931d7a6ebe05d00af73e0ffeb6e34bdb8"
46dependencies = [
47 "bitflags",
48 "cairo-sys-rs",
49 "glib",
50 "glib-sys",
51 "gobject-sys",
52 "libc",
53 "thiserror",
54]
55
56[[package]]
57name = "cairo-sys-rs"
58version = "0.10.0"
59source = "registry+https://github.com/rust-lang/crates.io-index"
60checksum = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7"
61dependencies = [
62 "glib-sys",
63 "libc",
64 "system-deps",
65]
66
67[[package]]
68name = "cc"
69version = "1.0.77"
70source = "registry+https://github.com/rust-lang/crates.io-index"
71checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
72
73[[package]]
74name = "cfg-if"
75version = "0.1.10"
76source = "registry+https://github.com/rust-lang/crates.io-index"
77checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
78
79[[package]]
80name = "diaphragm-cairo-renderer"
81version = "0.1.0"
82dependencies = [
83 "cairo-rs",
84 "diaphragm-core",
85 "pango",
86 "pangocairo",
87]
88
89[[package]]
90name = "diaphragm-core"
91version = "0.1.0"
92dependencies = [
93 "palette",
94]
95
96[[package]]
97name = "diaphragm-examples-lib-dfscq-log"
98version = "0.1.0"
99dependencies = [
100 "diaphragm-cairo-renderer",
101 "diaphragm-core",
102 "diaphragm-z3-solver",
103]
104
105[[package]]
106name = "diaphragm-lua-bindings"
107version = "0.1.0"
108dependencies = [
109 "diaphragm-cairo-renderer",
110 "diaphragm-core",
111 "diaphragm-z3-solver",
112 "mlua",
113]
114
115[[package]]
116name = "diaphragm-z3-solver"
117version = "0.1.0"
118dependencies = [
119 "diaphragm-core",
120 "z3",
121]
122
123[[package]]
124name = "either"
125version = "1.6.1"
126source = "registry+https://github.com/rust-lang/crates.io-index"
127checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
128
129[[package]]
130name = "futures-channel"
131version = "0.3.8"
132source = "registry+https://github.com/rust-lang/crates.io-index"
133checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
134dependencies = [
135 "futures-core",
136]
137
138[[package]]
139name = "futures-core"
140version = "0.3.8"
141source = "registry+https://github.com/rust-lang/crates.io-index"
142checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
143
144[[package]]
145name = "futures-executor"
146version = "0.3.8"
147source = "registry+https://github.com/rust-lang/crates.io-index"
148checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65"
149dependencies = [
150 "futures-core",
151 "futures-task",
152 "futures-util",
153]
154
155[[package]]
156name = "futures-macro"
157version = "0.3.8"
158source = "registry+https://github.com/rust-lang/crates.io-index"
159checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
160dependencies = [
161 "proc-macro-hack",
162 "proc-macro2",
163 "quote",
164 "syn",
165]
166
167[[package]]
168name = "futures-task"
169version = "0.3.8"
170source = "registry+https://github.com/rust-lang/crates.io-index"
171checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
172dependencies = [
173 "once_cell",
174]
175
176[[package]]
177name = "futures-util"
178version = "0.3.8"
179source = "registry+https://github.com/rust-lang/crates.io-index"
180checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
181dependencies = [
182 "futures-core",
183 "futures-macro",
184 "futures-task",
185 "pin-project",
186 "pin-utils",
187 "proc-macro-hack",
188 "proc-macro-nested",
189 "slab",
190]
191
192[[package]]
193name = "getrandom"
194version = "0.1.15"
195source = "registry+https://github.com/rust-lang/crates.io-index"
196checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
197dependencies = [
198 "cfg-if",
199 "libc",
200 "wasi",
201]
202
203[[package]]
204name = "glib"
205version = "0.10.3"
206source = "registry+https://github.com/rust-lang/crates.io-index"
207checksum = "0c685013b7515e668f1b57a165b009d4d28cb139a8a989bbd699c10dad29d0c5"
208dependencies = [
209 "bitflags",
210 "futures-channel",
211 "futures-core",
212 "futures-executor",
213 "futures-task",
214 "futures-util",
215 "glib-macros",
216 "glib-sys",
217 "gobject-sys",
218 "libc",
219 "once_cell",
220]
221
222[[package]]
223name = "glib-macros"
224version = "0.10.1"
225source = "registry+https://github.com/rust-lang/crates.io-index"
226checksum = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039"
227dependencies = [
228 "anyhow",
229 "heck",
230 "itertools",
231 "proc-macro-crate",
232 "proc-macro-error",
233 "proc-macro2",
234 "quote",
235 "syn",
236]
237
238[[package]]
239name = "glib-sys"
240version = "0.10.1"
241source = "registry+https://github.com/rust-lang/crates.io-index"
242checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1"
243dependencies = [
244 "libc",
245 "system-deps",
246]
247
248[[package]]
249name = "gobject-sys"
250version = "0.10.0"
251source = "registry+https://github.com/rust-lang/crates.io-index"
252checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c"
253dependencies = [
254 "glib-sys",
255 "libc",
256 "system-deps",
257]
258
259[[package]]
260name = "heck"
261version = "0.3.2"
262source = "registry+https://github.com/rust-lang/crates.io-index"
263checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
264dependencies = [
265 "unicode-segmentation",
266]
267
268[[package]]
269name = "itertools"
270version = "0.9.0"
271source = "registry+https://github.com/rust-lang/crates.io-index"
272checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
273dependencies = [
274 "either",
275]
276
277[[package]]
278name = "lazy_static"
279version = "1.4.0"
280source = "registry+https://github.com/rust-lang/crates.io-index"
281checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
282
283[[package]]
284name = "libc"
285version = "0.2.81"
286source = "registry+https://github.com/rust-lang/crates.io-index"
287checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
288
289[[package]]
290name = "log"
291version = "0.4.11"
292source = "registry+https://github.com/rust-lang/crates.io-index"
293checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
294dependencies = [
295 "cfg-if",
296]
297
298[[package]]
299name = "memchr"
300version = "2.5.0"
301source = "registry+https://github.com/rust-lang/crates.io-index"
302checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
303
304[[package]]
305name = "mlua"
306version = "0.8.6"
307source = "registry+https://github.com/rust-lang/crates.io-index"
308checksum = "4351dbcc863fb6249c81b3bd0c8001214e9d4d44d22cabda17026353a77fe612"
309dependencies = [
310 "bstr",
311 "cc",
312 "mlua_derive",
313 "num-traits",
314 "once_cell",
315 "pkg-config",
316 "rustc-hash",
317]
318
319[[package]]
320name = "mlua_derive"
321version = "0.8.0"
322source = "registry+https://github.com/rust-lang/crates.io-index"
323checksum = "b9214e60d3cf1643013b107330fcd374ccec1e4ba1eef76e7e5da5e8202e71c0"
324dependencies = [
325 "proc-macro2",
326 "quote",
327 "syn",
328]
329
330[[package]]
331name = "num-traits"
332version = "0.2.14"
333source = "registry+https://github.com/rust-lang/crates.io-index"
334checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
335dependencies = [
336 "autocfg",
337]
338
339[[package]]
340name = "once_cell"
341version = "1.5.2"
342source = "registry+https://github.com/rust-lang/crates.io-index"
343checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
344
345[[package]]
346name = "palette"
347version = "0.5.0"
348source = "registry+https://github.com/rust-lang/crates.io-index"
349checksum = "a05c0334468e62a4dfbda34b29110aa7d70d58c7fdb2c9857b5874dd9827cc59"
350dependencies = [
351 "approx",
352 "num-traits",
353 "palette_derive",
354 "phf",
355 "phf_codegen",
356]
357
358[[package]]
359name = "palette_derive"
360version = "0.5.0"
361source = "registry+https://github.com/rust-lang/crates.io-index"
362checksum = "0b4b5f600e60dd3a147fb57b4547033d382d1979eb087af310e91cb45a63b1f4"
363dependencies = [
364 "proc-macro2",
365 "quote",
366 "syn",
367]
368
369[[package]]
370name = "pango"
371version = "0.9.1"
372source = "registry+https://github.com/rust-lang/crates.io-index"
373checksum = "9937068580bebd8ced19975938573803273ccbcbd598c58d4906efd4ac87c438"
374dependencies = [
375 "bitflags",
376 "glib",
377 "glib-sys",
378 "gobject-sys",
379 "libc",
380 "once_cell",
381 "pango-sys",
382]
383
384[[package]]
385name = "pango-sys"
386version = "0.10.0"
387source = "registry+https://github.com/rust-lang/crates.io-index"
388checksum = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890"
389dependencies = [
390 "glib-sys",
391 "gobject-sys",
392 "libc",
393 "system-deps",
394]
395
396[[package]]
397name = "pangocairo"
398version = "0.10.0"
399source = "registry+https://github.com/rust-lang/crates.io-index"
400checksum = "00f5ae67a05a5e023f09f64e9a71c845274d4b82dedee237b70425811885e883"
401dependencies = [
402 "bitflags",
403 "cairo-rs",
404 "cairo-sys-rs",
405 "glib",
406 "glib-sys",
407 "gobject-sys",
408 "libc",
409 "pango",
410 "pango-sys",
411 "pangocairo-sys",
412]
413
414[[package]]
415name = "pangocairo-sys"
416version = "0.11.0"
417source = "registry+https://github.com/rust-lang/crates.io-index"
418checksum = "94ccc97f698c2f0233b84e5ca676893a1e676785b60eec700b9c0e6dcd0feb98"
419dependencies = [
420 "cairo-sys-rs",
421 "glib-sys",
422 "libc",
423 "pango-sys",
424 "system-deps",
425]
426
427[[package]]
428name = "phf"
429version = "0.8.0"
430source = "registry+https://github.com/rust-lang/crates.io-index"
431checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
432dependencies = [
433 "phf_shared",
434]
435
436[[package]]
437name = "phf_codegen"
438version = "0.8.0"
439source = "registry+https://github.com/rust-lang/crates.io-index"
440checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
441dependencies = [
442 "phf_generator",
443 "phf_shared",
444]
445
446[[package]]
447name = "phf_generator"
448version = "0.8.0"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
451dependencies = [
452 "phf_shared",
453 "rand",
454]
455
456[[package]]
457name = "phf_shared"
458version = "0.8.0"
459source = "registry+https://github.com/rust-lang/crates.io-index"
460checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
461dependencies = [
462 "siphasher",
463]
464
465[[package]]
466name = "pin-project"
467version = "1.0.2"
468source = "registry+https://github.com/rust-lang/crates.io-index"
469checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7"
470dependencies = [
471 "pin-project-internal",
472]
473
474[[package]]
475name = "pin-project-internal"
476version = "1.0.2"
477source = "registry+https://github.com/rust-lang/crates.io-index"
478checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
479dependencies = [
480 "proc-macro2",
481 "quote",
482 "syn",
483]
484
485[[package]]
486name = "pin-utils"
487version = "0.1.0"
488source = "registry+https://github.com/rust-lang/crates.io-index"
489checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
490
491[[package]]
492name = "pkg-config"
493version = "0.3.19"
494source = "registry+https://github.com/rust-lang/crates.io-index"
495checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
496
497[[package]]
498name = "ppv-lite86"
499version = "0.2.10"
500source = "registry+https://github.com/rust-lang/crates.io-index"
501checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
502
503[[package]]
504name = "proc-macro-crate"
505version = "0.1.5"
506source = "registry+https://github.com/rust-lang/crates.io-index"
507checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
508dependencies = [
509 "toml",
510]
511
512[[package]]
513name = "proc-macro-error"
514version = "1.0.4"
515source = "registry+https://github.com/rust-lang/crates.io-index"
516checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
517dependencies = [
518 "proc-macro-error-attr",
519 "proc-macro2",
520 "quote",
521 "syn",
522 "version_check",
523]
524
525[[package]]
526name = "proc-macro-error-attr"
527version = "1.0.4"
528source = "registry+https://github.com/rust-lang/crates.io-index"
529checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
530dependencies = [
531 "proc-macro2",
532 "quote",
533 "version_check",
534]
535
536[[package]]
537name = "proc-macro-hack"
538version = "0.5.19"
539source = "registry+https://github.com/rust-lang/crates.io-index"
540checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
541
542[[package]]
543name = "proc-macro-nested"
544version = "0.1.6"
545source = "registry+https://github.com/rust-lang/crates.io-index"
546checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
547
548[[package]]
549name = "proc-macro2"
550version = "1.0.24"
551source = "registry+https://github.com/rust-lang/crates.io-index"
552checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
553dependencies = [
554 "unicode-xid",
555]
556
557[[package]]
558name = "quote"
559version = "1.0.8"
560source = "registry+https://github.com/rust-lang/crates.io-index"
561checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
562dependencies = [
563 "proc-macro2",
564]
565
566[[package]]
567name = "rand"
568version = "0.7.3"
569source = "registry+https://github.com/rust-lang/crates.io-index"
570checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
571dependencies = [
572 "getrandom",
573 "libc",
574 "rand_chacha",
575 "rand_core",
576 "rand_hc",
577 "rand_pcg",
578]
579
580[[package]]
581name = "rand_chacha"
582version = "0.2.2"
583source = "registry+https://github.com/rust-lang/crates.io-index"
584checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
585dependencies = [
586 "ppv-lite86",
587 "rand_core",
588]
589
590[[package]]
591name = "rand_core"
592version = "0.5.1"
593source = "registry+https://github.com/rust-lang/crates.io-index"
594checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
595dependencies = [
596 "getrandom",
597]
598
599[[package]]
600name = "rand_hc"
601version = "0.2.0"
602source = "registry+https://github.com/rust-lang/crates.io-index"
603checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
604dependencies = [
605 "rand_core",
606]
607
608[[package]]
609name = "rand_pcg"
610version = "0.2.1"
611source = "registry+https://github.com/rust-lang/crates.io-index"
612checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
613dependencies = [
614 "rand_core",
615]
616
617[[package]]
618name = "rustc-hash"
619version = "1.1.0"
620source = "registry+https://github.com/rust-lang/crates.io-index"
621checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
622
623[[package]]
624name = "serde"
625version = "1.0.118"
626source = "registry+https://github.com/rust-lang/crates.io-index"
627checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
628
629[[package]]
630name = "siphasher"
631version = "0.3.3"
632source = "registry+https://github.com/rust-lang/crates.io-index"
633checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
634
635[[package]]
636name = "slab"
637version = "0.4.2"
638source = "registry+https://github.com/rust-lang/crates.io-index"
639checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
640
641[[package]]
642name = "strum"
643version = "0.18.0"
644source = "registry+https://github.com/rust-lang/crates.io-index"
645checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
646
647[[package]]
648name = "strum_macros"
649version = "0.18.0"
650source = "registry+https://github.com/rust-lang/crates.io-index"
651checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
652dependencies = [
653 "heck",
654 "proc-macro2",
655 "quote",
656 "syn",
657]
658
659[[package]]
660name = "syn"
661version = "1.0.55"
662source = "registry+https://github.com/rust-lang/crates.io-index"
663checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
664dependencies = [
665 "proc-macro2",
666 "quote",
667 "unicode-xid",
668]
669
670[[package]]
671name = "system-deps"
672version = "1.3.2"
673source = "registry+https://github.com/rust-lang/crates.io-index"
674checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
675dependencies = [
676 "heck",
677 "pkg-config",
678 "strum",
679 "strum_macros",
680 "thiserror",
681 "toml",
682 "version-compare",
683]
684
685[[package]]
686name = "thiserror"
687version = "1.0.22"
688source = "registry+https://github.com/rust-lang/crates.io-index"
689checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
690dependencies = [
691 "thiserror-impl",
692]
693
694[[package]]
695name = "thiserror-impl"
696version = "1.0.22"
697source = "registry+https://github.com/rust-lang/crates.io-index"
698checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
699dependencies = [
700 "proc-macro2",
701 "quote",
702 "syn",
703]
704
705[[package]]
706name = "toml"
707version = "0.5.8"
708source = "registry+https://github.com/rust-lang/crates.io-index"
709checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
710dependencies = [
711 "serde",
712]
713
714[[package]]
715name = "unicode-segmentation"
716version = "1.7.1"
717source = "registry+https://github.com/rust-lang/crates.io-index"
718checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
719
720[[package]]
721name = "unicode-xid"
722version = "0.2.1"
723source = "registry+https://github.com/rust-lang/crates.io-index"
724checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
725
726[[package]]
727name = "version-compare"
728version = "0.0.10"
729source = "registry+https://github.com/rust-lang/crates.io-index"
730checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
731
732[[package]]
733name = "version_check"
734version = "0.9.2"
735source = "registry+https://github.com/rust-lang/crates.io-index"
736checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
737
738[[package]]
739name = "wasi"
740version = "0.9.0+wasi-snapshot-preview1"
741source = "registry+https://github.com/rust-lang/crates.io-index"
742checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
743
744[[package]]
745name = "z3"
746version = "0.9.0"
747source = "registry+https://github.com/rust-lang/crates.io-index"
748checksum = "0c5bdc8c9e19d1b983c5584cd4baf6fbd71f3ca5c83283b9d46ad7780d67bd3b"
749dependencies = [
750 "lazy_static",
751 "log",
752 "z3-sys",
753]
754
755[[package]]
756name = "z3-sys"
757version = "0.6.3"
758source = "registry+https://github.com/rust-lang/crates.io-index"
759checksum = "afa18ba5fbd4933e41ffb440c3fd91f91fe9cdb7310cce3ddfb6648563811de0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..91eae68
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,10 @@
1[workspace]
2members = [
3 "cairo-renderer",
4 # "cli",
5 "core",
6 "lua-bindings",
7 "z3-solver",
8
9 "examples/lib-dfscq-log",
10]
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..da8c9b4
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,4 @@
1- Add the diaphragm language
2- Add a piet-based renderer
3- Add a web-based renderer? (maybe piet)
4- Add a live renderer (maybe druid)
diff --git a/cairo-renderer/Cargo.toml b/cairo-renderer/Cargo.toml
new file mode 100644
index 0000000..9d7d818
--- /dev/null
+++ b/cairo-renderer/Cargo.toml
@@ -0,0 +1,14 @@
1[package]
2name = "diaphragm-cairo-renderer"
3version = "0.1.0"
4authors = ["Minijackson <minijackson@riseup.net>"]
5edition = "2021"
6
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9[dependencies]
10diaphragm-core = { path = "../core" }
11
12cairo-rs = { version = "0.9", features = ["svg", "png"] }
13pango = "0.9"
14pangocairo = "0.10"
diff --git a/cairo-renderer/src/drawing/cairo/mod.rs b/cairo-renderer/src/drawing/cairo/mod.rs
new file mode 100644
index 0000000..09baa9c
--- /dev/null
+++ b/cairo-renderer/src/drawing/cairo/mod.rs
@@ -0,0 +1,35 @@
1use super::Engine;
2use crate::core::{shapes::Shape as CoreShape, types::DefinitelyBounded};
3
4use cairo::Context;
5
6pub struct CairoEngine {
7 ctx: Context,
8}
9
10impl Engine for CairoEngine {
11 fn new() -> Self {
12 let surface = cairo::SvgSurface::for_stream(200., 100., std::io::stdout()).unwrap();
13 let ctx = cairo::Context::new(&surface);
14
15 CairoEngine { ctx }
16 }
17
18 fn draw(&mut self, shape: &DefinitelyBounded<CoreShape>) {
19 let bounds = &shape.bounds;
20
21 self.ctx.move_to(bounds.left, bounds.top);
22
23 match &shape.shape {
24 CoreShape::Rectangle(_rectangle) => {
25 self.ctx
26 .rectangle(bounds.left, bounds.top, bounds.width, bounds.height);
27 self.ctx.stroke();
28 }
29 CoreShape::Text(text) => {
30 // TODO: properly shape it, with font, etc.
31 self.ctx.show_text(&text.content);
32 }
33 }
34 }
35}
diff --git a/cairo-renderer/src/drawing/mod.rs b/cairo-renderer/src/drawing/mod.rs
new file mode 100644
index 0000000..1c32fb1
--- /dev/null
+++ b/cairo-renderer/src/drawing/mod.rs
@@ -0,0 +1,8 @@
1pub mod cairo;
2
3use crate::core::{shapes::Shape as CoreShape, types::DefinitelyBounded};
4
5pub trait Engine {
6 fn new() -> Self;
7 fn draw(&mut self, shape: &DefinitelyBounded<CoreShape>);
8}
diff --git a/cairo-renderer/src/lib.rs b/cairo-renderer/src/lib.rs
new file mode 100644
index 0000000..26ca089
--- /dev/null
+++ b/cairo-renderer/src/lib.rs
@@ -0,0 +1,111 @@
1use diaphragm_core::{
2 styles::{Pattern, DefinedDashStyle},
3 text::{DefinedFontDescription, FontDescription},
4 Renderer,
5};
6
7pub struct CairoRenderer {
8 ctx: cairo::Context,
9}
10
11impl CairoRenderer {
12 pub fn new() -> Self {
13 // TODO: properly
14 let surface = cairo::SvgSurface::for_stream(1920., 1080., std::io::stdout()).unwrap();
15 let ctx = cairo::Context::new(&surface);
16
17 Self { ctx }
18 }
19}
20
21impl Renderer for CairoRenderer {
22 fn move_to(&mut self, x: f64, y: f64) {
23 self.ctx.move_to(x, y)
24 }
25
26 fn stroke(&mut self) {
27 self.ctx.stroke();
28 }
29
30 fn fill(&mut self) {
31 self.ctx.fill();
32 }
33
34 fn fill_preserve(&mut self) {
35 self.ctx.fill_preserve();
36 }
37
38 fn set_pattern(&mut self, pattern: &Pattern) {
39 match pattern {
40 Pattern::Solid(color) => {
41 let (red, green, blue, alpha) = color.rgba();
42 self.ctx.set_source_rgba(red, green, blue, alpha)
43 }
44 Pattern::None => {}
45 _ => panic!("Unhandled pattern"),
46 }
47 }
48
49 fn set_dash(&mut self, dash: &DefinedDashStyle) {
50 self.ctx.set_dash(&dash.dashes(), dash.offset());
51 }
52
53 fn clear_dash(&mut self) {
54 self.ctx.set_dash(&[], 0.);
55 }
56
57 fn set_line_width(&mut self, width: f64) {
58 self.ctx.set_line_width(width);
59 }
60
61 fn line_to(&mut self, x: f64, y: f64) {
62 self.ctx.line_to(x, y)
63 }
64
65 fn rectangle(&mut self, x: f64, y: f64, width: f64, height: f64) {
66 self.ctx.rectangle(x, y, width, height);
67 }
68
69 fn text_extents(&self, text: &str, font: &FontDescription) -> (f64, f64) {
70 let layout = pangocairo::create_layout(&self.ctx).expect("Couldn't create layout");
71 let font_desc = pango::FontDescription::from_string(&font.family);
72 layout.set_font_description(Some(&font_desc));
73 layout.set_markup(text);
74
75 //let (extents, _) = layout.get_pixel_extents();
76 //(extents.width as f64, extents.height as f64)
77
78 // TODO: get height from the baseline
79 let mut layout_iter = layout.get_iter().unwrap();
80 let _height = loop {
81 if layout_iter.at_last_line() {
82 break layout_iter.get_baseline();
83 }
84
85 layout_iter.next_line();
86 };
87
88 // TODO: Probably should use the logical extents, but it has weird width
89 let (_, extents) = layout.get_pixel_extents();
90 //let (extents, _) = layout.get_pixel_extents();
91 (extents.width as f64, extents.height as f64)
92
93 //let (width, height) = layout.get_pixel_size();
94 //(width as f64, height as f64)
95 }
96
97 fn show_text(&mut self, text: &str, font: &DefinedFontDescription) {
98 let layout = pangocairo::create_layout(&self.ctx).expect("Couldn't create layout");
99 let mut font_desc = pango::FontDescription::from_string(&font.family);
100
101 // TODO: I have no fucking idea why
102 font_desc.set_size((font.size * 600.) as _);
103 //font_desc.set_size((font.size * 700.) as _);
104 //font_desc.set_absolute_size(font.size * 800.);
105 layout.set_font_description(Some(&font_desc));
106 layout.set_markup(text);
107
108 //self.ctx.set_font_size(dbg!(font.size));
109 pangocairo::show_layout(&self.ctx, &layout);
110 }
111}
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
new file mode 100644
index 0000000..c02a484
--- /dev/null
+++ b/cli/Cargo.toml
@@ -0,0 +1,12 @@
1[package]
2name = "diaphragm-cli"
3version = "0.1.0"
4authors = ["Minijackson <minijackson@riseup.net>"]
5edition = "2021"
6
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9[dependencies]
10diaphragm-core = { path = "../core" }
11diaphragm-z3-solver = { path = "../z3-solver" }
12diaphragm-cairo-renderer = { path = "../cairo-renderer" }
diff --git a/cli/src/main.rs b/cli/src/main.rs
new file mode 100644
index 0000000..d2ec038
--- /dev/null
+++ b/cli/src/main.rs
@@ -0,0 +1,188 @@
1use diaphragm_cairo_renderer::CairoRenderer;
2use diaphragm_core::{styles::*, types::*, *};
3use diaphragm_z3_solver::{z3, Z3Context};
4
5// drawing::{cairo::CairoEngine, Engine},
6// z3::{self, ast::Ast},
7
8fn main() {
9 let z3_cfg = z3::Config::new();
10 let z3_ctx = z3::Context::new(&z3_cfg);
11 let ctx = Z3Context::new(&z3_ctx);
12
13 let cairo_renderer = CairoRenderer::new();
14
15 let mut runtime = Runtime::new(Box::new(ctx), Box::new(cairo_renderer));
16
17 let ctx = runtime.solver_ctx();
18
19 let rect1_height = ctx.new_free_float();
20 let rect1_width = ctx.new_free_float();
21
22 let rect1_ctx = ShapeContext {
23 bounds: Bounds {
24 top: ctx.new_fixed_float(10.),
25 left: ctx.new_fixed_float(10.),
26 height: rect1_height,
27 width: rect1_width,
28 },
29 fill: FillStyle::default(),
30 stroke: StrokeStyle::default(),
31 };
32
33 let text_bounds = rect1_ctx.bounds.clone();
34
35 let rect1 = core_shapes::Rectangle {};
36
37 let rect2_top = ctx.new_free_float();
38 let rect2_left = ctx.new_free_float();
39
40 let rect2_ctx = ShapeContext {
41 bounds: Bounds {
42 top: rect2_top,
43 left: rect2_left,
44 height: rect1_width,
45 width: rect1_height,
46 },
47 fill: FillStyle::default(),
48 stroke: StrokeStyle::default(),
49 };
50
51 let rect2 = core_shapes::Rectangle {};
52
53 let _2 = ctx.new_fixed_float(2.);
54 let double_height = ctx.float_mul(&[rect1_height, _2]);
55 let width_constraint = ctx.float_eq(rect1_width, double_height);
56 ctx.constrain(width_constraint);
57
58 let _42 = ctx.new_fixed_float(42.);
59 let width_constraint2 = ctx.float_eq(rect1_width, _42);
60 ctx.constrain(width_constraint2);
61
62 let _10 = ctx.new_fixed_float(10.);
63 let top_constraint = ctx.float_eq(rect2_top, _10);
64 ctx.constrain(top_constraint);
65
66 let bigger_width = ctx.float_add(&[rect1_width, _10]);
67 let left_constraint = ctx.float_eq(rect2_left, bigger_width);
68 ctx.constrain(left_constraint);
69
70 let text = core_shapes::Text {
71 content: String::from("Hello, World!"),
72 font: text::FontDescription {
73 family: String::from("mono"),
74 style: Default::default(),
75 weight: Default::default(),
76 size: rect1_height,
77 },
78 };
79
80 let text_ctx = ShapeContext {
81 bounds: text_bounds,
82 fill: FillStyle::default(),
83 stroke: StrokeStyle::default(),
84 };
85
86 runtime.add_shape(rect1, rect1_ctx);
87 runtime.add_shape(rect2, rect2_ctx);
88 runtime.add_shape(text, text_ctx);
89
90 runtime.render();
91}
92
93/*
94fn main() {
95 // simple_test()
96
97 let z3_cfg = z3::Config::new();
98 let z3_ctx = z3::Context::new(&z3_cfg);
99
100 let mut ctx = Context::new();
101
102 let rect1_height = z3::ast::Real::new_const(&z3_ctx, "rect1_height");
103 let rect1_width = z3::ast::Real::new_const(&z3_ctx, "rect1_width");
104
105 let rect1_bounds = Bounds {
106 top: Float::Defined(10.),
107 left: Float::Defined(10.),
108 height: Float::Constrained(rect1_height.clone()),
109 width: Float::Constrained(rect1_width.clone()),
110 };
111
112 let rect1 = Bounded::<Box<dyn Drawable>> {
113 bounds: rect1_bounds,
114 shape: Box::new(Shape::Rectangle(Rectangle {})),
115 };
116
117 let rect2_top = z3::ast::Real::new_const(&z3_ctx, "rect2_top");
118 let rect2_left = z3::ast::Real::new_const(&z3_ctx, "rect2_left");
119
120 let rect2_bounds = Bounds {
121 top: Float::Constrained(rect2_top.clone()),
122 left: Float::Constrained(rect2_left.clone()),
123 height: Float::Constrained(rect1_width.clone()),
124 width: Float::Constrained(rect1_height.clone()),
125 };
126
127 let rect2 = Bounded::<Box<dyn Drawable>> {
128 bounds: rect2_bounds,
129 shape: Box::new(Shape::Rectangle(Rectangle {})),
130 };
131
132 let solver = z3::Solver::new(&z3_ctx);
133
134 solver.assert(&rect1_width._eq(&(rect1_height * z3::ast::Real::from_real(&z3_ctx, 2, 1))));
135 solver.assert(&rect1_width._eq(&z3::ast::Real::from_real(&z3_ctx, 42, 1)));
136
137 solver.assert(&rect2_top._eq(&z3::ast::Real::from_real(&z3_ctx, 10, 1)));
138 solver.assert(&rect2_left._eq(&(rect1_width + z3::ast::Real::from_real(&z3_ctx, 10, 1))));
139
140 ctx.add_shape(rect1);
141 ctx.add_shape(rect2);
142 ctx.set_constraints(&z3_ctx, &solver);
143
144 solver.check();
145 let model = solver.get_model().expect("Failed to get model");
146
147 let shapes = ctx.draw(&model);
148
149 let mut cairo = CairoEngine::new();
150
151 for shape in shapes {
152 cairo.draw(&shape);
153 }
154}
155
156#[allow(dead_code)]
157fn simple_test() {
158 let mut cairo = CairoEngine::new();
159
160 cairo.draw(&DefinitelyBounded {
161 bounds: DefinedBounds {
162 top: 10.,
163 left: 10.,
164 height: 40.,
165 width: 40.,
166 },
167 shape: Shape::Rectangle(Rectangle {}),
168 });
169
170 cairo.draw(&DefinitelyBounded {
171 bounds: DefinedBounds {
172 top: 20.,
173 left: 20.,
174 height: 40.,
175 width: 40.,
176 },
177 shape: Shape::Text(Text {
178 content: String::from("Hello, World!"),
179 font: FontDescription {
180 family: String::from("Fira Code"),
181 size: 21,
182 style: FontStyle::Normal,
183 weight: FontWeight::Normal,
184 },
185 }),
186 });
187}
188*/
diff --git a/core/Cargo.toml b/core/Cargo.toml
new file mode 100644
index 0000000..37fb207
--- /dev/null
+++ b/core/Cargo.toml
@@ -0,0 +1,10 @@
1[package]
2name = "diaphragm-core"
3version = "0.1.0"
4authors = ["Minijackson <minijackson@riseup.net>"]
5edition = "2021"
6
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9[dependencies]
10palette = "0.5"
diff --git a/core/src/colors.rs b/core/src/colors.rs
new file mode 100644
index 0000000..ba78fa3
--- /dev/null
+++ b/core/src/colors.rs
@@ -0,0 +1,34 @@
1type Srgba = palette::Srgba<f64>;
2
3#[derive(Copy, Clone, PartialEq, Debug, Default)]
4pub struct Color(Srgba);
5
6impl Color {
7 pub fn transparent() -> Self {
8 Color(Srgba::new(0., 0., 0., 0.))
9 }
10
11 pub fn white() -> Self {
12 Color(Srgba::new(1., 1., 1., 1.))
13 }
14
15 pub fn black() -> Self {
16 Color(Srgba::new(0., 0., 0., 1.))
17 }
18
19 pub fn from_rgb(r: f64, g: f64, b: f64) -> Self {
20 Color(Srgba::new(r, g, b, 1.0))
21 }
22
23 pub fn from_rgba(r: f64, g: f64, b: f64, a: f64) -> Self {
24 Color(Srgba::new(r, g, b, a))
25 }
26
27 pub fn rgb(&self) -> (f64, f64, f64) {
28 (self.0.red, self.0.green, self.0.blue)
29 }
30
31 pub fn rgba(&self) -> (f64, f64, f64, f64) {
32 (self.0.red, self.0.green, self.0.blue, self.0.alpha)
33 }
34}
diff --git a/core/src/complex_shapes.rs b/core/src/complex_shapes.rs
new file mode 100644
index 0000000..e23881d
--- /dev/null
+++ b/core/src/complex_shapes.rs
@@ -0,0 +1,285 @@
1use super::core_shapes::CoreShape;
2use super::solving::SolverContext;
3use super::styles::{FillStyle, StrokeStyle};
4use super::types::{Bounds, ShapeContext, ShapeContextBuilder};
5
6pub trait ComplexShape: DynClone {
7 fn as_core_shape(&self) -> Option<&dyn CoreShape> {
8 None
9 }
10
11 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult;
12}
13
14pub trait DynClone {
15 fn dyn_clone(&self) -> Box<dyn ComplexShape>;
16}
17
18impl<T: Clone + ComplexShape + 'static> DynClone for T {
19 fn dyn_clone(&self) -> Box<dyn ComplexShape> {
20 Box::new(self.clone())
21 }
22}
23
24#[derive(Debug, Clone)]
25pub struct Drawable<T: ComplexShape> {
26 pub(crate) context: ShapeContext,
27 pub(crate) shape: T,
28}
29
30impl<T: ComplexShape> Drawable<T> {
31 pub fn new(shape: T, context: ShapeContext) -> Self {
32 Self { context, shape }
33 }
34
35 pub fn from_shape(shape: T, solver: &mut dyn SolverContext) -> Self {
36 Self {
37 context: ShapeContext::builder().build(solver),
38 shape,
39 }
40 }
41
42 pub fn builder(shape: T) -> DrawableBuilder<T>
43 where
44 T: Clone,
45 {
46 DrawableBuilder::new(shape)
47 }
48
49 pub fn shape(&self) -> &T {
50 &self.shape
51 }
52
53 pub fn shape_mut(&mut self) -> &mut T {
54 &mut self.shape
55 }
56
57 pub fn bounds(&self) -> &Bounds {
58 &self.context.bounds
59 }
60
61 pub fn bounds_mut(&mut self) -> &mut Bounds {
62 &mut self.context.bounds
63 }
64
65 pub fn fill_style(&mut self) -> &mut FillStyle {
66 &mut self.context.fill
67 }
68
69 pub fn stroke_style(&mut self) -> &mut StrokeStyle {
70 &mut self.context.stroke
71 }
72}
73
74pub struct DrawableBuilder<T: ComplexShape> {
75 context: ShapeContextBuilder,
76 shape: T,
77}
78
79impl<T: ComplexShape + Clone> DrawableBuilder<T> {
80 pub fn new(shape: T) -> Self {
81 Self {
82 context: ShapeContext::builder(),
83 shape,
84 }
85 }
86
87 pub fn bounds(&mut self, bounds: Bounds) -> &mut Self {
88 self.context.bounds(bounds);
89 self
90 }
91
92 pub fn fill(&mut self, fill: FillStyle) -> &mut Self {
93 self.context.fill(fill);
94 self
95 }
96
97 pub fn stroke(&mut self, stroke: StrokeStyle) -> &mut Self {
98 self.context.stroke(stroke);
99 self
100 }
101
102 pub fn build(&self, solver: &mut dyn SolverContext) -> Drawable<T> {
103 Drawable {
104 shape: self.shape.clone(),
105 context: self.context.build(solver),
106 }
107 }
108}
109
110pub struct DynDrawable {
111 pub(crate) context: ShapeContext,
112 pub(crate) shape: Box<dyn ComplexShape>,
113}
114
115// TODO: copy paste is bad?
116impl DynDrawable {
117 pub fn new<T: ComplexShape + 'static>(shape: T, context: ShapeContext) -> Self {
118 Self {
119 context,
120 shape: Box::new(shape),
121 }
122 }
123
124 pub fn new_dyn(shape: Box<dyn ComplexShape>, context: ShapeContext) -> Self {
125 Self { context, shape }
126 }
127
128 pub fn from_shape<T: ComplexShape + 'static>(shape: T, solver: &mut dyn SolverContext) -> Self {
129 Self {
130 context: ShapeContext::builder().build(solver),
131 shape: Box::new(shape),
132 }
133 }
134
135 pub fn from_dyn(shape: Box<dyn ComplexShape>, solver: &mut dyn SolverContext) -> Self {
136 Self {
137 context: ShapeContext::builder().build(solver),
138 shape,
139 }
140 }
141
142 pub fn shape(&self) -> &dyn ComplexShape {
143 &*self.shape
144 }
145
146 pub fn shape_mut(&mut self) -> &mut dyn ComplexShape {
147 &mut *self.shape
148 }
149
150 pub fn bounds(&self) -> &Bounds {
151 &self.context.bounds
152 }
153
154 pub fn bounds_mut(&mut self) -> &mut Bounds {
155 &mut self.context.bounds
156 }
157
158 pub fn fill_style(&mut self) -> &mut FillStyle {
159 &mut self.context.fill
160 }
161
162 pub fn stroke_mut(&mut self) -> &mut StrokeStyle {
163 &mut self.context.stroke
164 }
165}
166
167impl Clone for DynDrawable {
168 fn clone(&self) -> Self {
169 DynDrawable {
170 context: self.context.clone(),
171 shape: self.shape.dyn_clone(),
172 }
173 }
174}
175
176impl<T: ComplexShape + 'static> From<Drawable<T>> for DynDrawable {
177 fn from(drawable: Drawable<T>) -> Self {
178 DynDrawable {
179 context: drawable.context,
180 shape: Box::new(drawable.shape),
181 }
182 }
183}
184
185pub struct DrawResult {
186 pub(crate) subshapes: Vec<DynDrawable>,
187 pub(crate) waiting_on: Vec<()>,
188}
189
190impl DrawResult {
191 pub fn new() -> Self {
192 Self {
193 subshapes: Vec::new(),
194 waiting_on: Vec::new(),
195 }
196 }
197
198 /*
199 pub fn push_shape<T: ComplexShape + 'static>(&mut self, shape: T, context: ShapeContext) {
200 self.subshapes.push(DynDrawable {
201 context,
202 shape: Box::new(shape),
203 })
204 }
205
206 pub fn push_boxed_shape(&mut self, shape: Box<dyn ComplexShape>, context: ShapeContext) {
207 self.subshapes.push(DynDrawable { context, shape })
208 }
209 */
210
211 pub fn push<T: ComplexShape + 'static>(&mut self, drawable: Drawable<T>) {
212 self.subshapes.push(drawable.into())
213 }
214
215 pub fn push_dyn(&mut self, drawable: DynDrawable) {
216 self.subshapes.push(drawable)
217 }
218}
219
220/*
221pub trait Drawable {
222 fn draw<'z3>(&self, bounds: &Bounds<'z3>, z3_ctx: &z3::Context) -> DrawResult;
223}
224
225/*
226impl Drawable for Box<dyn Drawable> {
227 fn draw<'z3>(&self, bounds: &Bounds<'z3>, z3_ctx: &z3::Context) -> DrawResult {
228 (**self).draw(bounds, z3_ctx)
229 }
230}
231*/
232
233impl Drawable for CoreShape {
234 fn draw<'z3>(
235 &self,
236 bounds: &Bounds<'z3>,
237 ) -> (
238 Vec<Bounded<'z3, CoreShape>>,
239 Vec<Bounded<'z3, Box<dyn Drawable>>>,
240 ) {
241 // TODO: clone, really?
242 (
243 vec![Bounded::<CoreShape> {
244 bounds: bounds.clone(),
245 shape: self.clone(),
246 }],
247 vec![],
248 )
249 }
250
251 fn constraints(&self, _bounds: &Bounds, _z3_ctx: &z3::Context) -> Vec<z3::ast::Bool> {
252 vec![]
253 }
254}
255
256/*
257impl<'a, T: Drawable> Drawable for Vec<Bounded<'a, T>> {
258 fn draw<'z3>(
259 &self,
260 _bounds: &Bounds<'z3>,
261 as_render Vec<Bounded<'z3, CoreShape>>,
262 Vec<Bounded<'z3, Box<dyn Drawable>>>,
263 ) {
264 let mut core_shapes = Vec::new();
265 let mut complex_drawables = Vec::new();
266
267 for drawable in self.iter() {
268 let (mut inner_core_shapes, mut inner_complex_drawables) =
269 drawable.shape.draw(&drawable.bounds);
270
271 core_shapes.append(&mut inner_core_shapes);
272 complex_drawables.append(&mut inner_complex_drawables);
273 }
274
275 (core_shapes, complex_drawables)
276 }
277
278 fn constraints(&self, _bounds: &Bounds, z3_ctx: &z3::Context) -> Vec<z3::ast::Bool> {
279 self.iter()
280 .flat_map(|drawable| drawable.shape.constraints(&drawable.bounds, z3_ctx))
281 .collect()
282 }
283}
284*/
285*/
diff --git a/core/src/core_shapes.rs b/core/src/core_shapes.rs
new file mode 100644
index 0000000..c3d3cae
--- /dev/null
+++ b/core/src/core_shapes.rs
@@ -0,0 +1,86 @@
1use super::complex_shapes::{ComplexShape, DrawResult};
2use super::rendering::{Render, Renderer};
3use super::solving::{Constrainable, SolverContext, SolverModel};
4use super::types::*;
5
6pub trait CoreShape {
7 fn constrain(
8 &self,
9 _context: &ShapeContext,
10 _solver: &mut dyn SolverContext,
11 _renderer: &dyn Renderer,
12 ) {
13 }
14 fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>>;
15}
16
17impl<T: CoreShape + Clone + 'static> ComplexShape for T {
18 fn as_core_shape(&self) -> Option<&dyn CoreShape> {
19 Some(self)
20 }
21
22 fn draw(&self, _context: &ShapeContext, _solver: &mut dyn SolverContext) -> DrawResult {
23 panic!("Tried to decompose core shape")
24 }
25}
26
27// TODO: add default
28#[derive(Copy, Clone, Debug, Default)]
29pub struct Rectangle {}
30
31impl CoreShape for Rectangle {
32 fn to_render(&self, _model: &dyn SolverModel) -> Option<Box<dyn Render>> {
33 Some(Box::new(self.clone()))
34 }
35}
36
37pub use super::text::{DefinedText, Text};
38
39impl CoreShape for Text {
40 fn constrain(
41 &self,
42 context: &ShapeContext,
43 solver: &mut dyn SolverContext,
44 renderer: &dyn Renderer,
45 ) {
46 let height_constraint = solver.float_eq(context.bounds.height, self.font.size);
47 solver.constrain(height_constraint);
48
49 // TODO: handle multiline
50 let (width, height) = renderer.text_extents(&self.content, &self.font);
51 dbg!(height);
52
53 let scale = solver.float_div(self.font.size, Float::Fixed(height));
54
55 let calculated_width = solver.float_mul(&[Float::Fixed(width), scale]);
56 let width_constraint = solver.float_eq(context.bounds.width, calculated_width);
57 solver.constrain(width_constraint);
58 }
59
60 fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> {
61 self.fixate(model)
62 .map(|path| -> Box<dyn Render> { Box::new(path) })
63 }
64}
65
66#[derive(Clone, Debug, Default)]
67pub struct StraightPath {
68 pub(crate) points: Vec<Point2D>,
69}
70
71impl StraightPath {
72 pub fn new(points: Vec<Point2D>) -> Self {
73 Self { points }
74 }
75}
76
77pub struct DefinedStraightPath {
78 pub(crate) points: Vec<DefinedPoint2D>,
79}
80
81impl CoreShape for StraightPath {
82 fn to_render(&self, model: &dyn SolverModel) -> Option<Box<dyn Render>> {
83 self.fixate(model)
84 .map(|path| -> Box<dyn Render> { Box::new(path) })
85 }
86}
diff --git a/core/src/lib.rs b/core/src/lib.rs
new file mode 100644
index 0000000..57e45df
--- /dev/null
+++ b/core/src/lib.rs
@@ -0,0 +1,19 @@
1#![warn(clippy::all)]
2#![deny(unsafe_code)]
3
4pub mod colors;
5mod complex_shapes;
6pub mod core_shapes;
7mod rendering;
8mod runtime;
9pub mod solving;
10pub mod styles;
11pub mod text;
12pub mod types;
13
14pub use complex_shapes::{
15 ComplexShape, DrawResult, Drawable, DrawableBuilder, DynClone, DynDrawable,
16};
17pub use rendering::Renderer;
18pub use runtime::Runtime;
19pub use solving::{SolverContext, SolverModel};
diff --git a/core/src/mod.rs b/core/src/mod.rs
new file mode 100644
index 0000000..40fe74f
--- /dev/null
+++ b/core/src/mod.rs
@@ -0,0 +1,90 @@
1pub mod constraints;
2pub mod drawable;
3pub mod shapes;
4pub mod text;
5pub mod types;
6
7pub use self::drawable::Drawable;
8pub use self::shapes::Shape as CoreShape;
9pub use self::types::{Bounded, Bounds, DefinitelyBounded};
10
11use self::constraints::Constrainable;
12
13const RECURSION_LIMIT: u64 = 10_000;
14
15pub struct Context<'z3> {
16 drawables: Vec<Bounded<'z3, Box<dyn Drawable>>>,
17}
18
19impl<'z3> Context<'z3> {
20 pub fn new() -> Self {
21 Self { drawables: vec![] }
22 }
23
24 pub fn add_shape(&mut self, shape: Bounded<'z3, Box<dyn Drawable>>) {
25 self.drawables.push(shape);
26 }
27
28 pub fn set_constraints(&self, z3_ctx: &z3::Context, solver: &z3::Solver) {
29 for drawable in &self.drawables {
30 for constraint in drawable.shape.constraints(&drawable.bounds, &z3_ctx) {
31 solver.assert(&constraint);
32 }
33 }
34 }
35
36 // TODO: simplify until not possible?
37
38 pub fn draw(&self, model: &z3::Model) -> Vec<DefinitelyBounded<CoreShape>> {
39 let mut acc_core_drawables = Vec::new();
40 let mut acc_complex_drawables = Vec::new();
41
42 for drawable in &self.drawables {
43 let bounds = &drawable.bounds;
44 let shape = &drawable.shape;
45
46 let (core_drawables, mut complex_drawables) = shape.draw(bounds);
47
48 acc_core_drawables.extend(core_drawables.iter().map(|Bounded { bounds, shape }| {
49 DefinitelyBounded {
50 bounds: bounds.fixate(model),
51 shape: shape.clone(),
52 }
53 }));
54
55 acc_complex_drawables.append(&mut complex_drawables);
56 }
57
58 let mut recursion_count = 0;
59
60 while !acc_complex_drawables.is_empty() {
61 recursion_count += 1;
62
63 let mut tmp_complex_drawables = Vec::new();
64
65 for drawable in acc_complex_drawables.drain(..) {
66 let bounds = drawable.bounds;
67 let shape = drawable.shape;
68
69 let (core_drawables, mut complex_drawables) = shape.draw(&bounds);
70
71 acc_core_drawables.extend(core_drawables.into_iter().map(
72 |Bounded { bounds, shape }| DefinitelyBounded {
73 bounds: bounds.fixate(model),
74 shape,
75 },
76 ));
77
78 tmp_complex_drawables.append(&mut complex_drawables);
79 }
80
81 acc_complex_drawables = tmp_complex_drawables;
82
83 if recursion_count > RECURSION_LIMIT {
84 panic!("Recursion limit reached");
85 }
86 }
87
88 acc_core_drawables
89 }
90}
diff --git a/core/src/rendering.rs b/core/src/rendering.rs
new file mode 100644
index 0000000..f7a0189
--- /dev/null
+++ b/core/src/rendering.rs
@@ -0,0 +1,86 @@
1use super::core_shapes::*;
2use super::styles::{DefinedDashStyle, DefinedStrokeStyle, FillStyle, Pattern};
3use super::text::{DefinedFontDescription, FontDescription};
4use super::types::DefinedShapeContext;
5
6pub trait Renderer {
7 fn move_to(&mut self, x: f64, y: f64);
8 fn stroke(&mut self);
9 fn fill(&mut self);
10 fn fill_preserve(&mut self);
11 fn set_pattern(&mut self, pattern: &Pattern);
12 fn set_dash(&mut self, dash: &DefinedDashStyle);
13 fn clear_dash(&mut self);
14 fn set_line_width(&mut self, width: f64);
15 fn line_to(&mut self, x: f64, y: f64);
16 fn rectangle(&mut self, x: f64, y: f64, width: f64, height: f64);
17 // For a font of size 1.
18 fn text_extents(&self, text: &str, font: &FontDescription) -> (f64, f64);
19 fn show_text(&mut self, text: &str, font: &DefinedFontDescription);
20}
21
22pub trait Render {
23 fn render(&self, context: DefinedShapeContext, renderer: &mut dyn Renderer);
24}
25
26fn draw(fill: &FillStyle, stroke: &DefinedStrokeStyle, renderer: &mut dyn Renderer) {
27 let stroking = !stroke.pattern.is_none();
28
29 if !fill.pattern.is_none() {
30 renderer.set_pattern(&fill.pattern);
31 if stroking {
32 renderer.fill_preserve();
33 } else {
34 renderer.fill();
35 }
36 }
37
38 if !stroke.pattern.is_none() {
39 renderer.set_pattern(&stroke.pattern);
40 renderer.set_line_width(stroke.line_width);
41 if let Some(dash) = &stroke.dash {
42 renderer.set_dash(dash);
43 }
44 renderer.stroke();
45 renderer.clear_dash();
46 }
47}
48
49impl Render for Rectangle {
50 fn render(&self, context: DefinedShapeContext, renderer: &mut dyn Renderer) {
51 let bounds = &context.bounds;
52 renderer.rectangle(bounds.left, bounds.top, bounds.width, bounds.height);
53 draw(&context.fill, &context.stroke, renderer);
54 }
55}
56
57impl Render for DefinedText {
58 fn render(&self, context: DefinedShapeContext, renderer: &mut dyn Renderer) {
59 // TODO: select font, style, text shaping (renderer specific), etc.
60 let bounds = &context.bounds;
61 //renderer.move_to(bounds.left, bounds.top + self.font.size);
62 renderer.move_to(bounds.left, bounds.top);
63 // TODO: ???
64 //draw(&context.fill, &context.stroke, renderer);
65 renderer.show_text(&self.content, &self.font);
66 }
67}
68
69impl Render for DefinedStraightPath {
70 fn render(&self, context: DefinedShapeContext, renderer: &mut dyn Renderer) {
71 let mut iter = self.points.iter();
72
73 let first_point = match iter.next() {
74 Some(point) => point,
75 None => return,
76 };
77
78 renderer.move_to(first_point.x, first_point.y);
79
80 for point in iter {
81 renderer.line_to(point.x, point.y);
82 }
83
84 draw(&context.fill, &context.stroke, renderer);
85 }
86}
diff --git a/core/src/runtime.rs b/core/src/runtime.rs
new file mode 100644
index 0000000..bfb31fa
--- /dev/null
+++ b/core/src/runtime.rs
@@ -0,0 +1,95 @@
1use super::complex_shapes::{ComplexShape, Drawable, DynDrawable};
2use super::rendering::Renderer;
3use super::solving::{Constrainable, SolverContext};
4
5const RECURSION_LIMIT: u64 = 10_000;
6
7pub struct Runtime<'a> {
8 solver_ctx: Box<dyn SolverContext + 'a>,
9 renderer: Box<dyn Renderer>,
10 drawables: Vec<DynDrawable>,
11}
12
13impl<'a> Runtime<'a> {
14 pub fn new(solver_ctx: Box<dyn SolverContext + 'a>, renderer: Box<dyn Renderer>) -> Self {
15 Self {
16 solver_ctx,
17 renderer,
18 drawables: Vec::new(),
19 }
20 }
21
22 pub fn add_drawable<T: ComplexShape + 'static>(&mut self, drawable: Drawable<T>) {
23 self.drawables.push(drawable.into())
24 }
25
26 pub fn solver_ctx(&mut self) -> &mut (dyn SolverContext + 'a) {
27 &mut *self.solver_ctx
28 }
29
30 // TODO: preserve ordering of shapes
31 pub fn render(mut self) {
32 let mut drawables = self.drawables;
33 let mut waited_on_variables = Vec::new();
34 let mut core_shapes = Vec::new();
35
36 /*
37 for drawable in &self.shapes {
38 let bounds = &drawable.bounds;
39 let shape = &drawable.shape;
40
41 if let Some(core_shape) = shape.to_render() {
42 drawables.push((*drawable).clone());
43 continue;
44 }
45
46 let mut result = shape.draw(bounds);
47 drawables.append(&mut result.subshapes);
48 waited_on_variables.append(&mut result.waiting_on);
49 }
50 */
51
52 let mut recursion_count = 0;
53
54 while !drawables.is_empty() {
55 recursion_count += 1;
56
57 if recursion_count > RECURSION_LIMIT {
58 panic!("Recursion limit reached");
59 }
60
61 let mut tmp_drawables = Vec::new();
62
63 for drawable in drawables.drain(..) {
64 let shape_ctx = &drawable.context;
65 let shape = &drawable.shape;
66
67 if let Some(core_shape) = shape.as_core_shape() {
68 core_shape.constrain(shape_ctx, &mut *self.solver_ctx, &*self.renderer);
69 core_shapes.push((shape.dyn_clone(), shape_ctx.clone())); // Better to Arc? Cow?
70 continue;
71 }
72
73 let mut result = shape.draw(shape_ctx, &mut *self.solver_ctx);
74 tmp_drawables.append(&mut result.subshapes);
75 waited_on_variables.append(&mut result.waiting_on);
76 }
77
78 drawables = tmp_drawables;
79 }
80
81 let model = self.solver_ctx.solve();
82
83 // Delay rendering core shapes until later to have all the constraints
84 for (core_shape, shape_ctx) in core_shapes {
85 let core_shape = core_shape.as_core_shape().unwrap();
86
87 match (core_shape.to_render(&*model), shape_ctx.fixate(&*model)) {
88 (Some(defined_shape), Some(shape_ctx)) => {
89 defined_shape.render(shape_ctx, &mut *self.renderer)
90 }
91 _ => panic!("Failed to fixate core shape"),
92 }
93 }
94 }
95}
diff --git a/core/src/solving.rs b/core/src/solving.rs
new file mode 100644
index 0000000..c7e94ba
--- /dev/null
+++ b/core/src/solving.rs
@@ -0,0 +1,279 @@
1use super::core_shapes::*;
2use super::styles::*;
3use super::text::*;
4use super::types::{Bool, Float};
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
7pub struct VariableHandle(usize);
8
9impl VariableHandle {
10 pub fn new(id: usize) -> Self {
11 Self(id)
12 }
13
14 pub fn id(&self) -> usize {
15 self.0
16 }
17}
18
19/*
20pub trait VariableFloat<'a> {
21 fn id(&self) -> usize;
22 fn dyn_clone(&self) -> Box<dyn VariableFloat<'a> + 'a>;
23
24 fn eq(&self, other: &dyn VariableFloat) -> Bool<'a>;
25 fn neq(&self, other: &dyn VariableFloat) -> Bool<'a>;
26 fn gt(&self, other: &dyn VariableFloat) -> Bool<'a>;
27 fn ge(&self, other: &dyn VariableFloat) -> Bool<'a>;
28 fn lt(&self, other: &dyn VariableFloat) -> Bool<'a>;
29 fn le(&self, other: &dyn VariableFloat) -> Bool<'a>;
30
31 fn add(&self, other: &dyn VariableFloat) -> Float<'a>;
32 fn sub(&self, other: &dyn VariableFloat) -> Float<'a>;
33 fn mul(&self, other: &dyn VariableFloat) -> Float<'a>;
34 fn div(&self, other: &dyn VariableFloat) -> Float<'a>;
35
36 fn neg(&self) -> Float<'a>;
37}
38
39pub trait VariableBool<'a> {
40 fn id(&self) -> usize;
41 fn dyn_clone(&self) -> Box<dyn VariableBool<'a> + 'a>;
42
43 fn eq(&self, other: &dyn VariableBool) -> Bool<'a>;
44 fn neq(&self, other: &dyn VariableBool) -> Bool<'a>;
45
46 fn and(&self, other: &dyn VariableBool) -> Bool<'a>;
47 fn or(&self, other: &dyn VariableBool) -> Bool<'a>;
48
49 fn not(&self) -> Bool<'a>;
50}
51*/
52
53pub trait SolverContext {
54 fn solve<'a>(&'a self) -> Box<dyn SolverModel + 'a>;
55 fn constrain(&mut self, assertion: Bool);
56
57 // Floats
58
59 fn new_free_float(&mut self) -> Float;
60 fn new_fixed_float(&mut self, value: f64) -> Float;
61
62 fn float_add(&mut self, values: &[Float]) -> Float;
63 fn float_sub(&mut self, values: &[Float]) -> Float;
64 fn float_mul(&mut self, values: &[Float]) -> Float;
65 fn float_div(&mut self, lhs: Float, rhs: Float) -> Float;
66 fn float_neg(&mut self, value: Float) -> Float;
67
68 fn float_eq(&mut self, lhs: Float, rhs: Float) -> Bool;
69 fn float_ne(&mut self, lhs: Float, rhs: Float) -> Bool;
70 fn float_gt(&mut self, lhs: Float, rhs: Float) -> Bool;
71 fn float_ge(&mut self, lhs: Float, rhs: Float) -> Bool;
72 fn float_lt(&mut self, lhs: Float, rhs: Float) -> Bool;
73 fn float_le(&mut self, lhs: Float, rhs: Float) -> Bool;
74
75 fn float_max(&mut self, values: &[Float]) -> Float {
76 let result = self.new_free_float();
77
78 for (index, &candidate) in values.iter().enumerate() {
79 let comparisons: Vec<_> = values
80 .iter()
81 .enumerate()
82 .filter(|(other_index, _)| *other_index != index)
83 .map(|(_, &other)| self.float_ge(candidate, other))
84 .collect();
85
86 let premise = self.bool_and(&comparisons);
87 let conclusion = self.float_eq(candidate, result);
88 let implication = self.bool_implies(premise, conclusion);
89 self.constrain(implication);
90 }
91
92 result
93 }
94
95 fn float_min(&mut self, values: &[Float]) -> Float {
96 let result = self.new_free_float();
97
98 for (index, &candidate) in values.iter().enumerate() {
99 let comparisons: Vec<_> = values
100 .iter()
101 .enumerate()
102 .filter(|(other_index, _)| *other_index != index)
103 .map(|(_, &other)| self.float_le(candidate, other))
104 .collect();
105
106 let premise = self.bool_and(&comparisons);
107 let conclusion = self.float_eq(candidate, result);
108 let implication = self.bool_implies(premise, conclusion);
109 self.constrain(implication);
110 }
111
112 result
113 }
114
115 // Bools
116
117 fn new_free_bool(&mut self) -> Bool;
118 fn new_fixed_bool(&mut self, value: bool) -> Bool;
119
120 fn bool_eq(&mut self, lhs: Bool, rhs: Bool) -> Bool;
121 fn bool_ne(&mut self, lhs: Bool, rhs: Bool) -> Bool;
122
123 fn bool_and(&mut self, values: &[Bool]) -> Bool;
124 fn bool_or(&mut self, values: &[Bool]) -> Bool;
125 fn bool_not(&mut self, value: Bool) -> Bool;
126
127 fn bool_implies(&mut self, lhs: Bool, rhs: Bool) -> Bool;
128}
129
130pub trait SolverModel {
131 fn eval_float(&self, f: Float) -> Option<f64>;
132 fn eval_bool(&self, b: Bool) -> Option<bool>;
133}
134
135/*
136pub trait Solver {
137 fn constrain(&mut self, assertion: &Bool);
138 fn solve(&self) -> Box<dyn SolverModel>;
139}
140*/
141
142use super::types::*;
143
144pub trait Constrainable {
145 type Fixated;
146
147 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated>;
148}
149
150impl Constrainable for Float {
151 type Fixated = f64;
152
153 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
154 model.eval_float(*self)
155 }
156
157 /*
158 fn fixate(&self, model: &Model) -> Self::Fixated {
159 match self {
160 Float::Defined(float) => *float,
161 Float::Constrained(variable) => {
162 let (num, den) = model
163 .eval::<z3::ast::Real>(variable)
164 .expect("Couldn't eval variable")
165 .as_real()
166 .expect("Couldn't get value from variable");
167
168 num as f64 / den as f64
169 }
170 Float::Undefined => panic!("Undefined float"),
171 }
172 }
173 */
174}
175
176impl Constrainable for Bounds {
177 type Fixated = DefinedBounds;
178
179 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
180 Some(DefinedBounds {
181 top: self.top.fixate(model)?,
182 left: self.left.fixate(model)?,
183 width: self.width.fixate(model)?,
184 height: self.height.fixate(model)?,
185 })
186 }
187}
188
189impl Constrainable for StrokeStyle {
190 type Fixated = DefinedStrokeStyle;
191
192 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
193 let dash = match &self.dash {
194 Some(dash) => Some(dash.fixate(model)?),
195 None => None,
196 };
197
198 Some(DefinedStrokeStyle {
199 pattern: self.pattern.clone(),
200 dash,
201 line_width: self.line_width.fixate(model)?,
202 })
203 }
204}
205
206impl Constrainable for DashStyle {
207 type Fixated = DefinedDashStyle;
208
209 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
210 Some(DefinedDashStyle {
211 dashes: self
212 .dashes
213 .iter()
214 .map(|value| value.fixate(model))
215 .collect::<Option<_>>()?,
216 offset: self.offset.fixate(model)?,
217 })
218 }
219}
220
221impl Constrainable for ShapeContext {
222 type Fixated = DefinedShapeContext;
223
224 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
225 Some(DefinedShapeContext {
226 bounds: self.bounds.fixate(model)?,
227 fill: self.fill.clone(),
228 stroke: self.stroke.fixate(model)?,
229 })
230 }
231}
232
233impl Constrainable for Point2D {
234 type Fixated = DefinedPoint2D;
235
236 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
237 Some(DefinedPoint2D {
238 x: self.x.fixate(model)?,
239 y: self.y.fixate(model)?,
240 })
241 }
242}
243
244impl Constrainable for FontDescription {
245 type Fixated = DefinedFontDescription;
246
247 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
248 Some(DefinedFontDescription {
249 family: self.family.clone(),
250 style: self.style,
251 weight: self.weight,
252 size: self.size.fixate(&*model)?,
253 })
254 }
255}
256
257impl Constrainable for Text {
258 type Fixated = DefinedText;
259
260 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
261 Some(DefinedText {
262 content: self.content.clone(),
263 font: self.font.fixate(&*model)?,
264 })
265 }
266}
267
268impl Constrainable for StraightPath {
269 type Fixated = DefinedStraightPath;
270
271 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
272 let points: Option<_> = self
273 .points
274 .iter()
275 .map(|point| point.fixate(model))
276 .collect();
277 Some(DefinedStraightPath { points: points? })
278 }
279}
diff --git a/core/src/styles.rs b/core/src/styles.rs
new file mode 100644
index 0000000..c061c58
--- /dev/null
+++ b/core/src/styles.rs
@@ -0,0 +1,161 @@
1use super::colors::Color;
2use super::types::Float;
3
4#[derive(Copy, Clone, PartialEq, Debug)]
5#[non_exhaustive]
6pub enum Pattern {
7 Solid(Color),
8 None,
9}
10
11impl Pattern {
12 pub fn is_none(&self) -> bool {
13 match self {
14 Pattern::None => true,
15 _ => false,
16 }
17 }
18}
19
20impl Default for Pattern {
21 fn default() -> Self {
22 Pattern::Solid(Color::default())
23 }
24}
25
26#[derive(Clone, PartialEq, Debug)]
27pub struct FillStyle {
28 pub(crate) pattern: Pattern,
29}
30
31impl FillStyle {
32 pub fn solid(color: Color) -> Self {
33 FillStyle {
34 pattern: Pattern::Solid(color),
35 }
36 }
37}
38
39impl Default for FillStyle {
40 fn default() -> Self {
41 FillStyle {
42 pattern: Pattern::None,
43 }
44 }
45}
46
47// TODO: probably move Float into an enum with Defined(f64) and Variable(handle)
48#[derive(Clone, Debug)]
49pub struct StrokeStyle {
50 pub(crate) pattern: Pattern,
51 pub(crate) dash: Option<DashStyle>,
52 pub(crate) line_width: Float,
53}
54
55impl StrokeStyle {
56 pub fn solid(color: Color) -> Self {
57 StrokeStyle {
58 pattern: Pattern::Solid(color),
59 dash: None,
60 line_width: Float::Fixed(0.),
61 }
62 }
63
64 pub fn builder() -> StrokeStyleBuilder {
65 StrokeStyleBuilder::default()
66 }
67}
68
69impl Default for StrokeStyle {
70 fn default() -> Self {
71 Self::builder().build()
72 }
73}
74
75#[derive(Clone, Default)]
76pub struct StrokeStyleBuilder {
77 pattern: Option<Pattern>,
78 dash: Option<DashStyle>,
79 line_width: Option<Float>,
80}
81
82impl StrokeStyleBuilder {
83 pub fn pattern(&mut self, pattern: Pattern) -> &mut Self {
84 self.pattern = Some(pattern);
85 self
86 }
87
88 pub fn dash(&mut self, dash: DashStyle) -> &mut Self {
89 self.dash = Some(dash);
90 self
91 }
92
93 pub fn line_width(&mut self, width: Float) -> &mut Self {
94 self.line_width = Some(width);
95 self
96 }
97
98 pub fn build(&mut self) -> StrokeStyle {
99 StrokeStyle {
100 pattern: self.pattern.clone().unwrap_or_default(),
101 dash: self.dash.clone(),
102 line_width: self.line_width.unwrap_or(Float::Fixed(2.)),
103 }
104 }
105
106}
107
108
109
110
111#[derive(Clone, Debug, Default)]
112pub struct DashStyle {
113 pub(crate) dashes: Vec<Float>,
114 pub(crate) offset: Float,
115}
116
117impl DashStyle {
118 pub fn new(dashes: Vec<Float>, offset: Float) -> Self {
119 Self { dashes, offset }
120 }
121
122 pub fn dashes(&self) -> &[Float] {
123 &self.dashes
124 }
125
126 pub fn dashes_mut(&mut self) -> &mut Vec<Float> {
127 &mut self.dashes
128 }
129
130 pub fn offset(&self) -> Float {
131 self.offset
132 }
133
134 // TODO: does this makes sense?
135 pub fn offset_mut(&mut self) -> &mut Float {
136 &mut self.offset
137 }
138}
139
140#[derive(Clone, PartialEq, Debug, Default)]
141pub struct DefinedStrokeStyle {
142 pub(crate) pattern: Pattern,
143 pub(crate) dash: Option<DefinedDashStyle>,
144 pub(crate) line_width: f64,
145}
146
147#[derive(Clone, PartialEq, Debug, Default)]
148pub struct DefinedDashStyle {
149 pub(crate) dashes: Vec<f64>,
150 pub(crate) offset: f64,
151}
152
153impl DefinedDashStyle {
154 pub fn dashes(&self) -> &[f64] {
155 &self.dashes
156 }
157
158 pub fn offset(&self) -> f64 {
159 self.offset
160 }
161}
diff --git a/core/src/text.rs b/core/src/text.rs
new file mode 100644
index 0000000..3110030
--- /dev/null
+++ b/core/src/text.rs
@@ -0,0 +1,81 @@
1use super::types::Float;
2
3#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
4#[non_exhaustive]
5pub enum FontStyle {
6 Normal,
7 Oblique,
8 Italic,
9}
10
11impl Default for FontStyle {
12 fn default() -> Self {
13 Self::Normal
14 }
15}
16
17#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
18#[non_exhaustive]
19pub enum FontVariant {
20 Normal,
21 SmallCaps,
22}
23
24impl Default for FontVariant {
25 fn default() -> Self {
26 Self::Normal
27 }
28}
29
30#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
31#[non_exhaustive]
32pub enum FontWeight {
33 Thin,
34 Ultralight,
35 Light,
36 Semilight,
37 Book,
38 Normal,
39 Medium,
40 Semibold,
41 Bold,
42 Ultrabold,
43 Heavy,
44 Ultraheavy,
45}
46
47impl Default for FontWeight {
48 fn default() -> Self {
49 Self::Normal
50 }
51}
52
53#[derive(Clone, Debug)]
54pub struct FontDescription {
55 pub family: String,
56 pub style: FontStyle,
57 pub weight: FontWeight,
58 // TODO: handles weirdly with bounds that specifies both top and bottom
59 pub size: Float,
60}
61
62// TODO: automate creation of Defined* structs
63#[derive(Clone, Debug)]
64pub struct DefinedFontDescription {
65 pub family: String,
66 pub style: FontStyle,
67 pub weight: FontWeight,
68 pub size: f64,
69}
70
71#[derive(Clone, Debug)]
72pub struct Text {
73 pub content: String,
74 pub font: FontDescription,
75}
76
77#[derive(Clone, Debug)]
78pub struct DefinedText {
79 pub content: String,
80 pub font: DefinedFontDescription,
81}
diff --git a/core/src/types.rs b/core/src/types.rs
new file mode 100644
index 0000000..1b7623a
--- /dev/null
+++ b/core/src/types.rs
@@ -0,0 +1,316 @@
1use super::solving::{SolverContext, VariableHandle};
2use super::styles::{DefinedStrokeStyle, FillStyle, StrokeStyle};
3
4// TODO: if we're so dependent on lifetimes, it's probably better to remove Box, and use raw
5// references instead
6
7// Not Eq / Ord to prevent cofusion
8#[derive(Copy, Clone, Debug)]
9pub enum Float {
10 Fixed(f64),
11 Variable(VariableHandle),
12}
13
14impl Default for Float {
15 fn default() -> Self {
16 Float::Fixed(0.)
17 }
18}
19
20impl Float {
21 pub fn from_handle(handle: VariableHandle) -> Self {
22 Float::Variable(handle)
23 }
24
25 /*
26 pub fn handle(&self) -> Option<VariableHandle> {
27 match self {
28 Float::Fixed(_) => None,
29 Float::Variable(handle) => Some(handle),
30 }
31 }
32 */
33}
34
35#[derive(Clone, Default)]
36struct FloatBuilder(Option<Float>);
37
38impl FloatBuilder {
39 pub fn set(&mut self, value: Float) {
40 self.0 = Some(value);
41 }
42
43 pub fn build(&self, solver: &mut dyn SolverContext) -> Float {
44 self.0.unwrap_or_else(|| solver.new_free_float())
45 }
46}
47
48// Not Eq / Ord to prevent cofusion
49#[derive(Copy, Clone, Hash, Debug)]
50pub struct Bool(VariableHandle);
51
52impl Bool {
53 pub fn new(handle: VariableHandle) -> Self {
54 Bool(handle)
55 }
56
57 pub fn handle(&self) -> VariableHandle {
58 self.0
59 }
60}
61
62#[derive(Clone, Debug)]
63pub struct Point2D {
64 pub(crate) x: Float,
65 pub(crate) y: Float,
66}
67
68impl Point2D {
69 pub fn new(x: Float, y: Float) -> Self {
70 Point2D { x, y }
71 }
72
73 pub fn x(&self) -> Float {
74 self.x
75 }
76
77 pub fn y(&self) -> Float {
78 self.y
79 }
80}
81
82#[derive(Clone, PartialEq, PartialOrd, Debug)]
83pub struct DefinedPoint2D {
84 pub(crate) x: f64,
85 pub(crate) y: f64,
86}
87
88#[derive(Clone, Debug)]
89pub struct Bounds {
90 // TODO: really pub? That allows modification, when one might expect constraints
91 pub(crate) top: Float,
92 pub(crate) left: Float,
93 pub(crate) width: Float,
94 pub(crate) height: Float,
95}
96
97impl Bounds {
98 pub fn builder() -> BoundsBuilder {
99 BoundsBuilder::default()
100 }
101
102 pub fn top(&self, _ctx: &mut dyn SolverContext) -> Float {
103 self.top
104 }
105
106 pub fn left(&self, _ctx: &mut dyn SolverContext) -> Float {
107 self.left
108 }
109
110 pub fn width(&self, _ctx: &mut dyn SolverContext) -> Float {
111 self.width
112 }
113
114 pub fn height(&self, _ctx: &mut dyn SolverContext) -> Float {
115 self.height
116 }
117
118 pub fn right(&self, solver: &mut dyn SolverContext) -> Float {
119 solver.float_add(&[self.left, self.width])
120 }
121
122 pub fn bottom(&self, solver: &mut dyn SolverContext) -> Float {
123 solver.float_add(&[self.top, self.height])
124 }
125
126 pub fn vert_center(&self, solver: &mut dyn SolverContext) -> Float {
127 let half_height = solver.float_div(self.height, Float::Fixed(2.));
128 solver.float_add(&[self.top, half_height])
129 }
130
131 pub fn horiz_center(&self, solver: &mut dyn SolverContext) -> Float {
132 let half_width = solver.float_div(self.width, Float::Fixed(2.));
133 solver.float_add(&[self.left, half_width])
134 }
135
136 pub fn top_left(&self, _ctx: &mut dyn SolverContext) -> Point2D {
137 Point2D::new(self.left, self.top)
138 }
139
140 pub fn top_right(&self, solver: &mut dyn SolverContext) -> Point2D {
141 Point2D::new(self.right(solver), self.top)
142 }
143
144 pub fn bottom_left(&self, solver: &mut dyn SolverContext) -> Point2D {
145 Point2D::new(self.left, self.bottom(solver))
146 }
147
148 pub fn bottom_right(&self, solver: &mut dyn SolverContext) -> Point2D {
149 Point2D::new(self.right(solver), self.bottom(solver))
150 }
151
152 pub fn center(&self, solver: &mut dyn SolverContext) -> Point2D {
153 Point2D::new(self.horiz_center(solver), self.vert_center(solver))
154 }
155
156 pub fn with_margin(&self, margin: Float, solver: &mut dyn SolverContext) -> Self {
157 let neg_margin = solver.float_neg(margin);
158 Bounds {
159 top: solver.float_add(&[self.top, neg_margin]),
160 left: solver.float_add(&[self.top, neg_margin]),
161 height: solver.float_add(&[self.top, margin]),
162 width: solver.float_add(&[self.top, margin]),
163 }
164 }
165}
166
167#[derive(Clone, Default)]
168pub struct BoundsBuilder {
169 top: FloatBuilder,
170 left: FloatBuilder,
171 width: FloatBuilder,
172 height: FloatBuilder,
173}
174
175impl BoundsBuilder {
176 pub fn top(&mut self, top: Float) -> &mut Self {
177 self.top.set(top);
178 self
179 }
180
181 pub fn left(&mut self, left: Float) -> &mut Self {
182 self.left.set(left);
183 self
184 }
185
186 pub fn width(&mut self, width: Float) -> &mut Self {
187 self.width.set(width);
188 self
189 }
190
191 pub fn height(&mut self, height: Float) -> &mut Self {
192 self.height.set(height);
193 self
194 }
195
196 pub fn build(&self, solver: &mut dyn SolverContext) -> Bounds {
197 let _build_float =
198 |maybe_float: Option<Float>| maybe_float.unwrap_or_else(|| solver.new_free_float());
199
200 Bounds {
201 top: self.top.build(solver),
202 left: self.left.build(solver),
203 width: self.width.build(solver),
204 height: self.height.build(solver),
205 }
206 }
207}
208
209#[derive(Clone, Debug)]
210pub struct Bounded<Shape> {
211 pub bounds: Bounds,
212 pub shape: Shape,
213}
214
215#[derive(Clone, PartialEq, PartialOrd, Debug)]
216pub struct DefinedBounds {
217 pub top: f64,
218 pub left: f64,
219 pub width: f64,
220 pub height: f64,
221}
222
223#[derive(Clone, PartialEq, PartialOrd, Debug)]
224pub struct DefinitelyBounded<Shape> {
225 pub bounds: DefinedBounds,
226 pub shape: Shape,
227}
228
229#[derive(Clone, Debug)]
230pub struct ShapeContext {
231 pub(crate) bounds: Bounds,
232 pub(crate) fill: FillStyle,
233 pub(crate) stroke: StrokeStyle,
234}
235
236impl ShapeContext {
237 pub fn new(solver: &mut dyn SolverContext) -> Self {
238 Self {
239 bounds: Bounds {
240 top: solver.new_free_float(),
241 left: solver.new_free_float(),
242 width: solver.new_free_float(),
243 height: solver.new_free_float(),
244 },
245 fill: FillStyle::default(),
246 stroke: StrokeStyle::default(),
247 }
248 }
249
250 pub(crate) fn builder() -> ShapeContextBuilder {
251 ShapeContextBuilder::default()
252 }
253
254 pub fn bounds(&self) -> &Bounds {
255 &self.bounds
256 }
257
258 pub fn bounds_mut(&mut self) -> &mut Bounds {
259 &mut self.bounds
260 }
261
262 pub fn fill(&self) -> &FillStyle {
263 &self.fill
264 }
265
266 pub fn fill_mut(&mut self) -> &mut FillStyle {
267 &mut self.fill
268 }
269
270 pub fn stroke(&self) -> &StrokeStyle {
271 &self.stroke
272 }
273
274 pub fn stroke_mut(&mut self) -> &mut StrokeStyle {
275 &mut self.stroke
276 }
277}
278
279#[derive(Clone, Default)]
280pub(crate) struct ShapeContextBuilder {
281 bounds: Option<Bounds>,
282 fill: Option<FillStyle>,
283 stroke: Option<StrokeStyle>,
284}
285
286impl ShapeContextBuilder {
287 pub fn bounds(&mut self, bounds: Bounds) -> &mut Self {
288 self.bounds = Some(bounds);
289 self
290 }
291
292 pub fn fill(&mut self, fill: FillStyle) -> &mut Self {
293 self.fill = Some(fill);
294 self
295 }
296
297 pub fn stroke(&mut self, stroke: StrokeStyle) -> &mut Self {
298 self.stroke = Some(stroke);
299 self
300 }
301
302 pub fn build(&self, solver: &mut dyn SolverContext) -> ShapeContext {
303 ShapeContext {
304 bounds: self.bounds.clone().unwrap_or_else(|| Bounds::builder().build(solver)),
305 fill: self.fill.clone().unwrap_or_default(),
306 stroke: self.stroke.clone().unwrap_or_default(),
307 }
308 }
309}
310
311#[derive(Clone, Debug)]
312pub struct DefinedShapeContext {
313 pub bounds: DefinedBounds,
314 pub fill: FillStyle,
315 pub stroke: DefinedStrokeStyle,
316}
diff --git a/examples/lib-dfscq-log/Cargo.toml b/examples/lib-dfscq-log/Cargo.toml
new file mode 100644
index 0000000..8146aa4
--- /dev/null
+++ b/examples/lib-dfscq-log/Cargo.toml
@@ -0,0 +1,15 @@
1[package]
2name = "diaphragm-examples-lib-dfscq-log"
3version = "0.1.0"
4authors = ["Minijackson <minijackson@riseup.net>"]
5edition = "2021"
6
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9[package.metadata.riff]
10runtime-inputs = ["z3", "cairo"]
11
12[dependencies]
13diaphragm-core = { path = "../../core" }
14diaphragm-z3-solver = { path = "../../z3-solver" }
15diaphragm-cairo-renderer = { path = "../../cairo-renderer" }
diff --git a/examples/lib-dfscq-log/dfscq-log.lua b/examples/lib-dfscq-log/dfscq-log.lua
new file mode 100644
index 0000000..c54e4f2
--- /dev/null
+++ b/examples/lib-dfscq-log/dfscq-log.lua
@@ -0,0 +1,124 @@
1local diaphragm = require("diaphragm")
2
3-- TODO: anyone can use metatable?
4
5local Blocks = diaphragm.Drawable:new()
6Blocks.elements = {}
7Blocks.unit_width = diaphragm.float()
8
9function Blocks:draw()
10 local len = #self.elements
11 assert(len >= 1, "Blocks must have at least 1 element")
12
13 local total_grow = 0
14 for el in self.elements do
15 total_grow = el.grow or 1
16 end
17
18 diaphragm.constrain(self.width == self.unit_width * total_grow)
19
20 local param = self.elements[0]
21
22 -- TODO: this would be written with layout.hstack
23
24 local block = diaphragm.shape.Rectangle:new()
25 block.fill(param.color)
26 diaphragm.constrain(block.left() == self.left())
27 diaphragm.constrain(block.top() == self.top())
28 diaphragm.constrain(block.bottom() == self.bottom())
29 diaphragm.constrain(block.width() == (param.grow or 1) * self.unit_width)
30
31 block.draw()
32
33 local previous_right = block.right()
34
35 for i = 2, len do
36 param = self.elements[i]
37
38 block = diaphragm.shape.Rectangle:new()
39 block.fill(param.color)
40
41 diaphragm.constrain(block.left() == previous_right)
42 diaphragm.constrain(block.top() == self.top())
43 diaphragm.constrain(block.bottom() == self.bottom())
44 diaphragm.constrain(block.width() == (param.grow or 1) * self.unit_width)
45
46 block.draw()
47
48 previous_right = block.right()
49 end
50end
51
52-- Library
53----------
54
55local function block(color)
56 local res = diaphragm.shape.Rectangle:new()
57 res.fill(color)
58 return res
59end
60
61local function blocks_by_len(count, color)
62 local res = {}
63 for i = 1, count do
64 res[i] = block(color)
65 end
66
67 -- TODO: rename cons? Misleading
68 diaphragm.cons.same_size(res)
69 return diaphragm.layout.hstack(res)
70end
71
72local function layer(config)
73 local name = config.name or ""
74 local entries = config.entries or {}
75
76 -- TODO: how to do it without box?
77 -- TODO: implement union or combine
78 -- probably combine because
79 -- union could remove some
80 -- strokes
81 return diaphragm.layout.box({})
82end
83
84-- Parameters
85-------------
86
87local blue = diaphragm.color.from_rgb(0.35, 0.35, 1.)
88
89local active_txn_count = 5
90
91-- Log API
92----------
93
94local log_api = layer({
95 name = "LogAPI",
96 entries = {
97 {
98 name = "activeTxn",
99 content = blocks_by_len(active_txn_count, blue),
100 },
101 },
102})
103
104-- Group Commit
105---------------
106
107-- local group_commit = nil
108
109-- Disk Log
110-----------
111
112-- local disk_log = nil
113
114-- Applier
115----------
116
117-- local applier = nil
118
119diaphragm.draw(diaphragm.layout.vstack({
120 log_api,
121 -- group_commit,
122 -- disk_log,
123 -- applier,
124}))
diff --git a/examples/lib-dfscq-log/src/block_list.rs b/examples/lib-dfscq-log/src/block_list.rs
new file mode 100644
index 0000000..be0eee0
--- /dev/null
+++ b/examples/lib-dfscq-log/src/block_list.rs
@@ -0,0 +1,183 @@
1use super::blocks::Blocks;
2use super::bracket::*;
3
4use diaphragm_core::{
5 core_shapes::Text,
6 text::FontDescription,
7 types::{Bounds, Float, ShapeContext},
8 ComplexShape, DrawResult, Drawable, SolverContext,
9};
10
11#[derive(Clone)]
12pub struct BlockList {
13 pub block_list: Vec<Drawable<Blocks>>,
14 pub block_unit_width: Float,
15 pub bracket_width: Float,
16 pub blocks_vert_padding: Float,
17}
18
19impl ComplexShape for BlockList {
20 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
21 let mut result = DrawResult::new();
22
23 let bounds = context.bounds();
24
25 // Left bracket
26 let opening_bracket_left = {
27 let bracket = Drawable::builder(Bracket {
28 r#type: BracketType::Opening,
29 })
30 .bounds(
31 Bounds::builder()
32 .top(bounds.top(solver))
33 .left(bounds.left(solver))
34 .width(self.bracket_width)
35 .height(bounds.height(solver))
36 .build(solver),
37 )
38 .stroke(context.stroke().clone())
39 .build(solver);
40
41 let bracket_left = bracket.bounds().left(solver);
42
43 result.push(bracket);
44
45 bracket_left
46 };
47
48 let bounds_left = bounds.left(solver);
49 let mut x_acc = solver.float_add(&[bounds_left, self.bracket_width]);
50
51 // Block list
52
53 let bounds_top = bounds.top(solver);
54 let bounds_height = bounds.height(solver);
55 let wanted_blocks_top = solver.float_add(&[bounds_top, self.blocks_vert_padding]);
56 let wanted_blocks_height = solver.float_sub(&[
57 bounds_height,
58 self.blocks_vert_padding,
59 self.blocks_vert_padding,
60 ]);
61
62 let mut block_list_iter = self.block_list.iter();
63
64 // First blocks
65 if let Some(first_blocks) = block_list_iter.next() {
66 // TODO: waaay too verbose
67
68 let blocks_top = first_blocks.bounds().top(solver);
69 let blocks_top_constraint = solver.float_eq(blocks_top, wanted_blocks_top);
70 solver.constrain(blocks_top_constraint);
71
72 let blocks_left = first_blocks.bounds().left(solver);
73 let blocks_left_constraint = solver.float_eq(blocks_left, x_acc);
74 solver.constrain(blocks_left_constraint);
75
76 let blocks_height = first_blocks.bounds().height(solver);
77 let blocks_height_constraint = solver.float_eq(blocks_height, wanted_blocks_height);
78 solver.constrain(blocks_height_constraint);
79
80 let block_unit_width_constraint =
81 solver.float_eq(first_blocks.shape().unit_width, self.block_unit_width);
82 solver.constrain(block_unit_width_constraint);
83
84 result.push(first_blocks.clone());
85
86 let blocks_width = first_blocks.bounds().width(solver);
87 x_acc = solver.float_add(&[x_acc, blocks_width]);
88 }
89
90 // Rest of the blocks
91 for blocks in block_list_iter {
92 // Comma
93 let comma = Drawable::builder(Text {
94 content: String::from(", "),
95 font: FontDescription {
96 family: String::from("mono"),
97 style: Default::default(),
98 weight: Default::default(),
99 size: wanted_blocks_height,
100 },
101 })
102 .bounds(
103 Bounds::builder()
104 .top(wanted_blocks_top)
105 .left(x_acc)
106 .build(solver),
107 )
108 .stroke(context.stroke().clone())
109 .build(solver);
110
111 let comma_width = comma.bounds().width(solver);
112
113 x_acc = solver.float_add(&[x_acc, comma_width]);
114
115 result.push(comma);
116
117 // Blocks
118 /*
119 let blocks_context = ShapeContext {
120 bounds: Bounds {
121 top: blocks_top,
122 left: x_acc,
123 height: blocks_height,
124 width: blocks_width,
125 },
126 fill: FillStyle::default(),
127 stroke: StrokeStyle::default(),
128 };
129 */
130
131 let blocks_top = blocks.bounds().top(solver);
132 let blocks_top_constraint = solver.float_eq(blocks_top, wanted_blocks_top);
133 solver.constrain(blocks_top_constraint);
134
135 let blocks_left = blocks.bounds().left(solver);
136 let blocks_left_constraint = solver.float_eq(blocks_left, x_acc);
137 solver.constrain(blocks_left_constraint);
138
139 let blocks_height = blocks.bounds().height(solver);
140 let blocks_height_constraint = solver.float_eq(blocks_height, wanted_blocks_height);
141 solver.constrain(blocks_height_constraint);
142
143 let block_unit_width_constraint =
144 solver.float_eq(blocks.shape().unit_width, self.block_unit_width);
145 solver.constrain(block_unit_width_constraint);
146
147 result.push(blocks.clone());
148
149 let blocks_width = blocks.bounds().width(solver);
150 x_acc = solver.float_add(&[x_acc, blocks_width]);
151 }
152
153 // Right bracket
154 let closing_bracket_right = {
155 let bracket = Drawable::builder(Bracket {
156 r#type: BracketType::Closing,
157 })
158 .bounds(
159 Bounds::builder()
160 .top(bounds.top(solver))
161 .left(x_acc)
162 .width(self.bracket_width)
163 .height(bounds.height(solver))
164 .build(solver),
165 )
166 .stroke(context.stroke().clone())
167 .build(solver);
168
169 let bracket_right = bracket.bounds().right(solver);
170
171 result.push(bracket);
172
173 bracket_right
174 };
175
176 let this_width = solver.float_sub(&[closing_bracket_right, opening_bracket_left]);
177 let bounds_width = bounds.width(solver);
178 let bounds_width_constraint = solver.float_eq(bounds_width, this_width);
179 solver.constrain(bounds_width_constraint);
180
181 result
182 }
183}
diff --git a/examples/lib-dfscq-log/src/blocks.rs b/examples/lib-dfscq-log/src/blocks.rs
new file mode 100644
index 0000000..0576b7d
--- /dev/null
+++ b/examples/lib-dfscq-log/src/blocks.rs
@@ -0,0 +1,72 @@
1use diaphragm_core::{
2 core_shapes::Rectangle,
3 types::{Float, ShapeContext},
4 ComplexShape, DrawResult, Drawable, SolverContext,
5};
6
7#[derive(Debug, Clone)]
8pub struct Block {
9 pub grow: u8,
10}
11
12impl ComplexShape for Block {
13 fn draw(&self, context: &ShapeContext, _solver: &mut dyn SolverContext) -> DrawResult {
14 let mut result = DrawResult::new();
15
16 // Grow is handled at the upper level
17 let block = Drawable::new(Rectangle {}, context.clone());
18
19 result.push(block);
20
21 result
22 }
23}
24
25#[derive(Debug, Clone)]
26pub struct Blocks {
27 pub blocks: Vec<Drawable<Block>>,
28 pub unit_width: Float,
29}
30
31impl ComplexShape for Blocks {
32 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
33 let mut result = DrawResult::new();
34
35 let sum: u8 = self.blocks.iter().map(|block| block.shape().grow).sum();
36
37 let mut rect_left = context.bounds().left(solver);
38 let rect_top = context.bounds().top(solver);
39 let rect_height = context.bounds().height(solver);
40
41 for block in &self.blocks {
42 let block_top = block.bounds().top(solver);
43 let rect_top_constraint = solver.float_eq(block_top, rect_top);
44 solver.constrain(rect_top_constraint);
45
46 let block_left = block.bounds().left(solver);
47 let rect_left_constraint = solver.float_eq(block_left, rect_left);
48 solver.constrain(rect_left_constraint);
49
50 let grow = Float::Fixed(block.shape().grow as f64);
51 let block_width = block.bounds().width(solver);
52 let rect_width = solver.float_mul(&[self.unit_width, grow]);
53 let rect_width_constraint = solver.float_eq(block_width, rect_width);
54 solver.constrain(rect_width_constraint);
55
56 let block_height = block.bounds().height(solver);
57 let rect_height_constraint = solver.float_eq(block_height, rect_height);
58 solver.constrain(rect_height_constraint);
59
60 result.push(block.clone());
61
62 rect_left = solver.float_add(&[rect_left, rect_width]);
63 }
64
65 let this_width = solver.float_mul(&[self.unit_width, Float::Fixed(sum as f64)]);
66 let bounds_width = context.bounds().width(solver);
67 let bounds_width_constraint = solver.float_eq(bounds_width, this_width);
68 solver.constrain(bounds_width_constraint);
69
70 result
71 }
72}
diff --git a/examples/lib-dfscq-log/src/bracket.rs b/examples/lib-dfscq-log/src/bracket.rs
new file mode 100644
index 0000000..02bca8d
--- /dev/null
+++ b/examples/lib-dfscq-log/src/bracket.rs
@@ -0,0 +1,42 @@
1use diaphragm_core::{
2 core_shapes::StraightPath, types::ShapeContext, ComplexShape, DrawResult, Drawable,
3 SolverContext,
4};
5
6#[derive(Copy, Clone)]
7pub enum BracketType {
8 Opening,
9 Closing,
10}
11
12#[derive(Clone)]
13pub struct Bracket {
14 pub r#type: BracketType,
15}
16
17impl ComplexShape for Bracket {
18 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
19 let mut result = DrawResult::new();
20
21 let bounds = context.bounds();
22
23 let path = match self.r#type {
24 BracketType::Opening => StraightPath::new(vec![
25 bounds.top_right(solver),
26 bounds.top_left(solver),
27 bounds.bottom_left(solver),
28 bounds.bottom_right(solver),
29 ]),
30 BracketType::Closing => StraightPath::new(vec![
31 bounds.top_left(solver),
32 bounds.top_right(solver),
33 bounds.bottom_right(solver),
34 bounds.bottom_left(solver),
35 ]),
36 };
37
38 result.push(Drawable::new(path, context.clone()));
39
40 result
41 }
42}
diff --git a/examples/lib-dfscq-log/src/explode.rs b/examples/lib-dfscq-log/src/explode.rs
new file mode 100644
index 0000000..aeb85bd
--- /dev/null
+++ b/examples/lib-dfscq-log/src/explode.rs
@@ -0,0 +1,86 @@
1use diaphragm_core::{
2 core_shapes::StraightPath,
3 types::{Float, Point2D, ShapeContext},
4 ComplexShape, DrawResult, Drawable, SolverContext,
5};
6
7#[derive(Clone)]
8pub struct Explode {
9 pub top_left: Point2D,
10 pub top_right: Point2D,
11 pub bottom_left: Point2D,
12 pub bottom_right: Point2D,
13
14 pub arm_length: Float,
15}
16
17impl ComplexShape for Explode {
18 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
19 let mut result = DrawResult::new();
20
21 let wanted_top = solver.float_min(&[self.top_left.y(), self.top_right.y()]);
22 let wanted_left = solver.float_min(&[self.top_left.x(), self.bottom_left.x()]);
23 let wanted_bottom = solver.float_max(&[self.bottom_left.x(), self.bottom_right.x()]);
24 let wanted_right = solver.float_max(&[self.top_right.y(), self.bottom_right.y()]);
25
26 let bounds_top = context.bounds().top(solver);
27 let bounds_left = context.bounds().left(solver);
28 let bounds_bottom = context.bounds().bottom(solver);
29 let bounds_right = context.bounds().right(solver);
30
31 // TODO: add a facility to help this?
32 let bounds_top_constraint = solver.float_eq(bounds_top, wanted_top);
33 solver.constrain(bounds_top_constraint);
34
35 let bounds_left_constraint = solver.float_eq(bounds_left, wanted_left);
36 solver.constrain(bounds_left_constraint);
37
38 let bounds_bottom_constraint = solver.float_eq(bounds_bottom, wanted_bottom);
39 solver.constrain(bounds_bottom_constraint);
40
41 let bounds_right_constraint = solver.float_eq(bounds_right, wanted_right);
42 solver.constrain(bounds_right_constraint);
43
44 let top_left_arm_bottom = Point2D::new(
45 self.top_left.x(),
46 solver.float_add(&[self.top_left.y(), self.arm_length]),
47 );
48
49 let bottom_left_arm_top = Point2D::new(
50 self.bottom_left.x(),
51 solver.float_sub(&[self.bottom_left.y(), self.arm_length]),
52 );
53
54 result.push(Drawable::new(
55 StraightPath::new(vec![
56 self.top_left.clone(),
57 top_left_arm_bottom,
58 bottom_left_arm_top,
59 self.bottom_left.clone(),
60 ]),
61 context.clone(),
62 ));
63
64 let top_right_arm_bottom = Point2D::new(
65 self.top_right.x(),
66 solver.float_add(&[self.top_right.y(), self.arm_length]),
67 );
68
69 let bottom_right_arm_top = Point2D::new(
70 self.bottom_right.x(),
71 solver.float_sub(&[self.bottom_right.y(), self.arm_length]),
72 );
73
74 result.push(Drawable::new(
75 StraightPath::new(vec![
76 self.top_right.clone(),
77 top_right_arm_bottom,
78 bottom_right_arm_top,
79 self.bottom_right.clone(),
80 ]),
81 context.clone(),
82 ));
83
84 result
85 }
86}
diff --git a/examples/lib-dfscq-log/src/labeled.rs b/examples/lib-dfscq-log/src/labeled.rs
new file mode 100644
index 0000000..20aebcd
--- /dev/null
+++ b/examples/lib-dfscq-log/src/labeled.rs
@@ -0,0 +1,64 @@
1use diaphragm_core::{
2 core_shapes::Text,
3 text::FontDescription,
4 types::{Bounds, Float, ShapeContext},
5 ComplexShape, DrawResult, DynClone, SolverContext,
6};
7
8pub struct Labeled {
9 pub label: String,
10 pub label_font: FontDescription,
11 pub content: Box<dyn ComplexShape>,
12 pub content_left: Float,
13}
14
15impl ComplexShape for Labeled {
16 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
17 let mut result = DrawResult::new();
18
19 // Label
20
21 let label = Text {
22 content: self.label.clone(),
23 font: self.label_font.clone(),
24 };
25
26 let mut label_context = context.clone();
27 // TODO: make the text constrain the width
28 label_context.bounds.width = solver.new_free_float();
29
30 let label_right = solver.float_add(&[context.bounds.left, label_context.bounds.width]);
31 let content_left_constrain = solver.float_eq(label_right, self.content_left);
32 solver.constrain(content_left_constrain);
33
34 result.push_shape(label, label_context);
35
36 // Content
37
38 let content_context = ShapeContext {
39 bounds: Bounds {
40 top: context.bounds.top,
41 left: solver.float_add(&[context.bounds.left, self.content_left]),
42 height: context.bounds.height,
43 width: context.bounds.width,
44 },
45 fill: context.fill.clone(),
46 stroke: context.stroke.clone(),
47 };
48
49 result.push_boxed_shape(self.content.dyn_clone(), content_context);
50
51 result
52 }
53}
54
55impl DynClone for Labeled {
56 fn dyn_clone(&self) -> Box<dyn ComplexShape> {
57 Box::new(Labeled {
58 label: self.label.clone(),
59 label_font: self.label_font.clone(),
60 content: self.content.dyn_clone(),
61 content_left: self.content_left.clone(),
62 })
63 }
64}
diff --git a/examples/lib-dfscq-log/src/labeled_delimiter.rs b/examples/lib-dfscq-log/src/labeled_delimiter.rs
new file mode 100644
index 0000000..5a1c610
--- /dev/null
+++ b/examples/lib-dfscq-log/src/labeled_delimiter.rs
@@ -0,0 +1,121 @@
1use diaphragm_core::{
2 core_shapes::{StraightPath, Text},
3 types::{Bounds, Float, Point2D, ShapeContext},
4 ComplexShape, DrawResult, Drawable, SolverContext,
5};
6
7#[derive(Debug, Clone)]
8pub struct Delimiter {
9 pub width: Float,
10 pub label: Drawable<Text>,
11}
12
13#[derive(Debug, Clone)]
14pub struct LabeledDelimiter {
15 pub delimiters: Vec<Delimiter>,
16 pub tick_height: Float,
17}
18
19impl ComplexShape for LabeledDelimiter {
20 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
21 let mut result = DrawResult::new();
22
23 let bounds_left = context.bounds().left(solver);
24 let bounds_right = context.bounds().right(solver);
25 let bounds_bottom = context.bounds().bottom(solver);
26 let bounds_width = context.bounds().width(solver);
27
28 let tick_top = context.bounds().top(solver);
29 let tick_bottom = solver.float_add(&[tick_top, self.tick_height]);
30
31 let first_tick = Drawable::builder(StraightPath::new(vec![
32 context.bounds().top_left(solver),
33 Point2D::new(bounds_left, tick_bottom),
34 ]))
35 .bounds(
36 Bounds::builder()
37 .top(tick_top)
38 .left(bounds_left)
39 .height(self.tick_height)
40 .width(Float::Fixed(0.))
41 .build(solver),
42 )
43 .stroke(context.stroke().clone())
44 .build(solver);
45
46 let baseline_y = first_tick.bounds().vert_center(solver);
47
48 result.push(first_tick);
49
50 // TODO: split everything into functions
51
52 let baseline = Drawable::builder(StraightPath::new(vec![
53 Point2D::new(bounds_left, baseline_y),
54 Point2D::new(bounds_right, baseline_y),
55 ]))
56 .bounds(
57 Bounds::builder()
58 .top(baseline_y)
59 .left(bounds_left)
60 .width(bounds_width)
61 .height(Float::Fixed(0.))
62 .build(solver),
63 )
64 .stroke(context.stroke().clone())
65 .build(solver);
66
67 result.push(baseline);
68
69 let mut section_end = bounds_left;
70 let mut all_label_bottoms = vec![];
71
72 for &Delimiter {
73 width: section_width,
74 ref label,
75 } in &self.delimiters
76 {
77 let section_begin = section_end;
78 section_end = solver.float_add(&[section_end, section_width]);
79
80 let section_half_width = solver.float_div(section_width, Float::Fixed(2.));
81 let section_middle = solver.float_add(&[section_begin, section_half_width]);
82
83 let tick = Drawable::builder(StraightPath::new(vec![
84 Point2D::new(section_end, tick_top),
85 Point2D::new(section_end, tick_bottom),
86 ]))
87 .bounds(
88 Bounds::builder()
89 .top(tick_top)
90 .left(section_end)
91 .height(self.tick_height)
92 .width(Float::Fixed(0.))
93 .build(solver),
94 )
95 .stroke(context.stroke().clone())
96 .build(solver);
97
98 result.push(tick);
99
100 let label_top = label.bounds().top(solver);
101 let label_bottom = label.bounds().bottom(solver);
102 let label_horiz_center = label.bounds().horiz_center(solver);
103
104 let label_top_constraint = solver.float_eq(label_top, tick_bottom);
105 solver.constrain(label_top_constraint);
106
107 let label_middle_constraint = solver.float_eq(label_horiz_center, section_middle);
108 solver.constrain(label_middle_constraint);
109
110 result.push(label.clone());
111
112 all_label_bottoms.push(label_bottom);
113 }
114
115 let wanted_bounds_bottom = solver.float_max(&all_label_bottoms);
116 let bounds_bottom_constraint = solver.float_eq(bounds_bottom, wanted_bounds_bottom);
117 solver.constrain(bounds_bottom_constraint);
118
119 result
120 }
121}
diff --git a/examples/lib-dfscq-log/src/layer.rs b/examples/lib-dfscq-log/src/layer.rs
new file mode 100644
index 0000000..45edb56
--- /dev/null
+++ b/examples/lib-dfscq-log/src/layer.rs
@@ -0,0 +1,169 @@
1use diaphragm_core::{
2 core_shapes::Rectangle,
3 core_shapes::Text,
4 text::FontDescription,
5 types::{Bounds, Float, ShapeContext},
6 ComplexShape, DrawResult, Drawable, DynDrawable, SolverContext,
7};
8
9#[derive(Clone)]
10pub struct Entry {
11 // TODO: transform this to just Text
12 pub label: Option<String>,
13 pub label_vert_center_offset: Option<Float>,
14 pub content: DynDrawable,
15}
16
17#[derive(Clone)]
18pub struct Layer {
19 // TODO: transform this to just Text
20 pub name: String,
21 pub name_font: FontDescription,
22 pub label_font: FontDescription,
23 pub padding: Float,
24 pub entries: Vec<Entry>,
25 pub entries_width: Float,
26}
27
28impl ComplexShape for Layer {
29 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
30 let mut result = DrawResult::new();
31
32 let bounds_top = context.bounds().top(solver);
33 let bounds_left = context.bounds().left(solver);
34 let bounds_right = context.bounds().right(solver);
35 let bounds_height = context.bounds().height(solver);
36
37 let inner_top = solver.float_add(&[bounds_top, self.padding]);
38 let inner_right = solver.float_sub(&[bounds_right, self.padding]);
39
40 // Outer box
41
42 result.push(Drawable::new(Rectangle {}, context.clone()));
43
44 // Layer name
45
46 let layer_name = Drawable::builder(Text {
47 content: self.name.clone(),
48 font: self.name_font.clone(),
49 })
50 .bounds(
51 Bounds::builder()
52 .top(inner_top)
53 .left(solver.float_add(&[bounds_left, self.padding]))
54 .build(solver),
55 )
56 .stroke(context.stroke().clone())
57 .fill(context.fill().clone())
58 .build(solver);
59
60 let layer_name_bottom = layer_name.bounds().bottom(solver);
61
62 /*
63 let mut rect_context = layer_name_context.clone();
64 rect_context.stroke = StrokeStyle::solid(Color::from_rgb(1., 0., 0.));
65 result.push_shape(Rectangle {}, rect_context);
66 */
67
68 result.push(layer_name);
69
70 // Entries
71
72 let mut entry_y_acc = inner_top;
73
74 for entry in &self.entries {
75 // Entry content
76
77 /*
78 let content_context = ShapeContext {
79 bounds: Bounds {
80 top: solver.new_free_float(),
81 left: content_left,
82 width: entry.width,
83 height: entry.height,
84 },
85 fill: Default::default(),
86 stroke: Default::default(),
87 };
88 */
89
90 let content_vert_center = entry.content.bounds().vert_center(solver);
91 let content_top = entry.content.bounds().top(solver);
92 let content_left = entry.content.bounds().left(solver);
93 let content_bottom = entry.content.bounds().bottom(solver);
94
95 // TODO: to replace with label offset
96 let content_half_height = solver.float_sub(&[content_vert_center, content_top]);
97
98 result.push_dyn(entry.content.clone());
99
100 // Entry label
101
102 if let Some(label_content) = entry.label.clone() {
103 let label_top = solver.new_free_float();
104 let label_width = solver.new_free_float();
105 let label_left = solver.float_sub(&[inner_right, self.entries_width, label_width]);
106
107 let label = Drawable::builder(Text {
108 content: label_content,
109 font: self.label_font.clone(),
110 })
111 .bounds(
112 Bounds::builder()
113 .top(label_top)
114 .left(label_left)
115 .width(label_width)
116 .build(solver),
117 )
118 .build(solver);
119
120 /*
121 let mut rect_context = label_context.clone();
122 rect_context.stroke = StrokeStyle::solid(Color::from_rgb(1., 0., 0.));
123 result.push_shape(Rectangle {}, rect_context);
124 */
125
126 // TODO
127 let label_vert_center = label.bounds().vert_center(solver);
128 let label_top = label.bounds().top(solver);
129 let label_right = label.bounds().right(solver);
130
131 let label_vert_center_constraint =
132 solver.float_eq(label_vert_center, content_vert_center);
133 solver.constrain(label_vert_center_constraint);
134
135 let label_half_height = solver.float_sub(&[label_vert_center, label_top]);
136
137 let dumb_label_mid_placement =
138 solver.float_add(&[entry_y_acc, content_half_height]);
139 let safe_label_mid_placement =
140 solver.float_add(&[layer_name_bottom, label_half_height]);
141 let label_mid_placement =
142 solver.float_max(&[safe_label_mid_placement, dumb_label_mid_placement]);
143 let label_mid_placement_constraint =
144 solver.float_eq(label_vert_center, label_mid_placement);
145 solver.constrain(label_mid_placement_constraint);
146
147 let label_right_constraint = solver.float_eq(label_right, content_left);
148 solver.constrain(label_right_constraint);
149
150 result.push(label);
151 } else {
152 let content_top_constraint = solver.float_eq(content_top, entry_y_acc);
153 solver.constrain(content_top_constraint);
154
155 let wanted_content_left = solver.float_sub(&[inner_right, self.entries_width]);
156 let content_left_constraint = solver.float_eq(content_left, wanted_content_left);
157 solver.constrain(content_left_constraint);
158 }
159
160 entry_y_acc = solver.float_add(&[content_bottom, self.padding]);
161 }
162
163 let wanted_bounds_height = solver.float_sub(&[entry_y_acc, bounds_top]);
164 let height_constraint = solver.float_eq(bounds_height, wanted_bounds_height);
165 solver.constrain(height_constraint);
166
167 result
168 }
169}
diff --git a/examples/lib-dfscq-log/src/main.rs b/examples/lib-dfscq-log/src/main.rs
new file mode 100644
index 0000000..fe5db9a
--- /dev/null
+++ b/examples/lib-dfscq-log/src/main.rs
@@ -0,0 +1,642 @@
1mod block_list;
2mod blocks;
3mod bracket;
4mod explode;
5mod labeled_delimiter;
6mod layer;
7mod spacer;
8
9//mod labeled;
10//use labeled::Labeled;
11
12use block_list::BlockList;
13use blocks::*;
14use explode::*;
15use labeled_delimiter::*;
16use layer::*;
17use spacer::*;
18
19use diaphragm_cairo_renderer::CairoRenderer;
20use diaphragm_core::{
21 colors::Color,
22 core_shapes::{Text},
23 styles::*,
24 text::FontDescription,
25 types::*,
26 *,
27};
28use diaphragm_z3_solver::{z3, Z3Context};
29
30fn main() {
31 let z3_cfg = z3::Config::new();
32 let z3_ctx = z3::Context::new(&z3_cfg);
33 let ctx = Z3Context::new(&z3_ctx);
34
35 let cairo_renderer = CairoRenderer::new();
36
37 let mut runtime = Runtime::new(Box::new(ctx), Box::new(cairo_renderer));
38
39 let solver = runtime.solver_ctx();
40
41 let blue = Color::from_rgb(0.35, 0.35, 1.);
42 let light_grey = Color::from_rgb(0.8, 0.8, 0.8);
43 let dark_grey = Color::from_rgb(0.5, 0.5, 0.5);
44
45 // ----------------8<----------------
46
47 /*
48 let mut make_blocks = |grows: &[u8]| {
49 grows
50 .iter()
51 .map(|&grow| {
52 Drawable::builder(Block { grow })
53 .fill(FillStyle::solid(blue))
54 .build(solver)
55 })
56 .collect()
57 };
58
59 let blocks = Drawable::builder(Blocks {
60 blocks: make_blocks(&[1, 2, 1, 1, 4, 1, 1]),
61 unit_width: solver.new_free_float(),
62 })
63 .bounds(
64 Bounds::builder()
65 .top(Float::Fixed(20.))
66 .left(Float::Fixed(20.))
67 .width(Float::Fixed(150.))
68 .height(Float::Fixed(50.))
69 .build(solver),
70 )
71 .build(solver);
72
73 runtime.add_drawable(blocks);
74 */
75
76 // ----------------8<----------------
77
78 /*
79 let block_unit_width = solver.new_fixed_float(10.);
80
81 fn color_block(grow: u8, color: Color, solver: &mut dyn SolverContext) -> Drawable<Block> {
82 Drawable::builder(Block { grow })
83 .fill(FillStyle::solid(color))
84 .build(solver)
85 };
86
87 fn blocks(block_descs: &[(u8, Color)], solver: &mut dyn SolverContext) -> Drawable<Blocks> {
88 let mut blocks = Vec::new();
89
90 for &(grow, color) in block_descs {
91 blocks.push(color_block(grow, color, solver));
92 }
93
94 Drawable::builder(Blocks {
95 blocks,
96 unit_width: solver.new_free_float(),
97 })
98 .build(solver)
99 }
100
101 let block_list = Drawable::builder(BlockList {
102 block_list: vec![
103 blocks(&[(1, light_grey), (1, light_grey), (1, light_grey)], solver),
104 blocks(
105 &[
106 (1, light_grey),
107 (2, blue),
108 (1, light_grey),
109 (1, light_grey),
110 (1, light_grey),
111 ],
112 solver,
113 ),
114 blocks(&[(3, light_grey), (2, blue)], solver),
115 ],
116 block_unit_width,
117 bracket_width: block_unit_width,
118 blocks_vert_padding: block_unit_width,
119 })
120 .bounds(
121 Bounds::builder()
122 .top(Float::Fixed(10.))
123 .left(Float::Fixed(10.))
124 .height(Float::Fixed(40.))
125 .build(solver),
126 )
127 .build(solver);
128
129 runtime.add_drawable(block_list);
130 */
131
132 // ----------------8<----------------
133
134 /*
135 let label_font = FontDescription {
136 family: String::from("mono"),
137 style: Default::default(),
138 weight: Default::default(),
139 size: Float::Fixed(15.),
140 };
141
142 let layer = Drawable::builder(Layer {
143 name: String::from("Hello"),
144 name_font: FontDescription {
145 family: Default::default(),
146 style: Default::default(),
147 weight: Default::default(),
148 size: Float::Fixed(10.),
149 },
150 entries: vec![],
151 padding: Float::Fixed(5.),
152 entries_width: Float::Fixed(50.),
153 label_font,
154 })
155 .bounds(Bounds::builder()
156 .top(Float::Fixed(10.))
157 .left(Float::Fixed(10.))
158 .width(Float::Fixed(100.))
159 .height(Float::Fixed(40.))
160 .build(solver))
161 .build(solver);
162
163 runtime.add_drawable(layer);
164 */
165
166 // ----------------8<----------------
167
168 let title_font = FontDescription {
169 family: String::from("Fanwood"),
170 style: Default::default(),
171 weight: Default::default(),
172 size: Float::Fixed(30.),
173 };
174
175 let label_font = FontDescription {
176 family: String::from("mono"),
177 style: Default::default(),
178 weight: Default::default(),
179 size: Float::Fixed(15.),
180 };
181
182 let layer_padding = Float::Fixed(15.);
183 let layer_margin = Float::Fixed(15.);
184 //let layer_height = Float::Fixed(40.);
185 let layer_left_content_padding = Float::Fixed(240.);
186 //let layer_width = solver.new_free_float();
187 //let layer_width_constraint = solver.float_eq(layer_width, Float::Fixed(100.));
188 //solver.constrain(layer_width_constraint);
189
190 let mut layer_top = Float::Fixed(15.);
191
192 let entries_width = solver.new_free_float();
193 let mut all_entry_content_widths = vec![];
194
195 let layer_width = solver.float_add(&[
196 layer_left_content_padding,
197 entries_width,
198 layer_padding,
199 layer_padding,
200 ]);
201
202 let blocks_vert_padding = Float::Fixed(10.);
203
204 let block_unit_width = Float::Fixed(20.);
205
206 let blocks_height = Float::Fixed(26.);
207 let block_list_height =
208 solver.float_add(&[blocks_height, blocks_vert_padding, blocks_vert_padding]);
209
210 let blue_transaction_len = 5;
211
212 let blocks = |grows: &[u8], color, solver: &mut dyn SolverContext| {
213 let mut blocks = Vec::new();
214
215 for &grow in grows {
216 blocks.push(
217 Drawable::builder(Block { grow })
218 .fill(FillStyle::solid(color))
219 .build(solver),
220 );
221 }
222
223 Drawable::builder(Blocks {
224 blocks,
225 unit_width: block_unit_width,
226 })
227 .bounds(Bounds::builder().height(blocks_height).build(solver))
228 .build(solver)
229 };
230
231 let blocks_by_len =
232 |len, color, solver: &mut dyn SolverContext| blocks(&vec![1; len], color, solver);
233
234 // Log API
235 {
236 let blocks = blocks_by_len(blue_transaction_len, blue, solver);
237 let blocks_width = blocks.bounds().width(solver);
238
239 let layer = Drawable::builder(Layer {
240 name: String::from("LogAPI"),
241 name_font: title_font.clone(),
242 label_font: label_font.clone(),
243 padding: layer_padding,
244 entries: vec![Entry {
245 label: Some(String::from("activeTxn: ")),
246 label_vert_center_offset: None,
247 content: blocks.into(),
248 }],
249 entries_width,
250 })
251 .bounds(
252 Bounds::builder()
253 // TODO: Replace that with a "distributeHorizontally" that applies to all layer
254 .top(layer_top)
255 .left(Float::Fixed(10.))
256 .width(layer_width)
257 .build(solver),
258 )
259 .build(solver);
260
261 all_entry_content_widths.push(blocks_width);
262
263 let layer_height = layer.bounds().height(solver);
264 layer_top = solver.float_add(&[layer_top, layer_height, layer_margin]);
265
266 runtime.add_drawable(layer);
267 }
268
269 let solver = runtime.solver_ctx();
270
271 let other_transactions = [2, 7, 4];
272
273 let group_commit_left;
274 let group_commit_right;
275 let group_commit_bottom;
276
277 // Group Commit
278 {
279 let mut block_list = Vec::new();
280 for &blocks_count in other_transactions.iter() {
281 block_list.push(blocks_by_len(blocks_count, dark_grey, solver));
282 }
283
284 block_list.push(blocks_by_len(blue_transaction_len, blue, solver));
285
286 let block_list = Drawable::builder(BlockList {
287 block_list,
288 block_unit_width,
289 blocks_vert_padding: Float::Fixed(10.),
290 bracket_width: Float::Fixed(10.),
291 })
292 .bounds(Bounds::builder().height(block_list_height).build(solver))
293 .build(solver);
294
295 let content_width = block_list.bounds().width(solver);
296
297 group_commit_left = block_list.bounds().left(solver);
298 group_commit_right = block_list.bounds().right(solver);
299 group_commit_bottom = block_list.bounds().bottom(solver);
300
301 let layer = Drawable::builder(Layer {
302 name: String::from("GroupCommit"),
303 name_font: title_font.clone(),
304 label_font: label_font.clone(),
305 padding: layer_padding,
306 entries: vec![Entry {
307 label: Some(String::from("commitedTxns: ")),
308 label_vert_center_offset: None,
309 content: block_list.into(),
310 }],
311 entries_width,
312 })
313 .bounds(
314 Bounds::builder()
315 .top(layer_top)
316 .left(Float::Fixed(10.))
317 .width(layer_width)
318 .build(solver),
319 )
320 .build(solver);
321
322 all_entry_content_widths.push(content_width);
323
324 let layer_height = layer.bounds().height(solver);
325 layer_top = solver.float_add(&[layer_top, layer_height, layer_margin]);
326
327 runtime.add_drawable(layer);
328 }
329
330 let solver = runtime.solver_ctx();
331
332 let commit_in_log_left;
333 let commit_in_log_right;
334 let commit_in_log_top;
335 let big_block_grow;
336 let small_block_unit_width;
337 let data_in_log_left;
338 let data_in_log_right;
339 let data_in_log_bottom;
340
341 // Disk log
342 {
343 big_block_grow = (blue_transaction_len + other_transactions.iter().sum::<usize>()) as u8;
344
345 let make_block = |grow, color, solver: &mut dyn SolverContext| {
346 Drawable::builder(Block { grow })
347 .bounds(Bounds::builder().height(blocks_height).build(solver))
348 .fill(FillStyle::solid(color))
349 .build(solver)
350 };
351
352 let make_blocks = |block_descs: &[_], solver: &mut dyn SolverContext| {
353 let mut blocks = Vec::new();
354
355 for &(grow, color) in block_descs {
356 blocks.push(make_block(grow, color, solver));
357 }
358
359 blocks
360 };
361
362 let header_block = make_block(big_block_grow, Color::black(), solver);
363 let header_block_width = header_block.bounds().width(solver);
364
365 let mut blocks = vec![header_block];
366
367 blocks.append(&mut make_blocks(
368 &[(big_block_grow, light_grey), (big_block_grow, light_grey)],
369 solver,
370 ));
371
372 let sample_commit_start_id = blocks.len();
373
374 for &txn_block_count in other_transactions.iter() {
375 for _i in 0..txn_block_count {
376 blocks.push(make_block(1, dark_grey, solver));
377 }
378 }
379
380 for _ in 0..blue_transaction_len {
381 blocks.push(make_block(1, blue, solver));
382 }
383
384 let sample_commit_end_id = blocks.len() - 1;
385
386 commit_in_log_left = blocks[sample_commit_start_id].bounds().left(solver);
387 commit_in_log_right = blocks[sample_commit_end_id].bounds().right(solver);
388 commit_in_log_top = blocks[sample_commit_end_id].bounds().top(solver);
389
390 let log_data_blocks_widths: Vec<_> = blocks[1..]
391 .iter()
392 .map(|block| block.bounds().width(solver))
393 .collect();
394 let log_data_blocks_width = solver.float_add(&log_data_blocks_widths);
395
396 let log_space_block = make_block(big_block_grow, Color::white(), solver);
397 let log_space_width = log_space_block.bounds().width(solver);
398 blocks.push(log_space_block);
399
400 // Make it so that it takes as much space as the bigger one
401 small_block_unit_width = solver.new_free_float();
402
403 let disk_log_layout = Drawable::builder(Blocks {
404 blocks,
405 unit_width: small_block_unit_width,
406 })
407 .bounds(Bounds::builder().width(entries_width).build(solver))
408 .build(solver);
409
410 let mut make_delimiter_label = |content| {
411 Drawable::builder(Text {
412 content: String::from(content),
413 font: FontDescription {
414 family: String::from("Fanwood"),
415 size: Float::Fixed(15.),
416 style: Default::default(),
417 weight: Default::default(),
418 },
419 })
420 .build(solver)
421 };
422
423 let delimiters = vec![
424 Delimiter {
425 label: make_delimiter_label("header"),
426 width: header_block_width,
427 },
428 Delimiter {
429 label: make_delimiter_label("data"),
430 width: log_data_blocks_width,
431 },
432 Delimiter {
433 label: make_delimiter_label("available"),
434 width: log_space_width,
435 },
436 ];
437
438 let disk_log_label = Drawable::builder(LabeledDelimiter {
439 delimiters,
440 tick_height: Float::Fixed(10.),
441 })
442 .bounds(Bounds::builder().width(entries_width).build(solver))
443 .build(solver);
444
445 let label_left = disk_log_label.bounds().left(solver);
446 data_in_log_left = solver.float_add(&[label_left, header_block_width]);
447 data_in_log_right = solver.float_add(&[data_in_log_left, log_data_blocks_width]);
448 data_in_log_bottom = disk_log_label.bounds().bottom(solver);
449
450 let layer = Drawable::builder(Layer {
451 name: String::from("DiskLog"),
452 name_font: title_font.clone(),
453 label_font: label_font.clone(),
454 padding: layer_padding,
455 entries: vec![
456 Entry {
457 label: Some(String::from("disk log: ")),
458 label_vert_center_offset: None,
459 content: disk_log_layout.into(),
460 },
461 Entry {
462 label: None,
463 label_vert_center_offset: None,
464 content: disk_log_label.into(),
465 },
466 ],
467 entries_width,
468 })
469 .bounds(
470 Bounds::builder()
471 .top(layer_top)
472 .left(Float::Fixed(10.))
473 .width(layer_width)
474 .build(solver),
475 )
476 .build(solver);
477
478 let layer_height = layer.bounds().height(solver);
479 layer_top = solver.float_add(&[layer_top, layer_height, layer_margin]);
480
481 runtime.add_drawable(layer);
482 }
483
484 let solver = runtime.solver_ctx();
485
486 // Explode GroupLog -> DiskLog
487 {
488 let margin = Float::Fixed(6.);
489 let explode_top = solver.float_add(&[group_commit_bottom, margin]);
490 let explode_bottom = solver.float_sub(&[commit_in_log_top, margin]);
491
492 let explode = Drawable::builder(Explode {
493 top_left: Point2D::new(group_commit_left, explode_top),
494 top_right: Point2D::new(group_commit_right, explode_top),
495 bottom_left: Point2D::new(commit_in_log_left, explode_bottom),
496 bottom_right: Point2D::new(commit_in_log_right, explode_bottom),
497
498 arm_length: Float::Fixed(12.),
499 })
500 .stroke(
501 StrokeStyle::builder()
502 .dash(DashStyle::new(vec![Float::Fixed(2.)], Float::Fixed(0.)))
503 .build(),
504 )
505 .build(solver);
506
507 runtime.add_drawable(explode);
508 }
509
510 let solver = runtime.solver_ctx();
511
512 let data_in_applier_top;
513 let data_in_applier_left;
514 let data_in_applier_right;
515
516 // Applier
517 {
518 // TODO: this is exactly the same as before...
519 let make_block = |grow, color, solver: &mut dyn SolverContext| {
520 Drawable::builder(Block { grow })
521 .bounds(Bounds::builder().height(blocks_height).build(solver))
522 .fill(FillStyle::solid(color))
523 .build(solver)
524 };
525
526 let _make_blocks = |block_descs: &[_], solver: &mut dyn SolverContext| {
527 let mut blocks = Vec::new();
528
529 for &(grow, color) in block_descs {
530 blocks.push(make_block(grow, color, solver));
531 }
532
533 blocks
534 };
535
536 let mut blocks = vec![];
537
538 blocks.push(make_block(big_block_grow, light_grey, solver));
539 for &txn_block_count in other_transactions.iter() {
540 for _i in 0..txn_block_count {
541 blocks.push(make_block(1, dark_grey, solver));
542 }
543 }
544
545 for _ in 0..blue_transaction_len {
546 blocks.push(make_block(1, blue, solver));
547 }
548
549 let blocks = Drawable::builder(Blocks {
550 blocks,
551 unit_width: small_block_unit_width,
552 })
553 .build(solver);
554
555 data_in_applier_top = blocks.bounds().top(solver);
556 data_in_applier_left = blocks.bounds().left(solver);
557 data_in_applier_right = blocks.bounds().right(solver);
558
559 let spaced_data = Spacer::builder(blocks)
560 .horizontal_align_center(solver)
561 .vertical_align_center_with(Float::Fixed(10.))
562 .build(solver);
563
564 let spaced_data = Drawable::builder(spaced_data)
565 .bounds(Bounds::builder().width(entries_width).build(solver))
566 .build(solver);
567
568 let disk_data = Drawable::builder(Block { grow: 1 })
569 .bounds(
570 Bounds::builder()
571 .height(blocks_height)
572 .width(entries_width)
573 .build(solver),
574 )
575 .fill(FillStyle::solid(Color::white()))
576 .build(solver);
577
578 let layer = Drawable::builder(Layer {
579 name: String::from("Applier"),
580 name_font: title_font.clone(),
581 label_font: label_font.clone(),
582 padding: layer_padding,
583 entries: vec![
584 Entry {
585 label: None,
586 label_vert_center_offset: None,
587 content: spaced_data.into(),
588 },
589 Entry {
590 label: Some(String::from("disk data:")),
591 label_vert_center_offset: None,
592 content: disk_data.into(),
593 },
594 ],
595 entries_width,
596 })
597 .bounds(
598 Bounds::builder()
599 .top(layer_top)
600 .left(Float::Fixed(10.))
601 .width(layer_width)
602 .build(solver),
603 )
604 .build(solver);
605
606 runtime.add_drawable(layer);
607 }
608
609 let solver = runtime.solver_ctx();
610
611 // Explode DiskLog -> Applier
612 {
613 let margin = Float::Fixed(6.);
614 let explode_top = solver.float_add(&[data_in_log_bottom, margin]);
615 let explode_bottom = solver.float_sub(&[data_in_applier_top, margin]);
616
617 let explode = Drawable::builder(Explode {
618 top_left: Point2D::new(data_in_log_left, explode_top),
619 top_right: Point2D::new(data_in_log_right, explode_top),
620 bottom_left: Point2D::new(data_in_applier_left, explode_bottom),
621 bottom_right: Point2D::new(data_in_applier_right, explode_bottom),
622
623 arm_length: Float::Fixed(12.),
624 })
625 .stroke(
626 StrokeStyle::builder()
627 .dash(DashStyle::new(vec![Float::Fixed(2.)], Float::Fixed(0.)))
628 .build(),
629 )
630 .build(solver);
631
632 runtime.add_drawable(explode);
633 }
634
635 let solver = runtime.solver_ctx();
636
637 let max_entry_content_width = solver.float_max(&all_entry_content_widths);
638 let entries_width_constraint = solver.float_eq(entries_width, max_entry_content_width);
639 solver.constrain(entries_width_constraint);
640
641 runtime.render();
642}
diff --git a/examples/lib-dfscq-log/src/main2.rs b/examples/lib-dfscq-log/src/main2.rs
new file mode 100644
index 0000000..9db235d
--- /dev/null
+++ b/examples/lib-dfscq-log/src/main2.rs
@@ -0,0 +1,61 @@
1fn main() {
2 let solver = Solver::new();
3 let output = Output::new();
4
5 let blue_transaction_len = 5;
6
7 let blue_block = Block::builder().color(blue);
8 let dark_gray_block = Block::builder().color(dark_gray);
9
10 let log_layer = Layer::builder()
11 .name("LogAPI")
12 .push_entry(
13 Entry::builder()
14 .label("activeTxn: ")
15 .content(
16 Blocks::builder()
17 .push(blue_transaction_len, blue_block.build())
18 .build(),
19 )
20 .build(),
21 )
22 .build();
23
24 let other_transactions = [2, 7, 4];
25
26 let group_commit_layer = Layer::builder()
27 .name("GroupCommit")
28 .push_entry(
29 Entry::builder()
30 .label("commitedTxn: ")
31 .content(
32 BlockList::builder()
33 .append(
34 other_transactions
35 .iter()
36 // TODO: need collect?
37 .map(|len| Blocks::builder().push(len, dark_gray_block.build())),
38 )
39 .push(Blocks::builder().push(blue_transaction_len, blue_block.build()))
40 .build(),
41 )
42 .build(),
43 )
44 .build();
45
46 let disk_log_layer = todo!();
47
48 let applier_layer = todo!();
49
50 let layers = &[
51 &log_layer,
52 &group_commit_layer,
53 &disk_log_layer,
54 &applier_layer,
55 ];
56 constraints::distribute_vertically(solver, layers);
57 constraints::align_left(solver, layers);
58
59 solver.solve();
60 output.write_to_stdout(Output::Format::SVG);
61}
diff --git a/examples/lib-dfscq-log/src/spacer.rs b/examples/lib-dfscq-log/src/spacer.rs
new file mode 100644
index 0000000..6878183
--- /dev/null
+++ b/examples/lib-dfscq-log/src/spacer.rs
@@ -0,0 +1,133 @@
1use diaphragm_core::{
2 types::{Float, ShapeContext},
3 ComplexShape, DrawResult, DynDrawable, SolverContext,
4};
5
6#[derive(Clone)]
7pub struct Spacer {
8 pub margin_left: Float,
9 pub margin_right: Float,
10 pub margin_top: Float,
11 pub margin_bottom: Float,
12 pub content: DynDrawable,
13}
14
15impl Spacer {
16 pub fn builder<T: Into<DynDrawable>>(drawable: T) -> SpacerBuilder {
17 SpacerBuilder::new(drawable)
18 }
19}
20
21impl ComplexShape for Spacer {
22 fn draw(&self, context: &ShapeContext, solver: &mut dyn SolverContext) -> DrawResult {
23 let mut result = DrawResult::new();
24
25 let bounds_left = context.bounds().left(solver);
26 let bounds_right = context.bounds().right(solver);
27 let bounds_top = context.bounds().top(solver);
28 let bounds_bottom = context.bounds().bottom(solver);
29
30 let wanted_content_left = solver.float_add(&[bounds_left, self.margin_left]);
31 let content_left = self.content.bounds().left(solver);
32 let content_left_constraint = solver.float_eq(content_left, wanted_content_left);
33 solver.constrain(content_left_constraint);
34
35 let wanted_content_right = solver.float_sub(&[bounds_right, self.margin_right]);
36 let content_right = self.content.bounds().right(solver);
37 let content_right_constraint = solver.float_eq(content_right, wanted_content_right);
38 solver.constrain(content_right_constraint);
39
40 let wanted_content_top = solver.float_add(&[bounds_top, self.margin_top]);
41 let content_top = self.content.bounds().top(solver);
42 let content_top_constraint = solver.float_eq(content_top, wanted_content_top);
43 solver.constrain(content_top_constraint);
44
45 let wanted_content_bottom = solver.float_sub(&[bounds_bottom, self.margin_bottom]);
46 let content_bottom = self.content.bounds().bottom(solver);
47 let content_bottom_constraint = solver.float_eq(content_bottom, wanted_content_bottom);
48 solver.constrain(content_bottom_constraint);
49
50 result.push_dyn(self.content.clone());
51
52 result
53 }
54}
55
56#[derive(Clone)]
57pub struct SpacerBuilder {
58 pub margin_left: Option<Float>,
59 pub margin_right: Option<Float>,
60 pub margin_top: Option<Float>,
61 pub margin_bottom: Option<Float>,
62 pub content: DynDrawable,
63}
64
65impl SpacerBuilder {
66 pub fn new<T: Into<DynDrawable>>(drawable: T) -> Self {
67 SpacerBuilder {
68 margin_left: None,
69 margin_right: None,
70 margin_top: None,
71 margin_bottom: None,
72 content: drawable.into(),
73 }
74 }
75
76 pub fn margin_left(&mut self, margin_left: Float) -> &mut Self {
77 self.margin_left = Some(margin_left);
78 self
79 }
80
81 pub fn margin_right(&mut self, margin_right: Float) -> &mut Self {
82 self.margin_right = Some(margin_right);
83 self
84 }
85
86 pub fn margin_top(&mut self, margin_top: Float) -> &mut Self {
87 self.margin_top = Some(margin_top);
88 self
89 }
90
91 pub fn margin_bottom(&mut self, margin_bottom: Float) -> &mut Self {
92 self.margin_bottom = Some(margin_bottom);
93 self
94 }
95
96 pub fn vertical_align_center(&mut self, solver: &mut dyn SolverContext) -> &mut Self {
97 let vertical_margin = solver.new_free_float();
98 self.margin_top = Some(vertical_margin);
99 self.margin_bottom = Some(vertical_margin);
100 self
101 }
102
103 pub fn vertical_align_center_with(&mut self, margin: Float) -> &mut Self {
104 self.margin_top = Some(margin);
105 self.margin_bottom = Some(margin);
106 self
107 }
108
109 pub fn horizontal_align_center(&mut self, solver: &mut dyn SolverContext) -> &mut Self {
110 let horizontal_margin = solver.new_free_float();
111 self.margin_left = Some(horizontal_margin);
112 self.margin_right = Some(horizontal_margin);
113 self
114 }
115
116 pub fn horizontal_align_center_with(&mut self, margin: Float) -> &mut Self {
117 self.margin_left = Some(margin);
118 self.margin_right = Some(margin);
119 self
120 }
121
122 pub fn build(&self, solver: &mut dyn SolverContext) -> Spacer {
123 Spacer {
124 margin_left: self.margin_left.unwrap_or_else(|| solver.new_free_float()),
125 margin_right: self.margin_right.unwrap_or_else(|| solver.new_free_float()),
126 margin_top: self.margin_top.unwrap_or_else(|| solver.new_free_float()),
127 margin_bottom: self
128 .margin_bottom
129 .unwrap_or_else(|| solver.new_free_float()),
130 content: self.content.clone(),
131 }
132 }
133}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..bcd2dca
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
1{
2 "nodes": {
3 "nixpkgs": {
4 "locked": {
5 "lastModified": 1670461440,
6 "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=",
7 "owner": "NixOS",
8 "repo": "nixpkgs",
9 "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425",
10 "type": "github"
11 },
12 "original": {
13 "owner": "NixOS",
14 "ref": "nixos-22.11",
15 "repo": "nixpkgs",
16 "type": "github"
17 }
18 },
19 "root": {
20 "inputs": {
21 "nixpkgs": "nixpkgs"
22 }
23 }
24 },
25 "root": "root",
26 "version": 7
27}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..bbe2ab1
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,22 @@
1{
2 inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
3
4 outputs = {
5 self,
6 nixpkgs,
7 }: let
8 pkgs = nixpkgs.legacyPackages.x86_64-linux;
9 in {
10 devShell.x86_64-linux = pkgs.mkShell {
11 buildInputs = with pkgs; [
12 pkgconfig
13 cairo
14 pango
15 z3
16
17 lua5_4
18 stylua
19 ];
20 };
21 };
22}
diff --git a/lua-bindings/Cargo.toml b/lua-bindings/Cargo.toml
new file mode 100644
index 0000000..3859c4e
--- /dev/null
+++ b/lua-bindings/Cargo.toml
@@ -0,0 +1,15 @@
1[package]
2name = "diaphragm-lua-bindings"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7crate-type = ["cdylib"]
8name = "diaphragm"
9
10[dependencies]
11diaphragm-core = { path = "../core" }
12diaphragm-z3-solver = { path = "../z3-solver" }
13diaphragm-cairo-renderer = { path = "../cairo-renderer" }
14
15mlua = { version = "0.8", features = ["lua54", "module"] }
diff --git a/lua-bindings/src/lib.rs b/lua-bindings/src/lib.rs
new file mode 100644
index 0000000..6628ee2
--- /dev/null
+++ b/lua-bindings/src/lib.rs
@@ -0,0 +1,116 @@
1use std::sync::atomic::{AtomicUsize, Ordering};
2
3use diaphragm_core::{
4 solving::VariableHandle,
5 text::{FontDescription as CoreFontDescription, FontStyle, FontWeight, Text as CoreText},
6 types::Float as CoreFloat,
7};
8// use diaphragm_cairo_renderer::CairoRenderer;
9// use diaphragm_core::Runtime;
10// use diaphragm_z3_solver::{z3, Z3Context};
11use mlua::prelude::*;
12
13static MAX_ID: AtomicUsize = AtomicUsize::new(0);
14
15#[derive(Clone, Copy, Debug)]
16struct Float(CoreFloat);
17
18impl Float {
19 fn new() -> Float {
20 Float(CoreFloat::Variable(VariableHandle::new(
21 MAX_ID.fetch_add(1, Ordering::SeqCst),
22 )))
23 }
24}
25impl LuaUserData for Float {}
26
27fn float(_: &Lua, _: ()) -> LuaResult<Float> {
28 Ok(Float::new())
29}
30
31#[derive(Clone, Debug)]
32struct FontDescription(CoreFontDescription);
33impl LuaUserData for FontDescription {}
34
35const DEFAULT_FONT_FAMILY: &str = "serif";
36
37impl Default for FontDescription {
38 fn default() -> Self {
39 Self(CoreFontDescription {
40 family: DEFAULT_FONT_FAMILY.to_string(),
41 style: FontStyle::Normal,
42 weight: FontWeight::Normal,
43 size: Float::new().0,
44 })
45 }
46}
47
48fn font(_: &Lua, params: LuaTable) -> LuaResult<FontDescription> {
49 // TODO: better validation of the table
50 // What happens when I mistype a param?
51 // TODO: better error handling
52
53 let family = params
54 .get::<_, Option<_>>("family")?
55 .unwrap_or_else(|| DEFAULT_FONT_FAMILY.to_string());
56
57 let style = match params.get::<_, Option<String>>("style")?.as_deref() {
58 Some("normal") | None => FontStyle::Normal,
59 Some(_) => return Err(LuaError::RuntimeError("Unknown style".to_string())),
60 };
61
62 let weight = match params.get::<_, Option<String>>("weight")?.as_deref() {
63 Some("normal") | None => FontWeight::Normal,
64 Some(_) => return Err(LuaError::RuntimeError("Unknown weight".to_string())),
65 };
66
67 let size = params
68 .get::<_, Option<_>>("size")?
69 .unwrap_or_else(Float::new);
70
71 Ok(FontDescription(CoreFontDescription {
72 family,
73 style,
74 weight,
75 size: size.0,
76 }))
77}
78
79#[derive(Clone, Debug)]
80struct Text(CoreText);
81impl LuaUserData for Text {}
82
83fn text(_: &Lua, params: LuaTable) -> LuaResult<Text> {
84 let content = params.get("content")?;
85
86 let font = params
87 .get::<_, Option<FontDescription>>("font")?
88 .unwrap_or_default();
89
90 Ok(Text(CoreText {
91 content,
92 font: font.0,
93 }))
94}
95
96fn draw(_: &Lua, params: LuaTable) -> LuaResult<()> {
97 let content: LuaTable = params.get("content")?;
98 let output: LuaTable = params.get("output")?;
99
100 dbg!(content, output);
101
102 Ok(())
103}
104
105#[mlua::lua_module]
106fn libdiaphragm(lua: &Lua) -> LuaResult<LuaTable> {
107 // TODO: the solver as a mutable global solves so much problem (pun not intended)
108 let exports = lua.create_table()?;
109 exports.set("text", lua.create_function(text)?)?;
110 exports.set("font", lua.create_function(font)?)?;
111 exports.set("float", lua.create_function(float)?)?;
112
113 exports.set("draw", lua.create_function(draw)?)?;
114
115 Ok(exports)
116}
diff --git a/result b/result
new file mode 120000
index 0000000..42743c9
--- /dev/null
+++ b/result
@@ -0,0 +1 @@
/nix/store/wzmhg661jib969sj02hbf5991mq4had4-lua-5.4.4 \ No newline at end of file
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..2d25ec7
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,10 @@
1{ pkgs ? import <nixpkgs> {} }:
2
3pkgs.mkShell {
4 buildInputs = with pkgs; [
5 pkgconfig cairo pango z3
6
7 # keep this line if you use bash
8 pkgs.bashInteractive
9 ];
10}
diff --git a/test.svg b/test.svg
new file mode 100644
index 0000000..bfef495
--- /dev/null
+++ b/test.svg
@@ -0,0 +1,377 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920pt" height="1080pt" viewBox="0 0 1920 1080" version="1.1">
3<defs>
4<g>
5<symbol overflow="visible" id="glyph0-0">
6<path style="stroke:none;" d="M 1.171875 0 L 10.546875 0 L 10.546875 -10.78125 L 1.171875 -10.78125 Z M 2.34375 -1.171875 L 2.34375 -9.609375 L 9.375 -9.609375 L 9.375 -1.171875 Z M 2.34375 -1.171875 "/>
7</symbol>
8<symbol overflow="visible" id="glyph0-1">
9<path style="stroke:none;" d="M 0.9375 -0.359375 C 0.9375 0.046875 0.9375 0.078125 1.25 0.078125 C 1.78125 0.078125 3.40625 0 4.109375 0 C 4.8125 0 12.09375 0.078125 12.640625 0.078125 C 12.875 0.078125 13.125 0.03125 13.15625 -0.1875 C 13.25 -0.875 13.640625 -3.140625 13.640625 -3.328125 C 13.640625 -3.46875 13.40625 -3.5625 13.171875 -3.5625 C 13.03125 -3.5625 12.9375 -3.5 12.921875 -3.375 L 12.640625 -1.40625 C 12.5625 -0.890625 12.46875 -0.890625 12.09375 -0.875 C 11.84375 -0.84375 7.625 -0.734375 5.234375 -0.734375 C 5.09375 -0.734375 5.046875 -1.875 5.046875 -3.453125 L 5.046875 -9.9375 C 5.046875 -12.21875 5.0625 -14.984375 5.25 -14.984375 L 6.890625 -14.984375 C 7.265625 -14.984375 7.3125 -15.046875 7.3125 -15.328125 C 7.3125 -15.65625 7.296875 -15.6875 6.921875 -15.6875 C 6.375 -15.6875 4.859375 -15.609375 4.15625 -15.609375 C 3.453125 -15.609375 1.953125 -15.6875 1.578125 -15.6875 C 1.203125 -15.6875 1.109375 -15.65625 1.109375 -15.328125 C 1.109375 -15 1.171875 -14.984375 1.484375 -14.984375 L 2.84375 -14.984375 C 2.984375 -14.984375 3 -14.15625 3 -12.890625 L 3 -7.484375 C 3 -4.015625 2.984375 -0.640625 2.796875 -0.640625 L 1.34375 -0.640625 C 0.96875 -0.640625 0.9375 -0.640625 0.9375 -0.359375 Z M 0.9375 -0.359375 "/>
10</symbol>
11<symbol overflow="visible" id="glyph0-2">
12<path style="stroke:none;" d="M 0.703125 -4.296875 C 0.703125 -1.734375 2.625 0.359375 5.140625 0.359375 C 8.046875 0.359375 9.75 -1.734375 9.75 -4.625 C 9.75 -7.203125 8.0625 -9.28125 5.515625 -9.28125 C 2.625 -9.28125 0.703125 -7.0625 0.703125 -4.296875 Z M 2.375 -3.96875 C 2.375 -6.546875 3.03125 -8.671875 5.234375 -8.671875 C 7.203125 -8.671875 8.046875 -6.609375 8.046875 -4.78125 C 8.046875 -2.671875 7.484375 -0.265625 5.140625 -0.265625 C 3.3125 -0.265625 2.375 -2.203125 2.375 -3.96875 Z M 2.375 -3.96875 "/>
13</symbol>
14<symbol overflow="visible" id="glyph0-3">
15<path style="stroke:none;" d="M 0.359375 4.0625 C 0.359375 5.9375 2.75 6.796875 4.6875 6.796875 C 7.71875 6.796875 9.84375 5.296875 9.84375 2.90625 C 9.84375 -0.125 5.0625 0.1875 2.09375 0 C 2 -0.03125 1.765625 -0.421875 1.765625 -0.703125 C 1.765625 -0.796875 1.78125 -0.890625 1.859375 -0.921875 C 3.421875 -1.359375 4.828125 -1.71875 5.90625 -2.140625 C 7.578125 -2.765625 8.609375 -3.703125 8.609375 -5.703125 C 8.609375 -6.734375 8.296875 -7.25 8.296875 -7.390625 C 8.296875 -7.484375 9.40625 -7.6875 9.6875 -7.71875 C 9.734375 -7.71875 9.75 -7.765625 9.75 -7.859375 C 9.75 -8.140625 9.609375 -8.515625 9.546875 -8.515625 C 8.8125 -8.46875 7.921875 -8.0625 7.78125 -8.0625 C 7.71875 -8.0625 6.734375 -9.265625 4.921875 -9.265625 C 2.84375 -9.265625 0.796875 -7.828125 0.796875 -5.765625 C 0.796875 -3.546875 2.109375 -2.484375 3.78125 -2 C 4.015625 -1.921875 4.21875 -1.90625 4.21875 -1.875 C 4.21875 -1.828125 3.5625 -1.671875 3.328125 -1.59375 C 2.578125 -1.390625 2.140625 -1.265625 1.546875 -1.125 C 1.25 -1.0625 1.125 -0.796875 1.125 -0.375 C 1.125 -0.125 1.15625 0.3125 1.34375 0.75 C 1.484375 1.0625 1.875 1.203125 2.28125 1.203125 L 3.609375 1.203125 C 3.96875 1.203125 4.109375 1.203125 4.109375 1.21875 C 4.109375 1.25 3.796875 1.3125 3.5625 1.359375 C 2.4375 1.59375 0.359375 2.4375 0.359375 4.0625 Z M 1.40625 3.890625 C 1.40625 2.34375 3.3125 1.59375 4.4375 1.59375 C 6.140625 1.59375 8.515625 2.109375 8.515625 3.46875 C 8.515625 5.53125 6.421875 6.1875 4.671875 6.1875 C 3.265625 6.1875 1.40625 5.4375 1.40625 3.890625 Z M 2.296875 -5.859375 C 2.296875 -7.40625 3.46875 -8.671875 4.8125 -8.671875 C 6.234375 -8.671875 7.15625 -7.578125 7.15625 -5.71875 C 7.15625 -3.609375 5.796875 -2.234375 4.859375 -2.234375 C 4.265625 -2.234375 2.296875 -3.5625 2.296875 -5.859375 Z M 2.296875 -5.859375 "/>
16</symbol>
17<symbol overflow="visible" id="glyph0-4">
18<path style="stroke:none;" d="M 0.703125 -0.359375 C 0.703125 0.046875 0.734375 0.078125 1.03125 0.078125 C 1.578125 0.078125 2.046875 0 2.75 0 C 3.453125 0 4.359375 0.078125 4.90625 0.078125 C 5.140625 0.078125 5.15625 0.03125 5.15625 -0.328125 C 5.15625 -0.609375 5.15625 -0.640625 4.90625 -0.640625 L 3.078125 -0.640625 C 3.046875 -0.640625 3.046875 -0.65625 3.046875 -0.703125 C 3.046875 -1.21875 4.34375 -4.484375 4.953125 -6.03125 C 5.0625 -6.328125 5.046875 -6.453125 5.484375 -6.453125 L 10.203125 -6.453125 C 10.546875 -6.453125 10.53125 -6.421875 10.671875 -6 C 11.140625 -4.6875 12.3125 -1.265625 12.3125 -0.703125 C 12.3125 -0.65625 12.3125 -0.640625 12.28125 -0.640625 L 11.015625 -0.640625 C 10.640625 -0.640625 10.59375 -0.640625 10.59375 -0.359375 C 10.59375 0.046875 10.625 0.078125 10.921875 0.078125 C 11.46875 0.078125 12.828125 0 13.53125 0 C 14.234375 0 15.28125 0.078125 15.640625 0.078125 C 15.875 0.078125 15.890625 0.03125 15.890625 -0.328125 C 15.890625 -0.609375 15.890625 -0.640625 15.640625 -0.640625 L 14.890625 -0.640625 C 14.609375 -0.640625 12.96875 -5.375 12 -8.046875 L 9.1875 -15.9375 C 9.171875 -16.03125 9.09375 -16.109375 8.984375 -16.109375 C 8.84375 -16.109375 8.671875 -15.796875 8.53125 -15.46875 C 8.28125 -14.84375 7.875 -14.625 7.6875 -14.15625 L 5.203125 -8.390625 C 4.875 -7.640625 2.046875 -0.640625 1.78125 -0.640625 L 1.125 -0.640625 C 0.75 -0.640625 0.703125 -0.640625 0.703125 -0.359375 Z M 5.421875 -7.15625 C 5.421875 -7.21875 5.46875 -7.34375 5.53125 -7.5 L 7.828125 -13.125 C 7.953125 -13.40625 8.015625 -13.578125 8.0625 -13.578125 C 8.109375 -13.578125 8.15625 -13.4375 8.25 -13.125 L 10.203125 -7.4375 C 10.25 -7.296875 10.296875 -7.203125 10.296875 -7.125 C 10.296875 -7.0625 10.21875 -7.015625 9.984375 -7.015625 L 5.796875 -7.015625 C 5.515625 -7.015625 5.421875 -7.0625 5.421875 -7.15625 Z M 5.421875 -7.15625 "/>
19</symbol>
20<symbol overflow="visible" id="glyph0-5">
21<path style="stroke:none;" d="M 0.9375 -15.21875 C 0.9375 -14.859375 1.125 -14.8125 1.40625 -14.8125 L 2.890625 -14.859375 C 2.984375 -14.859375 3 -13.8125 3 -12.328125 L 3 -11.109375 C 3 -8.046875 2.984375 -0.640625 2.796875 -0.640625 L 1.59375 -0.640625 C 1.21875 -0.640625 1.171875 -0.640625 1.171875 -0.359375 C 1.171875 0.046875 1.203125 0.078125 1.5 0.078125 C 1.71875 0.078125 3.3125 0 4.015625 0 C 4.71875 0 6.171875 0.078125 6.703125 0.078125 C 6.9375 0.078125 6.96875 0.03125 6.96875 -0.328125 C 6.96875 -0.609375 6.96875 -0.640625 6.703125 -0.640625 L 5 -0.640625 C 4.90625 -0.640625 4.875 -3.1875 4.875 -5.0625 L 4.875 -6.609375 C 4.875 -6.75 4.875 -6.875 5.109375 -6.875 C 5.765625 -6.875 6.3125 -6.796875 7.15625 -6.796875 C 10.453125 -6.796875 12.75 -8.046875 12.75 -11.046875 C 12.75 -14.203125 10.3125 -15.640625 7.125 -15.640625 C 6.59375 -15.640625 4.765625 -15.515625 4.0625 -15.515625 C 3.359375 -15.515625 1.78125 -15.5625 1.40625 -15.5625 C 1.109375 -15.5625 0.9375 -15.5625 0.9375 -15.21875 Z M 4.90625 -7.625 L 4.90625 -13.734375 C 4.90625 -14.4375 4.921875 -15 5.015625 -15 C 5.28125 -15.03125 5.53125 -15.03125 5.796875 -15.03125 C 8.578125 -15.03125 10.734375 -13.671875 10.734375 -11.390625 C 10.734375 -8.375 8.46875 -7.3125 5.796875 -7.3125 C 5.421875 -7.3125 4.90625 -7.34375 4.90625 -7.625 Z M 4.90625 -7.625 "/>
22</symbol>
23<symbol overflow="visible" id="glyph0-6">
24<path style="stroke:none;" d="M 0.703125 -0.359375 C 0.703125 0.046875 0.734375 0.078125 1.03125 0.078125 C 1.578125 0.078125 3.328125 0 4.03125 0 C 4.734375 0 6.3125 0.078125 6.84375 0.078125 C 7.078125 0.078125 7.109375 0.03125 7.109375 -0.328125 C 7.109375 -0.609375 7.109375 -0.640625 6.84375 -0.640625 L 5.1875 -0.640625 C 4.96875 -0.640625 4.953125 -4.921875 4.953125 -8.109375 L 4.953125 -11.28125 C 4.953125 -12.59375 4.96875 -14.984375 5.203125 -14.984375 L 6.6875 -14.984375 C 7.0625 -14.984375 7.109375 -14.984375 7.109375 -15.265625 C 7.109375 -15.65625 7.078125 -15.6875 6.78125 -15.6875 C 6.234375 -15.6875 4.78125 -15.609375 4.078125 -15.609375 C 3.375 -15.609375 1.640625 -15.6875 1.265625 -15.6875 C 0.96875 -15.6875 0.796875 -15.6875 0.796875 -15.328125 C 0.796875 -14.984375 0.984375 -14.984375 1.265625 -14.984375 L 2.71875 -14.984375 C 2.890625 -14.984375 2.953125 -13.21875 2.953125 -11.53125 L 2.953125 -9.234375 C 2.953125 -5.984375 2.9375 -0.640625 2.71875 -0.640625 L 1.125 -0.640625 C 0.75 -0.640625 0.703125 -0.640625 0.703125 -0.359375 Z M 0.703125 -0.359375 "/>
25</symbol>
26<symbol overflow="visible" id="glyph0-7">
27<path style="stroke:none;" d="M 1.0625 -7.859375 C 1.0625 -2.0625 4.96875 0.421875 9.28125 0.421875 C 12.46875 0.421875 15.734375 -1.296875 15.734375 -1.71875 C 15.734375 -2.484375 15.75 -3.21875 15.75 -3.796875 C 15.75 -4.625 15.75 -5.15625 16.0625 -5.15625 L 16.78125 -5.15625 C 16.953125 -5.15625 16.96875 -5.34375 16.96875 -5.53125 C 16.96875 -5.71875 16.953125 -5.859375 16.78125 -5.859375 C 15.6875 -5.84375 15.421875 -5.796875 14.671875 -5.796875 C 13.921875 -5.796875 12.734375 -5.84375 11.578125 -5.859375 C 11.421875 -5.859375 11.375 -5.65625 11.375 -5.4375 C 11.375 -5.28125 11.421875 -5.15625 11.5625 -5.15625 L 13.59375 -5.15625 C 13.78125 -5.15625 13.828125 -4.53125 13.828125 -3.796875 C 13.828125 -2.984375 13.8125 -2 13.765625 -1.59375 C 13.734375 -1.34375 12.59375 -0.28125 9.9375 -0.28125 C 6.140625 -0.28125 3.453125 -3.84375 3.453125 -7.8125 C 3.453125 -12.046875 6.078125 -15.234375 9.46875 -15.234375 C 12.65625 -15.234375 14.671875 -13.015625 14.671875 -12.6875 C 14.671875 -12.46875 14.578125 -10.90625 14.578125 -10.8125 C 14.578125 -10.59375 14.609375 -10.53125 15.03125 -10.53125 C 15.328125 -10.53125 15.40625 -10.625 15.40625 -10.90625 C 15.40625 -12.09375 15.46875 -14.8125 15.46875 -15.140625 C 15.46875 -15.421875 15.375 -15.453125 15.03125 -15.453125 C 14.671875 -15.453125 14.671875 -15.40625 14.671875 -15.140625 L 14.671875 -14.5625 C 14.671875 -14.15625 14.484375 -14.328125 14.28125 -14.484375 C 13.8125 -14.8125 12.171875 -15.875 9.5625 -15.875 C 4.828125 -15.875 1.0625 -13.03125 1.0625 -7.859375 Z M 1.0625 -7.859375 "/>
28</symbol>
29<symbol overflow="visible" id="glyph0-8">
30<path style="stroke:none;" d="M 0.59375 -8.28125 C 0.59375 -8.203125 0.59375 -8.1875 0.65625 -8.1875 C 0.75 -8.1875 2.09375 -8.234375 2.15625 -8.234375 C 2.234375 -8.234375 2.328125 -5.859375 2.328125 -3.796875 C 2.328125 -2.109375 2.296875 -0.59375 2.109375 -0.59375 L 1.109375 -0.59375 C 0.875 -0.59375 0.828125 -0.5 0.828125 -0.28125 C 0.828125 -0.03125 0.828125 0.046875 1.125 0.046875 C 1.828125 0.046875 2.5625 0 3.140625 0 C 3.828125 0 5.1875 0.046875 5.625 0.046875 C 5.9375 0.046875 5.9375 -0.078125 5.9375 -0.28125 C 5.9375 -0.5 5.90625 -0.59375 5.625 -0.59375 L 4.15625 -0.59375 C 3.875 -0.59375 3.875 -1.96875 3.875 -3.21875 C 3.875 -5.203125 4.03125 -8 5.203125 -8 C 5.671875 -8 6.078125 -7.265625 6.609375 -7.265625 C 6.984375 -7.265625 7.484375 -7.96875 7.484375 -8.234375 C 7.484375 -8.515625 6.84375 -9.234375 6.140625 -9.234375 C 5.4375 -9.234375 4.5 -8.515625 3.96875 -7.25 C 3.875 -7.03125 3.796875 -6.65625 3.75 -6.65625 C 3.734375 -6.65625 3.734375 -6.78125 3.734375 -7.078125 C 3.734375 -7.53125 3.75 -8.140625 3.75 -8.578125 C 3.75 -8.8125 3.84375 -8.8125 3.46875 -8.8125 C 3.3125 -8.8125 1.34375 -8.765625 1.015625 -8.75 C 0.6875 -8.71875 0.734375 -8.75 0.65625 -8.5625 C 0.609375 -8.4375 0.59375 -8.34375 0.59375 -8.28125 Z M 0.59375 -8.28125 "/>
31</symbol>
32<symbol overflow="visible" id="glyph0-9">
33<path style="stroke:none;" d="M 0.359375 -8.4375 C 0.359375 -8.375 0.375 -8.328125 0.453125 -8.328125 C 0.546875 -8.328125 1.53125 -8.34375 1.59375 -8.34375 C 1.875 -8.34375 1.875 -7.578125 1.875 -6.546875 L 1.875 -2.859375 C 1.875 -1.296875 2.203125 0.265625 4.4375 0.265625 C 6.1875 0.265625 8.140625 -0.84375 8.25 -0.84375 C 8.328125 -0.84375 8.328125 -0.3125 8.34375 0.046875 C 8.375 0.3125 8.46875 0.359375 8.609375 0.359375 C 8.765625 0.359375 10.25 0.125 11.046875 0 C 11.34375 -0.046875 11.375 -0.046875 11.375 -0.375 C 11.375 -0.515625 11.34375 -0.609375 11.25 -0.609375 C 11.203125 -0.609375 10.359375 -0.46875 10.296875 -0.46875 C 9.921875 -0.46875 9.84375 -0.703125 9.84375 -1.859375 C 9.84375 -3.3125 9.875 -8.90625 9.875 -8.90625 C 9.875 -9.03125 9.84375 -9.046875 9.703125 -9.046875 C 9.59375 -9.046875 7.5 -8.953125 7.0625 -8.9375 C 6.75 -8.90625 6.796875 -8.8125 6.75 -8.46875 C 6.75 -8.390625 6.78125 -8.375 6.84375 -8.375 C 6.9375 -8.375 8 -8.421875 8.0625 -8.421875 C 8.203125 -8.421875 8.25 -4.765625 8.25 -4.0625 L 8.25 -1.296875 C 8.25 -1.015625 6.875 -0.921875 6.125 -0.921875 C 4.734375 -0.921875 3.515625 -1.171875 3.515625 -2.484375 L 3.515625 -8.859375 C 3.515625 -8.984375 3.5 -9 3.359375 -9 C 3.234375 -9 1.296875 -8.9375 0.78125 -8.90625 C 0.5 -8.890625 0.5 -8.890625 0.421875 -8.703125 C 0.375 -8.578125 0.359375 -8.515625 0.359375 -8.4375 Z M 0.359375 -8.4375 "/>
34</symbol>
35<symbol overflow="visible" id="glyph0-10">
36<path style="stroke:none;" d="M 0.59375 -8.25 C 0.59375 -8.109375 0.65625 -8.140625 0.890625 -8.140625 C 1.015625 -8.140625 1.921875 -8.1875 2.0625 -8.1875 C 2.390625 -8.1875 2.421875 -8.1875 2.4375 -7.859375 C 2.515625 -6.890625 2.609375 -6.171875 2.609375 -1.125 L 2.609375 2.203125 C 2.609375 4.0625 2.609375 5.953125 2.53125 5.953125 L 1.25 5.953125 C 1.015625 5.953125 0.96875 6.046875 0.96875 6.265625 C 0.96875 6.515625 0.96875 6.59375 1.265625 6.59375 C 1.96875 6.59375 2.953125 6.546875 3.546875 6.546875 C 4.21875 6.546875 5.578125 6.59375 6.03125 6.59375 C 6.328125 6.59375 6.328125 6.46875 6.328125 6.265625 C 6.328125 6.046875 6.3125 5.953125 6.03125 5.953125 L 4.390625 5.953125 C 4.25 5.953125 4.265625 5.28125 4.25 4.390625 L 4.171875 -0.046875 C 4.171875 -0.3125 4.4375 -0.140625 4.734375 -0.046875 C 5.1875 0.09375 5.796875 0.21875 6.28125 0.21875 C 9.359375 0.21875 11.1875 -2.1875 11.1875 -4.546875 C 11.1875 -7.03125 9.875 -8.984375 7.171875 -8.984375 C 6.1875 -8.984375 5.1875 -8.515625 4.640625 -8.109375 C 4.4375 -7.953125 4.265625 -7.78125 4.203125 -7.78125 C 4.15625 -7.78125 4.15625 -7.859375 4.15625 -8.015625 L 4.15625 -8.578125 C 4.15625 -8.90625 4.078125 -8.90625 3.890625 -8.90625 C 3.796875 -8.90625 2.375 -8.8125 0.796875 -8.765625 C 0.734375 -8.765625 0.59375 -8.34375 0.59375 -8.25 Z M 4.171875 -1.21875 L 4.171875 -7.078125 C 4.171875 -7.171875 4.203125 -7.484375 4.953125 -7.859375 C 5.296875 -8.015625 5.796875 -8.15625 6.453125 -8.15625 C 8.1875 -8.15625 9.5 -6.6875 9.5 -4.390625 C 9.5 -2.515625 8.421875 -0.234375 6.21875 -0.234375 C 5.484375 -0.234375 4.171875 -0.65625 4.171875 -1.21875 Z M 4.171875 -1.21875 "/>
37</symbol>
38<symbol overflow="visible" id="glyph0-11">
39<path style="stroke:none;" d="M 1.0625 -7.859375 C 1.0625 -2.203125 4.96875 0.375 9.28125 0.375 C 12.265625 0.375 15.1875 -1.265625 15.234375 -1.6875 C 15.515625 -3.796875 15.609375 -4.578125 15.609375 -4.8125 C 15.609375 -4.96875 15.5625 -5.09375 15.328125 -5.109375 C 14.953125 -5.15625 14.859375 -5.109375 14.8125 -4.78125 L 14.515625 -2.140625 C 14.484375 -1.875 12.59375 -0.546875 9.9375 -0.546875 C 6.328125 -0.546875 3.453125 -3.84375 3.453125 -7.8125 C 3.453125 -12.046875 5.859375 -15.234375 9.265625 -15.234375 C 12.375 -15.234375 14.671875 -12.78125 14.671875 -12.453125 C 14.671875 -12.234375 14.578125 -10.4375 14.578125 -10.34375 C 14.578125 -10.125 14.609375 -10.0625 15.03125 -10.0625 C 15.328125 -10.0625 15.40625 -10.15625 15.40625 -10.4375 C 15.40625 -11.625 15.5 -14.53125 15.5 -14.953125 C 15.5 -15.234375 15.375 -15.265625 15.03125 -15.265625 C 14.671875 -15.265625 14.671875 -15.21875 14.671875 -14.953125 L 14.671875 -14.328125 C 14.671875 -13.921875 14.484375 -14.09375 14.28125 -14.25 C 13.8125 -14.578125 12.1875 -15.9375 9.421875 -15.9375 C 4.6875 -15.9375 1.0625 -12.75 1.0625 -7.859375 Z M 1.0625 -7.859375 "/>
40</symbol>
41<symbol overflow="visible" id="glyph0-12">
42<path style="stroke:none;" d="M 0.59375 -8.203125 C 0.59375 -8.15625 0.609375 -8.140625 0.703125 -8.140625 C 0.828125 -8.140625 2.015625 -8.203125 2.09375 -8.203125 C 2.140625 -8.203125 2.1875 -7.34375 2.1875 -6.375 L 2.1875 -3.828125 C 2.1875 -2.765625 2.1875 -1.8125 2.140625 -1.34375 C 2.09375 -0.890625 2.046875 -0.59375 1.828125 -0.59375 L 0.921875 -0.59375 C 0.6875 -0.59375 0.65625 -0.46875 0.65625 -0.265625 C 0.65625 0 0.75 0.046875 0.9375 0.046875 C 1.3125 0.046875 2.328125 0 2.90625 0 C 3.5 0 4.25 0.046875 4.6875 0.046875 C 5 0.046875 5.015625 -0.078125 5.015625 -0.28125 C 5.015625 -0.5 4.96875 -0.59375 4.6875 -0.59375 L 4.203125 -0.59375 C 3.75 -0.59375 3.75 -0.6875 3.75 -1.59375 L 3.75 -6.9375 C 3.75 -7.078125 3.78125 -7.171875 4.015625 -7.359375 C 4.390625 -7.640625 5.1875 -8.0625 6.359375 -8.0625 C 7.96875 -8.0625 8.046875 -6.65625 8.046875 -5.0625 C 8.046875 -4.90625 8.0625 -3.890625 8.0625 -2.859375 C 8.0625 -1.734375 8.046875 -0.59375 7.90625 -0.59375 L 6.984375 -0.59375 C 6.75 -0.59375 6.703125 -0.5 6.703125 -0.28125 C 6.703125 -0.03125 6.75 0.046875 7.0625 0.046875 C 7.765625 0.046875 8.1875 0 8.765625 0 C 9.453125 0 10.03125 0.046875 10.484375 0.046875 C 10.78125 0.046875 10.8125 -0.078125 10.8125 -0.28125 C 10.8125 -0.5 10.765625 -0.59375 10.484375 -0.59375 L 9.6875 -0.59375 C 9.609375 -0.59375 9.609375 -0.984375 9.609375 -1.546875 L 9.609375 -5.53125 C 9.609375 -6.9375 9.46875 -7.171875 9.46875 -7.359375 C 9.46875 -7.4375 10.546875 -8.0625 11.75 -8.0625 C 13.453125 -8.0625 13.828125 -6.640625 13.828125 -5.0625 C 13.828125 -3.96875 13.828125 -0.59375 13.625 -0.59375 L 12.6875 -0.59375 C 12.453125 -0.59375 12.328125 -0.5 12.328125 -0.28125 C 12.328125 -0.03125 12.328125 0.046875 12.640625 0.046875 C 13.34375 0.046875 14.046875 0 14.625 0 C 15.3125 0 15.96875 0.046875 16.40625 0.046875 C 16.71875 0.046875 16.734375 -0.078125 16.734375 -0.28125 C 16.734375 -0.5 16.6875 -0.59375 16.40625 -0.59375 L 15.65625 -0.59375 C 15.46875 -0.59375 15.421875 -0.65625 15.421875 -0.828125 C 15.421875 -1.953125 15.46875 -3.65625 15.46875 -5.625 C 15.46875 -7.640625 14.84375 -9.046875 12.5625 -9.046875 C 11.671875 -9.046875 10.359375 -8.53125 9.640625 -8.0625 C 9.46875 -7.953125 9.375 -7.90625 9.328125 -7.90625 C 9.265625 -7.90625 9.046875 -9.09375 7.265625 -9.09375 C 5.9375 -9.09375 4.671875 -8.296875 3.96875 -7.8125 C 3.75 -7.640625 3.734375 -7.546875 3.734375 -8.015625 L 3.734375 -8.671875 C 3.734375 -8.90625 3.734375 -8.9375 3.375 -8.9375 C 3.265625 -8.9375 2 -8.859375 1.03125 -8.8125 C 0.703125 -8.796875 0.75 -8.8125 0.6875 -8.625 C 0.640625 -8.484375 0.59375 -8.25 0.59375 -8.203125 Z M 0.59375 -8.203125 "/>
43</symbol>
44<symbol overflow="visible" id="glyph0-13">
45<path style="stroke:none;" d="M 0.59375 -8.375 C 0.59375 -8.296875 0.609375 -8.28125 0.6875 -8.28125 C 0.78125 -8.28125 1.78125 -8.328125 1.859375 -8.328125 C 2.09375 -8.328125 2.140625 -8.296875 2.15625 -7.953125 C 2.234375 -6.234375 2.25 -4.578125 2.25 -2.9375 C 2.25 -2.234375 2.25 -1.546875 2.234375 -0.875 C 2.234375 -0.640625 2.234375 -0.59375 1.96875 -0.59375 L 1.015625 -0.59375 C 0.703125 -0.59375 0.6875 -0.5 0.6875 -0.28125 C 0.6875 -0.03125 0.6875 0.046875 0.9375 0.046875 C 1.390625 0.046875 2.4375 0 3.03125 0 C 3.609375 0 4.546875 0.046875 5 0.046875 C 5.25 0.046875 5.25 -0.078125 5.25 -0.28125 C 5.25 -0.5 5.234375 -0.59375 5 -0.59375 L 4.15625 -0.59375 C 3.921875 -0.59375 3.921875 -0.65625 3.921875 -0.875 C 3.84375 -2.203125 3.84375 -3.515625 3.84375 -4.859375 L 3.84375 -8.84375 C 3.84375 -8.953125 3.828125 -8.984375 3.6875 -8.984375 C 3.5625 -8.984375 1.484375 -8.890625 1.03125 -8.859375 C 0.75 -8.84375 0.78125 -8.859375 0.6875 -8.671875 C 0.59375 -8.484375 0.59375 -8.4375 0.59375 -8.375 Z M 1.8125 -12.96875 C 1.8125 -12.3125 2.28125 -12 2.765625 -12 C 3.421875 -12 4.203125 -12.515625 4.203125 -13.3125 C 4.203125 -14 3.703125 -14.25 3.21875 -14.25 C 2.65625 -14.25 1.8125 -13.8125 1.8125 -12.96875 Z M 1.8125 -12.96875 "/>
46</symbol>
47<symbol overflow="visible" id="glyph0-14">
48<path style="stroke:none;" d="M 0.828125 -8.0625 C 0.828125 -7.96875 0.875 -7.90625 0.96875 -7.90625 L 1.546875 -7.90625 C 1.8125 -7.90625 1.828125 -7.34375 1.828125 -6.46875 C 1.828125 -5.796875 1.8125 -3.09375 1.78125 -1.40625 C 1.78125 -0.703125 2.140625 0.21875 3.46875 0.21875 C 4.4375 0.21875 6.421875 -0.78125 6.421875 -0.890625 C 6.421875 -1.0625 6.40625 -1.265625 6.328125 -1.265625 C 6.140625 -1.265625 5.375 -0.890625 4.453125 -0.890625 C 3.375 -0.890625 3.328125 -1.625 3.328125 -2.34375 L 3.328125 -6.84375 C 3.328125 -7.5 3.328125 -7.921875 3.40625 -7.921875 L 5.71875 -7.921875 C 5.890625 -7.921875 5.953125 -8 6.03125 -8.296875 C 6.125 -8.71875 6.09375 -8.71875 5.8125 -8.71875 L 3.59375 -8.71875 C 3.375 -8.71875 3.328125 -8.75 3.328125 -8.953125 C 3.328125 -9.328125 3.46875 -11.046875 3.46875 -11.109375 C 3.46875 -11.28125 3.359375 -11.34375 3.234375 -11.34375 C 3.140625 -11.34375 3.078125 -11.296875 3.03125 -11.234375 L 0.890625 -8.25 C 0.84375 -8.203125 0.828125 -8.140625 0.828125 -8.0625 Z M 0.828125 -8.0625 "/>
49</symbol>
50<symbol overflow="visible" id="glyph0-15">
51<path style="stroke:none;" d="M 0.828125 -0.234375 C 0.828125 0.046875 0.828125 0.09375 1.078125 0.09375 C 1.34375 0.09375 3.40625 0 4.0625 0 C 5.578125 0 7.109375 0.09375 8.625 0.09375 C 12.828125 0.046875 16.71875 -2.71875 16.71875 -7.859375 C 16.71875 -12.875 12.84375 -15.890625 7.78125 -15.890625 C 6.84375 -15.890625 4.734375 -15.609375 3 -15.609375 C 2.203125 -15.609375 1.484375 -15.640625 1.390625 -15.640625 C 1.078125 -15.640625 1.078125 -15.546875 1.078125 -15.265625 C 1.078125 -14.984375 1.171875 -14.984375 1.390625 -14.984375 L 3.03125 -15.03125 C 3.046875 -15.03125 3.078125 -14.296875 3.078125 -13.203125 C 3.078125 -9.3125 2.90625 -0.59375 2.765625 -0.59375 L 1.21875 -0.59375 C 0.921875 -0.59375 0.828125 -0.59375 0.828125 -0.234375 Z M 5 -2.015625 C 5 -5.28125 5 -8.484375 5.015625 -11.71875 C 5.015625 -12.78125 5.09375 -15.125 5.1875 -15.140625 C 5.71875 -15.28125 6.6875 -15.28125 7.296875 -15.28125 C 11.625 -15.28125 14.34375 -11.484375 14.34375 -8.15625 C 14.34375 -6.125 14.25 -0.515625 6.375 -0.515625 C 5.90625 -0.515625 5.1875 -0.515625 5.046875 -0.609375 C 5 -0.640625 5 -1.265625 5 -2.015625 Z M 5 -2.015625 "/>
52</symbol>
53<symbol overflow="visible" id="glyph0-16">
54<path style="stroke:none;" d="M 0.828125 -1.171875 C 0.828125 -0.453125 2.34375 0.28125 3.78125 0.28125 C 5.515625 0.28125 7.078125 -0.78125 7.078125 -2.484375 C 7.078125 -3.875 5.53125 -4.546875 4.171875 -5.203125 C 3.1875 -5.671875 2.25 -6.078125 2.25 -7.078125 C 2.25 -8.296875 3.1875 -8.71875 3.96875 -8.71875 C 5.484375 -8.71875 5.234375 -7.203125 5.765625 -7.203125 C 6.03125 -7.203125 6.703125 -7.390625 6.703125 -7.640625 C 6.703125 -8.1875 6.046875 -9.21875 4.265625 -9.21875 C 2.609375 -9.21875 0.890625 -8.140625 0.890625 -6.5625 C 0.890625 -4.90625 2.328125 -4.4375 3.609375 -3.875 C 4.71875 -3.40625 5.703125 -2.890625 5.703125 -1.78125 C 5.703125 -0.734375 4.953125 -0.265625 4.15625 -0.265625 C 3.03125 -0.265625 2.4375 -0.875 1.96875 -1.4375 C 1.6875 -1.765625 1.671875 -2.0625 1.53125 -2.0625 C 1.34375 -2.0625 0.828125 -1.546875 0.828125 -1.171875 Z M 0.828125 -1.171875 "/>
55</symbol>
56<symbol overflow="visible" id="glyph0-17">
57<path style="stroke:none;" d="M 0.234375 -15.21875 C 0.234375 -15.046875 0.265625 -15.03125 0.46875 -15.03125 C 0.703125 -15.03125 1.640625 -15.09375 1.78125 -15.09375 C 2 -15.09375 2 -10.203125 2 -5.53125 L 2 -1.015625 C 2 -0.65625 2 -0.59375 1.765625 -0.59375 L 0.796875 -0.59375 C 0.5625 -0.59375 0.515625 -0.5 0.515625 -0.28125 C 0.515625 -0.03125 0.515625 0.046875 0.828125 0.046875 C 1.078125 0.046875 1.921875 0 2.703125 0 C 3.375 0 3.84375 0.046875 4.296875 0.046875 C 4.59375 0.046875 4.59375 -0.078125 4.59375 -0.28125 C 4.59375 -0.5 4.578125 -0.59375 4.296875 -0.59375 L 3.75 -0.59375 C 3.515625 -0.59375 3.5 -0.59375 3.5 -1.015625 L 3.5 -4.15625 C 3.5 -4.4375 3.5 -4.53125 3.75 -4.53125 L 4.078125 -4.53125 C 4.3125 -4.53125 4.3125 -4.484375 4.59375 -4.125 L 7.171875 -0.9375 C 7.296875 -0.796875 7.40625 -0.59375 7.0625 -0.59375 L 6.796875 -0.59375 C 6.5625 -0.59375 6.515625 -0.5 6.515625 -0.28125 C 6.515625 -0.03125 6.515625 0.046875 6.828125 0.046875 C 7.15625 0.046875 7.828125 0 8.421875 0 C 9 0 9.65625 0.046875 9.984375 0.046875 C 10.296875 0.046875 10.296875 -0.078125 10.296875 -0.28125 C 10.296875 -0.5 10.265625 -0.59375 9.984375 -0.59375 L 9.75 -0.59375 C 9.546875 -0.59375 9.46875 -0.609375 9.234375 -0.890625 L 5.703125 -5 C 5.421875 -5.328125 5.421875 -5.203125 5.703125 -5.5625 C 6.125 -6.09375 8.015625 -8.4375 8.203125 -8.4375 L 8.953125 -8.4375 C 9.1875 -8.4375 9.234375 -8.53125 9.234375 -8.75 C 9.234375 -9 9.171875 -9.078125 8.9375 -9.078125 C 8.578125 -9.078125 8.046875 -9.03125 7.59375 -9.03125 C 7.109375 -9.03125 6.46875 -9.078125 6.234375 -9.078125 C 5.9375 -9.078125 5.90625 -8.953125 5.90625 -8.75 C 5.90625 -8.53125 5.9375 -8.4375 6.21875 -8.4375 L 6.6875 -8.4375 C 7.15625 -8.4375 7.078125 -8.34375 6.921875 -8.0625 C 6.375 -7.171875 5.71875 -6.28125 5.0625 -5.421875 C 4.90625 -5.203125 4.734375 -4.90625 4.390625 -4.90625 L 3.875 -4.90625 C 3.515625 -4.90625 3.5 -4.921875 3.5 -5.15625 L 3.75 -15.65625 C 3.75 -15.9375 3.75 -15.96875 3.59375 -15.96875 C 3.453125 -15.96875 1.40625 -15.828125 0.515625 -15.75 C 0.265625 -15.734375 0.234375 -15.609375 0.234375 -15.421875 Z M 0.234375 -15.21875 "/>
58</symbol>
59<symbol overflow="visible" id="glyph0-18">
60<path style="stroke:none;" d="M 0.46875 -15.125 C 0.46875 -15.046875 0.5 -15.046875 0.65625 -15.046875 C 0.75 -15.046875 1.671875 -15.140625 1.78125 -15.140625 C 2.015625 -15.140625 2 -15.09375 2.046875 -14.703125 C 2.234375 -12.609375 2.296875 -3.734375 2.296875 -2.578125 C 2.296875 -2 2.296875 -0.59375 2.203125 -0.59375 L 0.984375 -0.59375 C 0.75 -0.59375 0.703125 -0.5 0.703125 -0.28125 C 0.703125 -0.03125 0.703125 0.046875 1.015625 0.046875 C 1.71875 0.046875 2.609375 0 3.1875 0 C 3.875 0 4.59375 0.046875 5.046875 0.046875 C 5.34375 0.046875 5.34375 -0.078125 5.34375 -0.28125 C 5.34375 -0.5 5.328125 -0.59375 5.046875 -0.59375 L 4.125 -0.59375 C 3.9375 -0.59375 3.9375 -0.96875 3.9375 -1.5 C 3.9375 -6.21875 3.828125 -8.34375 3.796875 -15.546875 C 3.796875 -15.828125 3.796875 -15.890625 3.640625 -15.890625 C 3.5 -15.890625 1.6875 -15.75 0.75 -15.6875 C 0.546875 -15.65625 0.5625 -15.6875 0.515625 -15.5 C 0.5 -15.328125 0.46875 -15.1875 0.46875 -15.125 Z M 0.46875 -15.125 "/>
61</symbol>
62<symbol overflow="visible" id="glyph0-19">
63<path style="stroke:none;" d="M 0.703125 -4.265625 C 0.703125 -1.53125 2.296875 0.359375 5.1875 0.359375 C 7.546875 0.359375 9.234375 -1.71875 9.234375 -1.859375 C 9.234375 -1.921875 8.9375 -2.203125 8.859375 -2.203125 C 8.796875 -2.203125 7.71875 -0.6875 5.84375 -0.6875 C 4.078125 -0.6875 2.34375 -2.046875 2.34375 -4.546875 C 2.34375 -4.875 2.34375 -5.390625 2.46875 -5.390625 C 2.65625 -5.390625 7.453125 -5.28125 7.71875 -5.28125 C 8 -5.28125 8.984375 -5.375 8.984375 -5.5625 C 8.984375 -7.53125 7.8125 -9.28125 5.484375 -9.28125 C 2.65625 -9.28125 0.703125 -7.078125 0.703125 -4.265625 Z M 2.46875 -5.984375 C 2.5625 -7.15625 3.65625 -8.765625 5.203125 -8.765625 C 5.953125 -8.765625 7.359375 -8.28125 7.359375 -5.984375 C 7.359375 -5.9375 7.296875 -5.90625 6.421875 -5.890625 C 5.25 -5.84375 2.859375 -5.796875 2.75 -5.796875 C 2.5625 -5.796875 2.46875 -5.84375 2.46875 -5.984375 Z M 2.46875 -5.984375 "/>
64</symbol>
65<symbol overflow="visible" id="glyph1-0">
66<path style="stroke:none;" d="M 1.0625 -12.3125 L 1.0625 4.109375 L 5.984375 4.109375 L 5.984375 -12.3125 Z M 5.34375 3.5 L 1.703125 3.5 L 1.703125 -11.703125 L 5.34375 -11.703125 Z M 3.59375 -2.03125 L 3.59375 -2.5625 C 4.390625 -2.671875 4.71875 -3.125 4.71875 -3.9375 C 4.71875 -4.640625 4.421875 -5.28125 3.40625 -5.28125 C 2.953125 -5.28125 2.328125 -5.140625 2.328125 -4.828125 C 2.328125 -4.671875 2.421875 -4.5625 2.609375 -4.5625 C 2.65625 -4.5625 2.703125 -4.578125 2.75 -4.59375 C 2.953125 -4.6875 3.125 -4.71875 3.359375 -4.71875 C 3.953125 -4.71875 4.078125 -4.375 4.078125 -3.921875 C 4.078125 -3.296875 3.859375 -3.0625 3.015625 -3.015625 L 3.015625 -2.03125 C 3.015625 -1.859375 3.15625 -1.75 3.3125 -1.75 C 3.453125 -1.75 3.59375 -1.859375 3.59375 -2.03125 Z M 2.890625 -1 C 2.890625 -0.75 3.078125 -0.5625 3.3125 -0.5625 C 3.546875 -0.5625 3.71875 -0.75 3.71875 -1 C 3.71875 -1.234375 3.546875 -1.40625 3.3125 -1.40625 C 3.078125 -1.40625 2.890625 -1.234375 2.890625 -1 Z M 2.890625 -1 "/>
67</symbol>
68<symbol overflow="visible" id="glyph1-1">
69<path style="stroke:none;" d="M 5.609375 -1.34375 L 5.609375 -4.3125 C 5.609375 -5.53125 4.828125 -6.3125 3.296875 -6.3125 C 2.6875 -6.3125 2.03125 -6.1875 1.265625 -5.921875 L 1.53125 -5.171875 C 2.171875 -5.390625 2.734375 -5.484375 3.140625 -5.484375 C 4.0625 -5.484375 4.609375 -5.15625 4.609375 -4.25 L 4.609375 -3.75 L 3.6875 -3.75 C 1.828125 -3.75 0.8125 -3.03125 0.8125 -1.765625 C 0.8125 -0.625 1.5625 0.125 2.796875 0.125 C 3.59375 0.125 4.296875 -0.171875 4.734375 -0.734375 C 4.90625 -0.171875 5.328125 0.078125 5.859375 0.140625 L 6.109375 -0.5625 C 5.75 -0.671875 5.609375 -0.859375 5.609375 -1.34375 Z M 3.046875 -0.609375 C 2.234375 -0.609375 1.859375 -1.015625 1.859375 -1.78125 C 1.859375 -2.578125 2.359375 -3.078125 3.71875 -3.078125 L 4.609375 -3.078125 L 4.609375 -1.484375 C 4.25 -0.9375 3.65625 -0.609375 3.046875 -0.609375 Z M 3.046875 -0.609375 "/>
70</symbol>
71<symbol overflow="visible" id="glyph1-2">
72<path style="stroke:none;" d="M 3.96875 -0.71875 C 2.90625 -0.71875 2.140625 -1.40625 2.140625 -3.0625 C 2.140625 -4.6875 2.890625 -5.46875 3.96875 -5.46875 C 4.515625 -5.46875 5.03125 -5.28125 5.5625 -4.9375 L 6.03125 -5.578125 C 5.46875 -6.0625 4.765625 -6.3125 3.96875 -6.3125 C 2.140625 -6.3125 1.0625 -4.90625 1.0625 -3.0625 C 1.0625 -1.125 2.125 0.125 3.96875 0.125 C 4.6875 0.125 5.515625 -0.15625 6.046875 -0.609375 L 5.578125 -1.25 C 5.109375 -0.9375 4.59375 -0.71875 3.96875 -0.71875 Z M 3.96875 -0.71875 "/>
73</symbol>
74<symbol overflow="visible" id="glyph1-3">
75<path style="stroke:none;" d="M 6.078125 -0.3125 L 5.703125 -0.984375 C 5.375 -0.8125 4.96875 -0.6875 4.515625 -0.6875 C 3.671875 -0.6875 3.328125 -1.0625 3.328125 -1.734375 L 3.328125 -5.40625 L 5.34375 -5.40625 L 5.46875 -6.171875 L 3.328125 -6.171875 L 3.328125 -7.6875 L 2.34375 -7.578125 L 2.34375 -6.171875 L 0.921875 -6.171875 L 0.921875 -5.40625 L 2.34375 -5.40625 L 2.34375 -1.71875 C 2.34375 -0.640625 3.09375 0.125 4.421875 0.125 C 5 0.125 5.65625 -0.03125 6.078125 -0.3125 Z M 6.078125 -0.3125 "/>
76</symbol>
77<symbol overflow="visible" id="glyph1-4">
78<path style="stroke:none;" d="M 3.515625 -9.0625 C 3.09375 -9.0625 2.8125 -8.765625 2.8125 -8.375 C 2.8125 -7.96875 3.09375 -7.671875 3.515625 -7.671875 C 3.953125 -7.671875 4.25 -7.96875 4.25 -8.375 C 4.25 -8.765625 3.953125 -9.0625 3.515625 -9.0625 Z M 4.296875 -6.171875 L 1.484375 -6.171875 L 1.484375 -5.390625 L 3.3125 -5.390625 L 3.3125 -0.78125 L 1.421875 -0.78125 L 1.421875 0 L 6.03125 0 L 6.03125 -0.78125 L 4.296875 -0.78125 Z M 4.296875 -6.171875 "/>
79</symbol>
80<symbol overflow="visible" id="glyph1-5">
81<path style="stroke:none;" d="M 6.328125 -6.171875 L 5.296875 -6.171875 L 3.546875 -0.890625 L 1.765625 -6.171875 L 0.703125 -6.171875 L 2.9375 0 L 4.078125 0 Z M 6.328125 -6.171875 "/>
82</symbol>
83<symbol overflow="visible" id="glyph1-6">
84<path style="stroke:none;" d="M 1.953125 -2.75 L 6.109375 -2.75 C 6.125 -2.875 6.125 -3.0625 6.125 -3.265625 C 6.125 -5.140625 5.171875 -6.3125 3.609375 -6.3125 C 1.96875 -6.3125 0.921875 -4.953125 0.921875 -3.078125 C 0.921875 -1.15625 1.953125 0.125 3.75 0.125 C 4.515625 0.125 5.28125 -0.140625 5.859375 -0.59375 L 5.40625 -1.25 C 4.859375 -0.875 4.390625 -0.6875 3.75 -0.6875 C 2.796875 -0.6875 2 -1.3125 1.953125 -2.75 Z M 3.625 -5.5 C 4.5625 -5.5 5.140625 -4.8125 5.171875 -3.5 L 1.953125 -3.5 C 2.046875 -4.859375 2.703125 -5.5 3.625 -5.5 Z M 3.625 -5.5 "/>
85</symbol>
86<symbol overflow="visible" id="glyph1-7">
87<path style="stroke:none;" d="M 4.015625 -7.203125 L 6.453125 -7.203125 L 6.546875 -8.078125 L 0.46875 -8.078125 L 0.46875 -7.203125 L 2.984375 -7.203125 L 2.984375 0 L 4.015625 0 Z M 4.015625 -7.203125 "/>
88</symbol>
89<symbol overflow="visible" id="glyph1-8">
90<path style="stroke:none;" d="M 1.78125 0 L 3.484375 -2.65625 L 5.1875 0 L 6.375 0 L 4.109375 -3.3125 L 6.109375 -6.171875 L 4.96875 -6.171875 L 3.53125 -3.875 L 2.09375 -6.171875 L 0.921875 -6.171875 L 2.9375 -3.265625 L 0.65625 0 Z M 1.78125 0 "/>
91</symbol>
92<symbol overflow="visible" id="glyph1-9">
93<path style="stroke:none;" d="M 1.171875 0 L 2.15625 0 L 2.15625 -4.484375 C 2.484375 -4.984375 3.109375 -5.515625 3.828125 -5.515625 C 4.765625 -5.515625 4.890625 -5.015625 4.890625 -3.75 L 4.890625 0 L 5.875 0 L 5.875 -4.484375 C 5.875 -5.625 5.34375 -6.3125 4.140625 -6.3125 C 3.40625 -6.3125 2.59375 -5.9375 2.09375 -5.3125 L 2.015625 -6.171875 L 1.171875 -6.171875 Z M 1.171875 0 "/>
94</symbol>
95<symbol overflow="visible" id="glyph1-10">
96<path style="stroke:none;" d="M 2.5625 -5.046875 C 2.5625 -4.53125 2.96875 -4.09375 3.5 -4.09375 C 4.0625 -4.09375 4.453125 -4.53125 4.453125 -5.046875 C 4.453125 -5.5625 4.0625 -5.984375 3.5 -5.984375 C 2.96875 -5.984375 2.5625 -5.5625 2.5625 -5.046875 Z M 2.5625 -0.828125 C 2.5625 -0.28125 2.96875 0.125 3.5 0.125 C 4.0625 0.125 4.453125 -0.28125 4.453125 -0.828125 C 4.453125 -1.34375 4.0625 -1.765625 3.5 -1.765625 C 2.96875 -1.765625 2.5625 -1.34375 2.5625 -0.828125 Z M 2.5625 -0.828125 "/>
97</symbol>
98<symbol overflow="visible" id="glyph1-11">
99<path style="stroke:none;" d=""/>
100</symbol>
101<symbol overflow="visible" id="glyph1-12">
102<path style="stroke:none;" d="M 3.53125 -6.3125 C 1.796875 -6.3125 0.859375 -4.984375 0.859375 -3.078125 C 0.859375 -1.140625 1.78125 0.125 3.515625 0.125 C 5.234375 0.125 6.171875 -1.203125 6.171875 -3.09375 C 6.171875 -5.046875 5.265625 -6.3125 3.53125 -6.3125 Z M 3.53125 -5.5 C 4.578125 -5.5 5.109375 -4.71875 5.109375 -3.09375 C 5.109375 -1.4375 4.578125 -0.6875 3.515625 -0.6875 C 2.453125 -0.6875 1.921875 -1.4375 1.921875 -3.078125 C 1.921875 -4.71875 2.46875 -5.5 3.53125 -5.5 Z M 3.53125 -5.5 "/>
103</symbol>
104<symbol overflow="visible" id="glyph1-13">
105<path style="stroke:none;" d="M 5.234375 -6.3125 C 4.625 -6.3125 4.21875 -5.984375 3.875 -5.484375 C 3.6875 -6.125 3.234375 -6.3125 2.765625 -6.3125 C 2.140625 -6.3125 1.765625 -5.9375 1.4375 -5.453125 L 1.359375 -6.171875 L 0.59375 -6.171875 L 0.59375 0 L 1.5 0 L 1.5 -4.796875 C 1.84375 -5.328125 2.1875 -5.53125 2.578125 -5.53125 C 3.03125 -5.53125 3.0625 -5.21875 3.0625 -4.4375 L 3.0625 0 L 3.96875 0 L 3.96875 -4.796875 C 4.3125 -5.328125 4.671875 -5.53125 5.046875 -5.53125 C 5.5 -5.53125 5.53125 -5.21875 5.53125 -4.4375 L 5.53125 0 L 6.4375 0 L 6.4375 -4.59375 C 6.4375 -6.015625 5.84375 -6.3125 5.234375 -6.3125 Z M 5.234375 -6.3125 "/>
106</symbol>
107<symbol overflow="visible" id="glyph1-14">
108<path style="stroke:none;" d="M 4.875 -8.78125 L 4.875 -5.5625 C 4.453125 -6.046875 3.921875 -6.3125 3.21875 -6.3125 C 1.703125 -6.3125 0.796875 -4.9375 0.796875 -3.078125 C 0.796875 -1.15625 1.53125 0.125 3.15625 0.125 C 3.828125 0.125 4.4375 -0.171875 4.90625 -0.8125 L 5 0 L 5.859375 0 L 5.859375 -8.65625 Z M 3.46875 -5.515625 C 4.046875 -5.515625 4.53125 -5.21875 4.875 -4.71875 L 4.875 -1.640625 C 4.53125 -1.125 4.0625 -0.65625 3.359375 -0.65625 C 2.375 -0.65625 1.859375 -1.484375 1.859375 -3.078125 C 1.859375 -4.71875 2.453125 -5.515625 3.46875 -5.515625 Z M 3.46875 -5.515625 "/>
109</symbol>
110<symbol overflow="visible" id="glyph1-15">
111<path style="stroke:none;" d="M 3.28125 -0.6875 C 2.5625 -0.6875 1.90625 -0.953125 1.421875 -1.34375 L 0.875 -0.703125 C 1.390625 -0.25 2.15625 0.125 3.28125 0.125 C 4.59375 0.125 5.875 -0.390625 5.875 -1.71875 C 5.875 -2.859375 5.078125 -3.28125 3.875 -3.609375 C 2.625 -3.953125 2.234375 -4.140625 2.234375 -4.703125 C 2.234375 -5.171875 2.59375 -5.515625 3.578125 -5.515625 C 4.375 -5.515625 4.90625 -5.265625 5.359375 -4.953125 L 5.796875 -5.625 C 5.28125 -6 4.546875 -6.3125 3.546875 -6.3125 C 2.15625 -6.3125 1.203125 -5.65625 1.203125 -4.625 C 1.203125 -3.546875 2.046875 -3.15625 3.3125 -2.84375 C 4.625 -2.515625 4.8125 -2.21875 4.8125 -1.671875 C 4.8125 -1.0625 4.234375 -0.6875 3.28125 -0.6875 Z M 3.28125 -0.6875 "/>
112</symbol>
113<symbol overflow="visible" id="glyph1-16">
114<path style="stroke:none;" d="M 2.234375 -8.78125 L 1.25 -8.65625 L 1.25 0 L 2.234375 0 Z M 6.34375 -6.171875 L 5.078125 -6.171875 L 2.328125 -3.375 L 5.375 0 L 6.671875 0 L 3.578125 -3.390625 Z M 6.34375 -6.171875 "/>
115</symbol>
116<symbol overflow="visible" id="glyph1-17">
117<path style="stroke:none;" d="M 3.59375 -8.65625 L 0.703125 -8.65625 L 0.703125 -7.875 L 2.609375 -7.875 L 2.609375 -1.578125 C 2.609375 -0.5 3.34375 0.125 4.4375 0.125 C 5.0625 0.125 5.5625 -0.015625 5.890625 -0.1875 L 5.640625 -0.90625 C 5.296875 -0.78125 4.96875 -0.6875 4.609375 -0.6875 C 4.015625 -0.6875 3.59375 -0.921875 3.59375 -1.53125 Z M 3.59375 -8.65625 "/>
118</symbol>
119<symbol overflow="visible" id="glyph1-18">
120<path style="stroke:none;" d="M 6.203125 -6.828125 C 5.46875 -6.515625 4.9375 -6.3125 3.390625 -6.3125 C 1.921875 -6.3125 0.921875 -5.421875 0.921875 -4.15625 C 0.921875 -3.359375 1.25 -2.828125 1.953125 -2.46875 C 1.515625 -2.171875 1.28125 -1.765625 1.28125 -1.390625 C 1.28125 -0.765625 1.765625 -0.21875 2.84375 -0.21875 L 3.9375 -0.21875 C 4.71875 -0.21875 5.328125 0.078125 5.328125 0.671875 C 5.328125 1.34375 4.71875 1.6875 3.375 1.6875 C 2 1.6875 1.671875 1.34375 1.671875 0.625 L 0.78125 0.625 C 0.78125 1.875 1.40625 2.484375 3.375 2.484375 C 5.25 2.484375 6.3125 1.8125 6.3125 0.609375 C 6.3125 -0.359375 5.375 -1.0625 4.140625 -1.0625 L 3.03125 -1.0625 C 2.390625 -1.0625 2.203125 -1.296875 2.203125 -1.59375 C 2.203125 -1.8125 2.34375 -2.046875 2.515625 -2.1875 C 2.796875 -2.09375 3.03125 -2.0625 3.453125 -2.0625 C 4.90625 -2.0625 5.765625 -2.9375 5.765625 -4.15625 C 5.765625 -4.859375 5.421875 -5.390625 4.6875 -5.71875 C 5.375 -5.71875 5.984375 -5.734375 6.5 -5.890625 Z M 3.375 -5.578125 C 4.296875 -5.578125 4.75 -5.09375 4.75 -4.171875 C 4.75 -3.265625 4.28125 -2.71875 3.40625 -2.71875 C 2.390625 -2.71875 1.9375 -3.3125 1.9375 -4.15625 C 1.9375 -5 2.375 -5.578125 3.375 -5.578125 Z M 3.375 -5.578125 "/>
121</symbol>
122<symbol overflow="visible" id="glyph2-0">
123<path style="stroke:none;" d="M 1.828125 -21.328125 L 1.828125 7.109375 L 10.359375 7.109375 L 10.359375 -21.328125 Z M 9.265625 6.046875 L 2.953125 6.046875 L 2.953125 -20.265625 L 9.265625 -20.265625 Z M 6.234375 -3.515625 L 6.234375 -4.421875 C 7.59375 -4.625 8.171875 -5.40625 8.171875 -6.828125 C 8.171875 -8.046875 7.65625 -9.15625 5.90625 -9.15625 C 5.125 -9.15625 4.015625 -8.921875 4.015625 -8.375 C 4.015625 -8.109375 4.203125 -7.90625 4.515625 -7.90625 C 4.59375 -7.90625 4.671875 -7.921875 4.78125 -7.96875 C 5.125 -8.125 5.40625 -8.1875 5.828125 -8.1875 C 6.84375 -8.1875 7.0625 -7.578125 7.0625 -6.78125 C 7.0625 -5.703125 6.6875 -5.296875 5.21875 -5.21875 L 5.21875 -3.515625 C 5.21875 -3.203125 5.46875 -3.03125 5.734375 -3.03125 C 5.96875 -3.03125 6.234375 -3.203125 6.234375 -3.515625 Z M 5.015625 -1.734375 C 5.015625 -1.296875 5.328125 -0.96875 5.734375 -0.96875 C 6.140625 -0.96875 6.4375 -1.296875 6.4375 -1.734375 C 6.4375 -2.140625 6.140625 -2.4375 5.734375 -2.4375 C 5.328125 -2.4375 5.015625 -2.140625 5.015625 -1.734375 Z M 5.015625 -1.734375 "/>
124</symbol>
125<symbol overflow="visible" id="glyph2-1">
126<path style="stroke:none;" d="M 6.09375 -3.359375 C 5.1875 -3.359375 4.46875 -2.625 4.46875 -1.703125 C 4.46875 -1.171875 4.734375 -0.65625 5.125 -0.359375 L 4.171875 3.640625 L 5.703125 3.640625 L 7.359375 -0.125 C 7.640625 -0.75 7.734375 -1.21875 7.734375 -1.734375 C 7.734375 -2.625 7.03125 -3.359375 6.09375 -3.359375 Z M 6.09375 -3.359375 "/>
127</symbol>
128<symbol overflow="visible" id="glyph2-2">
129<path style="stroke:none;" d=""/>
130</symbol>
131<symbol overflow="visible" id="glyph3-0">
132<path style="stroke:none;" d="M 0.59375 0 L 5.28125 0 L 5.28125 -5.390625 L 0.59375 -5.390625 Z M 1.171875 -0.59375 L 1.171875 -4.8125 L 4.6875 -4.8125 L 4.6875 -0.59375 Z M 1.171875 -0.59375 "/>
133</symbol>
134<symbol overflow="visible" id="glyph3-1">
135<path style="stroke:none;" d="M 0.125 -7.5 C 0.125 -7.4375 0.125 -7.375 0.171875 -7.375 C 0.21875 -7.375 0.84375 -7.453125 0.875 -7.453125 C 0.953125 -7.453125 0.9375 -7.40625 0.953125 -7.25 C 1 -6.359375 1.046875 -4.46875 1.046875 -3.078125 C 1.046875 -2.234375 1.046875 -1.609375 1.03125 -0.5 C 1.03125 -0.328125 1.03125 -0.296875 0.921875 -0.296875 L 0.453125 -0.296875 C 0.34375 -0.296875 0.3125 -0.25 0.3125 -0.140625 C 0.3125 -0.015625 0.3125 0.03125 0.46875 0.03125 C 0.828125 0.03125 1.1875 0 1.484375 0 C 1.8125 0 2.234375 0.03125 2.453125 0.03125 C 2.609375 0.03125 2.609375 -0.03125 2.609375 -0.140625 C 2.609375 -0.25 2.59375 -0.296875 2.453125 -0.296875 L 2 -0.296875 C 1.890625 -0.296875 1.890625 -0.296875 1.875 -0.5 C 1.859375 -0.8125 1.859375 -1.375 1.859375 -1.859375 L 1.859375 -3.609375 C 1.859375 -3.65625 1.875 -3.703125 2.046875 -3.78125 C 2.28125 -3.90625 2.609375 -4.03125 3.078125 -4.03125 C 3.875 -4.03125 4.203125 -3.328125 4.203125 -2.484375 C 4.203125 -1.25 4.203125 -0.65625 4.1875 -0.421875 C 4.171875 -0.296875 4.171875 -0.296875 4.0625 -0.296875 L 3.59375 -0.296875 C 3.484375 -0.296875 3.453125 -0.25 3.453125 -0.140625 C 3.453125 -0.015625 3.453125 0.03125 3.59375 0.03125 C 3.953125 0.03125 4.3125 0 4.609375 0 C 4.953125 0 5.21875 0.03125 5.4375 0.03125 C 5.59375 0.03125 5.609375 -0.03125 5.609375 -0.140625 C 5.609375 -0.25 5.578125 -0.296875 5.4375 -0.296875 L 5.140625 -0.296875 C 5.015625 -0.296875 5 -0.3125 5 -0.4375 L 5 -2.109375 C 5 -3.375 4.859375 -4.515625 3.546875 -4.515625 C 3.046875 -4.515625 2.34375 -4.25 1.984375 -4.046875 C 1.859375 -3.96875 1.859375 -3.953125 1.859375 -4.15625 C 1.859375 -5.1875 1.90625 -6.703125 1.953125 -7.671875 C 1.953125 -7.796875 1.953125 -7.90625 1.890625 -7.90625 C 1.8125 -7.90625 0.71875 -7.765625 0.171875 -7.703125 C 0.125 -7.6875 0.125 -7.59375 0.125 -7.5 Z M 0.125 -7.5 "/>
136</symbol>
137<symbol overflow="visible" id="glyph3-2">
138<path style="stroke:none;" d="M 0.359375 -2.140625 C 0.359375 -0.765625 1.15625 0.171875 2.59375 0.171875 C 3.78125 0.171875 4.625 -0.859375 4.625 -0.921875 C 4.625 -0.96875 4.46875 -1.109375 4.4375 -1.109375 C 4.390625 -1.109375 3.859375 -0.34375 2.921875 -0.34375 C 2.046875 -0.34375 1.171875 -1.015625 1.171875 -2.28125 C 1.171875 -2.4375 1.171875 -2.703125 1.234375 -2.703125 C 1.328125 -2.703125 3.734375 -2.640625 3.859375 -2.640625 C 4 -2.640625 4.484375 -2.6875 4.484375 -2.78125 C 4.484375 -3.765625 3.90625 -4.640625 2.75 -4.640625 C 1.328125 -4.640625 0.359375 -3.546875 0.359375 -2.140625 Z M 1.234375 -2.984375 C 1.28125 -3.578125 1.828125 -4.390625 2.609375 -4.390625 C 2.984375 -4.390625 3.6875 -4.140625 3.6875 -2.984375 C 3.6875 -2.96875 3.640625 -2.953125 3.21875 -2.9375 C 2.625 -2.921875 1.4375 -2.890625 1.375 -2.890625 C 1.28125 -2.890625 1.234375 -2.921875 1.234375 -2.984375 Z M 1.234375 -2.984375 "/>
139</symbol>
140<symbol overflow="visible" id="glyph3-3">
141<path style="stroke:none;" d="M 0.40625 -0.828125 C 0.40625 -0.234375 0.828125 0.171875 1.5625 0.171875 C 2.046875 0.171875 2.671875 -0.171875 2.90625 -0.3125 C 3 -0.359375 3.125 -0.453125 3.140625 -0.453125 C 3.171875 -0.453125 3.1875 0.203125 3.609375 0.203125 C 3.734375 0.203125 3.828125 0.125 3.921875 0.078125 C 4.171875 -0.109375 4.671875 -0.453125 4.671875 -0.5 C 4.671875 -0.578125 4.578125 -0.6875 4.53125 -0.6875 C 4.484375 -0.6875 4.125 -0.40625 4.078125 -0.40625 C 3.875 -0.40625 3.828125 -0.640625 3.828125 -0.75 C 3.828125 -1.015625 3.890625 -2.546875 3.890625 -3.140625 C 3.890625 -4.0625 3.546875 -4.671875 2.359375 -4.671875 C 1.59375 -4.671875 0.578125 -4.109375 0.578125 -3.140625 C 0.578125 -3.015625 0.609375 -2.96875 0.671875 -2.96875 C 0.71875 -2.96875 1.109375 -3.15625 1.296875 -3.296875 C 1.359375 -3.34375 1.375 -3.46875 1.375 -3.546875 C 1.390625 -4.015625 1.421875 -4.1875 1.75 -4.328125 C 1.859375 -4.375 2 -4.390625 2.109375 -4.390625 C 3.125 -4.390625 3.125 -3.578125 3.125 -2.75 C 3.125 -2.65625 3.125 -2.578125 3.03125 -2.5625 C 1.875 -2.375 0.40625 -1.875 0.40625 -0.828125 Z M 1.234375 -1.15625 C 1.234375 -1.71875 1.78125 -2.03125 2.328125 -2.203125 C 2.671875 -2.3125 3.03125 -2.375 3.0625 -2.375 C 3.125 -2.375 3.125 -2.328125 3.125 -2.25 L 3.125 -0.6875 C 3.125 -0.625 2.515625 -0.359375 2 -0.359375 C 1.5 -0.359375 1.234375 -0.78125 1.234375 -1.15625 Z M 1.234375 -1.15625 "/>
142</symbol>
143<symbol overflow="visible" id="glyph3-4">
144<path style="stroke:none;" d="M 0.359375 -2.125 C 0.359375 -0.4375 1.375 0.15625 2.421875 0.15625 C 2.921875 0.15625 3.421875 -0.0625 3.828125 -0.3125 C 3.984375 -0.40625 4 -0.375 4 -0.265625 C 4 -0.21875 3.984375 0.140625 3.984375 0.171875 C 3.984375 0.21875 4.015625 0.265625 4.0625 0.265625 L 5.40625 0.09375 C 5.5625 0.078125 5.5625 0.03125 5.5625 -0.125 C 5.5625 -0.25 5.515625 -0.234375 5.421875 -0.21875 C 5.25 -0.203125 5.125 -0.171875 5.03125 -0.171875 C 4.84375 -0.171875 4.765625 -0.28125 4.765625 -0.75 C 4.75 -1.171875 4.734375 -1.78125 4.734375 -2.15625 C 4.734375 -5.796875 4.8125 -7.296875 4.8125 -7.703125 C 4.8125 -7.953125 4.796875 -7.96875 4.6875 -7.96875 C 4.625 -7.96875 3.828125 -7.84375 3.15625 -7.765625 C 3.078125 -7.75 3.078125 -7.6875 3.0625 -7.609375 C 3.03125 -7.4375 3.03125 -7.4375 3.109375 -7.4375 C 3.1875 -7.4375 3.859375 -7.53125 3.890625 -7.53125 C 3.921875 -7.53125 4.015625 -5.53125 4.015625 -4.34375 C 4.015625 -4.25 4.015625 -4.140625 3.9375 -4.140625 C 3.921875 -4.140625 3.4375 -4.4375 2.734375 -4.4375 C 1.390625 -4.4375 0.359375 -3.453125 0.359375 -2.125 Z M 1.203125 -2.203125 C 1.203125 -3.25 1.84375 -4.203125 2.875 -4.203125 C 3.484375 -4.203125 4.015625 -3.75 4.015625 -3.59375 L 4.015625 -0.671875 C 4.015625 -0.453125 3.296875 -0.28125 2.984375 -0.28125 C 1.71875 -0.28125 1.203125 -1.109375 1.203125 -2.203125 Z M 1.203125 -2.203125 "/>
145</symbol>
146<symbol overflow="visible" id="glyph3-5">
147<path style="stroke:none;" d="M 0.296875 -4.140625 C 0.296875 -4.109375 0.296875 -4.09375 0.328125 -4.09375 C 0.375 -4.09375 1.046875 -4.109375 1.078125 -4.109375 C 1.109375 -4.109375 1.15625 -2.9375 1.15625 -1.90625 C 1.15625 -1.0625 1.15625 -0.296875 1.0625 -0.296875 L 0.546875 -0.296875 C 0.4375 -0.296875 0.40625 -0.25 0.40625 -0.140625 C 0.40625 -0.015625 0.40625 0.03125 0.5625 0.03125 C 0.921875 0.03125 1.28125 0 1.578125 0 C 1.90625 0 2.59375 0.03125 2.8125 0.03125 C 2.96875 0.03125 2.96875 -0.03125 2.96875 -0.140625 C 2.96875 -0.25 2.953125 -0.296875 2.8125 -0.296875 L 2.078125 -0.296875 C 1.9375 -0.296875 1.9375 -0.984375 1.9375 -1.609375 C 1.9375 -2.609375 2.015625 -4 2.609375 -4 C 2.84375 -4 3.03125 -3.640625 3.3125 -3.640625 C 3.5 -3.640625 3.734375 -3.984375 3.734375 -4.109375 C 3.734375 -4.25 3.421875 -4.625 3.078125 -4.625 C 2.71875 -4.625 2.25 -4.25 1.984375 -3.625 C 1.9375 -3.515625 1.90625 -3.328125 1.875 -3.328125 C 1.859375 -3.328125 1.859375 -3.390625 1.859375 -3.546875 C 1.859375 -3.765625 1.875 -4.0625 1.875 -4.296875 C 1.875 -4.40625 1.921875 -4.40625 1.734375 -4.40625 C 1.65625 -4.40625 0.671875 -4.390625 0.5 -4.375 C 0.34375 -4.359375 0.359375 -4.375 0.328125 -4.28125 C 0.3125 -4.21875 0.296875 -4.171875 0.296875 -4.140625 Z M 0.296875 -4.140625 "/>
148</symbol>
149<symbol overflow="visible" id="glyph3-6">
150<path style="stroke:none;" d="M 0.40625 -4.03125 C 0.40625 -3.984375 0.4375 -3.953125 0.484375 -3.953125 L 0.78125 -3.953125 C 0.90625 -3.953125 0.921875 -3.671875 0.921875 -3.234375 C 0.921875 -2.890625 0.90625 -1.546875 0.890625 -0.703125 C 0.890625 -0.359375 1.0625 0.109375 1.734375 0.109375 C 2.21875 0.109375 3.21875 -0.390625 3.21875 -0.453125 C 3.21875 -0.53125 3.203125 -0.640625 3.171875 -0.640625 C 3.078125 -0.640625 2.6875 -0.453125 2.234375 -0.453125 C 1.6875 -0.453125 1.671875 -0.8125 1.671875 -1.171875 L 1.671875 -3.421875 C 1.671875 -3.75 1.671875 -3.96875 1.703125 -3.96875 L 2.859375 -3.96875 C 2.9375 -3.96875 2.984375 -4 3.015625 -4.15625 C 3.0625 -4.359375 3.046875 -4.359375 2.90625 -4.359375 L 1.796875 -4.359375 C 1.6875 -4.359375 1.671875 -4.375 1.671875 -4.484375 C 1.671875 -4.671875 1.734375 -5.515625 1.734375 -5.5625 C 1.734375 -5.640625 1.671875 -5.671875 1.625 -5.671875 C 1.578125 -5.671875 1.53125 -5.65625 1.515625 -5.609375 L 0.453125 -4.125 C 0.421875 -4.109375 0.40625 -4.0625 0.40625 -4.03125 Z M 0.40625 -4.03125 "/>
151</symbol>
152<symbol overflow="visible" id="glyph3-7">
153<path style="stroke:none;" d="M 0.296875 -4.3125 C 0.296875 -4.203125 0.3125 -4.15625 0.453125 -4.15625 L 0.546875 -4.15625 C 0.734375 -4.15625 0.734375 -4.15625 0.8125 -3.984375 C 1.28125 -2.765625 1.953125 -0.875 2.09375 -0.484375 C 2.171875 -0.234375 2.28125 0.296875 2.4375 0.296875 C 2.46875 0.296875 2.515625 0.265625 2.5625 0.21875 C 2.875 -0.25 2.953125 -0.21875 3.140625 -0.609375 C 3.671875 -1.71875 4.375 -3.578125 4.625 -4.046875 C 4.6875 -4.140625 4.6875 -4.15625 4.78125 -4.15625 L 4.96875 -4.15625 C 5.09375 -4.15625 5.109375 -4.203125 5.109375 -4.3125 C 5.109375 -4.4375 5.09375 -4.484375 4.984375 -4.484375 C 4.8125 -4.484375 4.640625 -4.453125 4.390625 -4.453125 C 4.15625 -4.453125 3.8125 -4.484375 3.71875 -4.484375 C 3.5625 -4.484375 3.546875 -4.421875 3.546875 -4.3125 C 3.546875 -4.203125 3.5625 -4.15625 3.703125 -4.15625 L 4.015625 -4.15625 C 4.09375 -4.15625 4.125 -4.09375 4.125 -3.96875 C 4.125 -3.59375 3.3125 -1.625 3.03125 -0.96875 C 2.984375 -0.84375 2.953125 -0.78125 2.921875 -0.78125 C 2.890625 -0.78125 2.84375 -0.828125 2.78125 -0.984375 C 2.4375 -1.78125 1.671875 -4.015625 1.671875 -4.0625 C 1.671875 -4.15625 1.765625 -4.15625 1.890625 -4.15625 L 2.234375 -4.15625 C 2.359375 -4.15625 2.375 -4.203125 2.375 -4.3125 C 2.375 -4.4375 2.375 -4.484375 2.234375 -4.484375 C 2.015625 -4.484375 1.53125 -4.453125 1.234375 -4.453125 C 0.890625 -4.453125 0.671875 -4.484375 0.453125 -4.484375 C 0.296875 -4.484375 0.296875 -4.421875 0.296875 -4.3125 Z M 0.296875 -4.3125 "/>
154</symbol>
155<symbol overflow="visible" id="glyph3-8">
156<path style="stroke:none;" d="M 0.296875 -4.1875 C 0.296875 -4.15625 0.3125 -4.140625 0.34375 -4.140625 C 0.390625 -4.140625 0.890625 -4.15625 0.921875 -4.15625 C 1.046875 -4.15625 1.0625 -4.15625 1.078125 -3.96875 C 1.109375 -3.125 1.125 -2.28125 1.125 -1.46875 C 1.125 -1.109375 1.125 -0.78125 1.109375 -0.4375 C 1.109375 -0.3125 1.109375 -0.296875 0.984375 -0.296875 L 0.5 -0.296875 C 0.359375 -0.296875 0.34375 -0.25 0.34375 -0.140625 C 0.34375 -0.015625 0.34375 0.03125 0.46875 0.03125 C 0.6875 0.03125 1.21875 0 1.515625 0 C 1.8125 0 2.28125 0.03125 2.5 0.03125 C 2.625 0.03125 2.625 -0.03125 2.625 -0.140625 C 2.625 -0.25 2.609375 -0.296875 2.5 -0.296875 L 2.078125 -0.296875 C 1.953125 -0.296875 1.953125 -0.328125 1.953125 -0.4375 C 1.921875 -1.109375 1.921875 -1.765625 1.921875 -2.421875 L 1.921875 -4.421875 C 1.921875 -4.484375 1.90625 -4.484375 1.84375 -4.484375 C 1.78125 -4.484375 0.734375 -4.4375 0.515625 -4.4375 C 0.375 -4.421875 0.390625 -4.4375 0.34375 -4.34375 C 0.296875 -4.25 0.296875 -4.21875 0.296875 -4.1875 Z M 0.90625 -6.484375 C 0.90625 -6.15625 1.140625 -6 1.390625 -6 C 1.71875 -6 2.09375 -6.265625 2.09375 -6.65625 C 2.09375 -7 1.859375 -7.125 1.609375 -7.125 C 1.328125 -7.125 0.90625 -6.90625 0.90625 -6.484375 Z M 0.90625 -6.484375 "/>
157</symbol>
158<symbol overflow="visible" id="glyph3-9">
159<path style="stroke:none;" d="M 0.234375 -7.5625 C 0.234375 -7.53125 0.25 -7.53125 0.328125 -7.53125 C 0.375 -7.53125 0.828125 -7.578125 0.890625 -7.578125 C 1.015625 -7.578125 1 -7.546875 1.015625 -7.34375 C 1.109375 -6.3125 1.15625 -1.859375 1.15625 -1.296875 C 1.15625 -1 1.15625 -0.296875 1.109375 -0.296875 L 0.5 -0.296875 C 0.375 -0.296875 0.359375 -0.25 0.359375 -0.140625 C 0.359375 -0.015625 0.359375 0.03125 0.5 0.03125 C 0.859375 0.03125 1.296875 0 1.59375 0 C 1.9375 0 2.296875 0.03125 2.515625 0.03125 C 2.671875 0.03125 2.671875 -0.03125 2.671875 -0.140625 C 2.671875 -0.25 2.65625 -0.296875 2.515625 -0.296875 L 2.0625 -0.296875 C 1.96875 -0.296875 1.96875 -0.484375 1.96875 -0.75 C 1.96875 -3.109375 1.90625 -4.171875 1.90625 -7.765625 C 1.90625 -7.90625 1.90625 -7.953125 1.8125 -7.953125 C 1.75 -7.953125 0.84375 -7.875 0.375 -7.84375 C 0.265625 -7.828125 0.28125 -7.84375 0.265625 -7.75 C 0.25 -7.671875 0.234375 -7.59375 0.234375 -7.5625 Z M 0.234375 -7.5625 "/>
160</symbol>
161<symbol overflow="visible" id="glyph3-10">
162<path style="stroke:none;" d="M 0.0625 -7.484375 C 0.0625 -7.4375 0.078125 -7.421875 0.125 -7.421875 C 0.171875 -7.421875 0.796875 -7.484375 0.84375 -7.484375 C 1 -7.484375 1.046875 -2.703125 1.046875 -2.3125 C 1.046875 -1.53125 0.984375 -0.078125 0.984375 -0.015625 C 0.984375 0.09375 1.03125 0.140625 1.125 0.140625 C 1.25 0.140625 1.46875 -0.078125 1.703125 -0.078125 C 2.03125 -0.078125 2.328125 0.15625 2.75 0.15625 C 4.078125 0.15625 5.328125 -0.6875 5.328125 -2.203125 C 5.328125 -3.484375 4.40625 -4.53125 3.078125 -4.53125 C 2.5 -4.53125 1.859375 -4.171875 1.828125 -4.171875 C 1.8125 -4.171875 1.8125 -4.34375 1.8125 -4.625 C 1.8125 -5.578125 1.859375 -7.75 1.859375 -7.75 C 1.859375 -7.8125 1.859375 -7.921875 1.78125 -7.921875 C 1.71875 -7.921875 0.6875 -7.796875 0.125 -7.734375 C 0.078125 -7.734375 0.0625 -7.5625 0.0625 -7.484375 Z M 1.796875 -0.75 C 1.796875 -1.140625 1.8125 -2.703125 1.8125 -3.890625 C 1.8125 -3.953125 2.21875 -4.1875 2.609375 -4.1875 C 3.640625 -4.1875 4.484375 -3.234375 4.484375 -2.1875 C 4.484375 -1.15625 3.875 -0.171875 2.78125 -0.171875 C 2.453125 -0.171875 1.796875 -0.171875 1.796875 -0.75 Z M 1.796875 -0.75 "/>
163</symbol>
164</g>
165</defs>
166<g id="surface1">
167<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10 15 L 738 15 L 738 95.5 L 10 95.5 Z M 10 15 "/>
168<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
169 <use xlink:href="#glyph0-1" x="25" y="46.171875"/>
170 <use xlink:href="#glyph0-2" x="39" y="46.171875"/>
171 <use xlink:href="#glyph0-3" x="49" y="46.171875"/>
172 <use xlink:href="#glyph0-4" x="59" y="46.171875"/>
173 <use xlink:href="#glyph0-5" x="75" y="46.171875"/>
174 <use xlink:href="#glyph0-6" x="88" y="46.171875"/>
175</g>
176<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
177 <use xlink:href="#glyph1-1" x="182.5" y="70.957031"/>
178 <use xlink:href="#glyph1-2" x="189.5" y="70.957031"/>
179 <use xlink:href="#glyph1-3" x="196.5" y="70.957031"/>
180 <use xlink:href="#glyph1-4" x="203.5" y="70.957031"/>
181 <use xlink:href="#glyph1-5" x="210.5" y="70.957031"/>
182 <use xlink:href="#glyph1-6" x="217.5" y="70.957031"/>
183 <use xlink:href="#glyph1-7" x="224.5" y="70.957031"/>
184 <use xlink:href="#glyph1-8" x="231.5" y="70.957031"/>
185 <use xlink:href="#glyph1-9" x="238.5" y="70.957031"/>
186 <use xlink:href="#glyph1-10" x="245.5" y="70.957031"/>
187 <use xlink:href="#glyph1-11" x="252.5" y="70.957031"/>
188</g>
189<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10 110.5 L 738 110.5 L 738 201 L 10 201 Z M 10 110.5 "/>
190<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
191 <use xlink:href="#glyph0-7" x="25" y="141.671875"/>
192 <use xlink:href="#glyph0-8" x="43" y="141.671875"/>
193 <use xlink:href="#glyph0-2" x="51" y="141.671875"/>
194 <use xlink:href="#glyph0-9" x="61" y="141.671875"/>
195 <use xlink:href="#glyph0-10" x="73" y="141.671875"/>
196 <use xlink:href="#glyph0-11" x="85" y="141.671875"/>
197 <use xlink:href="#glyph0-2" x="102" y="141.671875"/>
198 <use xlink:href="#glyph0-12" x="112" y="141.671875"/>
199 <use xlink:href="#glyph0-12" x="129" y="141.671875"/>
200 <use xlink:href="#glyph0-13" x="146" y="141.671875"/>
201 <use xlink:href="#glyph0-14" x="152" y="141.671875"/>
202</g>
203<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
204 <use xlink:href="#glyph1-2" x="160" y="166.457031"/>
205 <use xlink:href="#glyph1-12" x="167" y="166.457031"/>
206 <use xlink:href="#glyph1-13" x="174" y="166.457031"/>
207 <use xlink:href="#glyph1-13" x="181" y="166.457031"/>
208 <use xlink:href="#glyph1-4" x="188" y="166.457031"/>
209 <use xlink:href="#glyph1-3" x="195" y="166.457031"/>
210 <use xlink:href="#glyph1-6" x="202" y="166.457031"/>
211 <use xlink:href="#glyph1-14" x="209" y="166.457031"/>
212 <use xlink:href="#glyph1-7" x="216" y="166.457031"/>
213 <use xlink:href="#glyph1-8" x="223" y="166.457031"/>
214 <use xlink:href="#glyph1-9" x="230" y="166.457031"/>
215 <use xlink:href="#glyph1-15" x="237" y="166.457031"/>
216 <use xlink:href="#glyph1-10" x="244" y="166.457031"/>
217 <use xlink:href="#glyph1-11" x="251" y="166.457031"/>
218</g>
219<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10 216 L 738 216 L 738 336.5 L 10 336.5 Z M 10 216 "/>
220<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
221 <use xlink:href="#glyph0-15" x="25" y="247.171875"/>
222 <use xlink:href="#glyph0-13" x="43" y="247.171875"/>
223 <use xlink:href="#glyph0-16" x="49" y="247.171875"/>
224 <use xlink:href="#glyph0-17" x="57" y="247.171875"/>
225 <use xlink:href="#glyph0-1" x="68" y="247.171875"/>
226 <use xlink:href="#glyph0-2" x="82" y="247.171875"/>
227 <use xlink:href="#glyph0-3" x="92" y="247.171875"/>
228</g>
229<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
230 <use xlink:href="#glyph1-14" x="190" y="271.957031"/>
231 <use xlink:href="#glyph1-4" x="197" y="271.957031"/>
232 <use xlink:href="#glyph1-15" x="204" y="271.957031"/>
233 <use xlink:href="#glyph1-16" x="211" y="271.957031"/>
234 <use xlink:href="#glyph1-11" x="218" y="271.957031"/>
235 <use xlink:href="#glyph1-17" x="225" y="271.957031"/>
236 <use xlink:href="#glyph1-12" x="232" y="271.957031"/>
237 <use xlink:href="#glyph1-18" x="239" y="271.957031"/>
238 <use xlink:href="#glyph1-10" x="246" y="271.957031"/>
239 <use xlink:href="#glyph1-11" x="253" y="271.957031"/>
240</g>
241<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:2;stroke-miterlimit:10;" d="M 265 192 L 265 204 L 539.800781 237.5 L 539.800781 249.5 "/>
242<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:2;stroke-miterlimit:10;" d="M 723 192 L 723 204 L 631.398438 237.5 L 631.398438 249.5 "/>
243<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10 351.5 L 738 351.5 L 738 468.5 L 10 468.5 Z M 10 351.5 "/>
244<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
245 <use xlink:href="#glyph0-4" x="25" y="382.671875"/>
246 <use xlink:href="#glyph0-10" x="41" y="382.671875"/>
247 <use xlink:href="#glyph0-10" x="53" y="382.671875"/>
248 <use xlink:href="#glyph0-18" x="65" y="382.671875"/>
249 <use xlink:href="#glyph0-13" x="71" y="382.671875"/>
250 <use xlink:href="#glyph0-19" x="77" y="382.671875"/>
251 <use xlink:href="#glyph0-8" x="87" y="382.671875"/>
252</g>
253<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
254 <use xlink:href="#glyph1-14" x="190" y="443.957031"/>
255 <use xlink:href="#glyph1-4" x="197" y="443.957031"/>
256 <use xlink:href="#glyph1-15" x="204" y="443.957031"/>
257 <use xlink:href="#glyph1-16" x="211" y="443.957031"/>
258 <use xlink:href="#glyph1-11" x="218" y="443.957031"/>
259 <use xlink:href="#glyph1-14" x="225" y="443.957031"/>
260 <use xlink:href="#glyph1-1" x="232" y="443.957031"/>
261 <use xlink:href="#glyph1-3" x="239" y="443.957031"/>
262 <use xlink:href="#glyph1-1" x="246" y="443.957031"/>
263 <use xlink:href="#glyph1-10" x="253" y="443.957031"/>
264</g>
265<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:2;stroke-miterlimit:10;" d="M 356.601562 327.5 L 356.601562 339.5 L 402.398438 358.5 L 402.398438 370.5 "/>
266<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:2;stroke-miterlimit:10;" d="M 631.398438 327.5 L 631.398438 339.5 L 585.601562 358.5 L 585.601562 370.5 "/>
267<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
268 <use xlink:href="#glyph2-1" x="315" y="168.992188"/>
269 <use xlink:href="#glyph2-2" x="327" y="168.992188"/>
270</g>
271<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
272 <use xlink:href="#glyph2-1" x="481" y="168.992188"/>
273 <use xlink:href="#glyph2-2" x="493" y="168.992188"/>
274</g>
275<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
276 <use xlink:href="#glyph2-1" x="587" y="168.992188"/>
277 <use xlink:href="#glyph2-2" x="599" y="168.992188"/>
278</g>
279<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 265 296.5 L 265 306.5 "/>
280<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 265 301.5 L 723 301.5 "/>
281<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.601562 296.5 L 356.601562 306.5 "/>
282<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
283 <use xlink:href="#glyph3-1" x="291.113281" y="314.585938"/>
284 <use xlink:href="#glyph3-2" x="297.113281" y="314.585938"/>
285 <use xlink:href="#glyph3-3" x="302.113281" y="314.585938"/>
286 <use xlink:href="#glyph3-4" x="307.113281" y="314.585938"/>
287 <use xlink:href="#glyph3-2" x="313.113281" y="314.585938"/>
288 <use xlink:href="#glyph3-5" x="318.113281" y="314.585938"/>
289</g>
290<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 631.398438 296.5 L 631.398438 306.5 "/>
291<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
292 <use xlink:href="#glyph3-4" x="481.34375" y="314.585938"/>
293 <use xlink:href="#glyph3-3" x="487.34375" y="314.585938"/>
294 <use xlink:href="#glyph3-6" x="492.34375" y="314.585938"/>
295 <use xlink:href="#glyph3-3" x="495.34375" y="314.585938"/>
296</g>
297<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 723 296.5 L 723 306.5 "/>
298<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
299 <use xlink:href="#glyph3-3" x="652.355469" y="314.585938"/>
300 <use xlink:href="#glyph3-7" x="657.355469" y="314.585938"/>
301 <use xlink:href="#glyph3-3" x="662.355469" y="314.585938"/>
302 <use xlink:href="#glyph3-8" x="667.355469" y="314.585938"/>
303 <use xlink:href="#glyph3-9" x="670.355469" y="314.585938"/>
304 <use xlink:href="#glyph3-3" x="673.355469" y="314.585938"/>
305 <use xlink:href="#glyph3-10" x="678.355469" y="314.585938"/>
306 <use xlink:href="#glyph3-9" x="684.355469" y="314.585938"/>
307 <use xlink:href="#glyph3-2" x="687.355469" y="314.585938"/>
308</g>
309<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 265 427.5 L 723 427.5 L 723 453.5 L 265 453.5 Z M 265 427.5 "/>
310<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 265 54.5 L 285 54.5 L 285 80.5 L 265 80.5 Z M 265 54.5 "/>
311<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 285 54.5 L 305 54.5 L 305 80.5 L 285 80.5 Z M 285 54.5 "/>
312<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 305 54.5 L 325 54.5 L 325 80.5 L 305 80.5 Z M 305 54.5 "/>
313<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 325 54.5 L 345 54.5 L 345 80.5 L 325 80.5 Z M 325 54.5 "/>
314<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 345 54.5 L 365 54.5 L 365 80.5 L 345 80.5 Z M 345 54.5 "/>
315<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 275 140 L 265 140 L 265 186 L 275 186 "/>
316<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 713 140 L 723 140 L 723 186 L 713 186 "/>
317<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 265 255.5 L 356.601562 255.5 L 356.601562 281.5 L 265 281.5 Z M 265 255.5 "/>
318<path style="fill-rule:nonzero;fill:rgb(80%,80%,80%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.601562 255.5 L 448.203125 255.5 L 448.203125 281.5 L 356.601562 281.5 Z M 356.601562 255.5 "/>
319<path style="fill-rule:nonzero;fill:rgb(80%,80%,80%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 448.199219 255.5 L 539.800781 255.5 L 539.800781 281.5 L 448.199219 281.5 Z M 448.199219 255.5 "/>
320<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 539.800781 255.5 L 544.890625 255.5 L 544.890625 281.5 L 539.800781 281.5 Z M 539.800781 255.5 "/>
321<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 544.890625 255.5 L 549.980469 255.5 L 549.980469 281.5 L 544.890625 281.5 Z M 544.890625 255.5 "/>
322<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 549.976562 255.5 L 555.066406 255.5 L 555.066406 281.5 L 549.976562 281.5 Z M 549.976562 255.5 "/>
323<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.066406 255.5 L 560.15625 255.5 L 560.15625 281.5 L 555.066406 281.5 Z M 555.066406 255.5 "/>
324<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 560.15625 255.5 L 565.246094 255.5 L 565.246094 281.5 L 560.15625 281.5 Z M 560.15625 255.5 "/>
325<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 565.246094 255.5 L 570.335938 255.5 L 570.335938 281.5 L 565.246094 281.5 Z M 565.246094 255.5 "/>
326<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 570.332031 255.5 L 575.421875 255.5 L 575.421875 281.5 L 570.332031 281.5 Z M 570.332031 255.5 "/>
327<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 575.421875 255.5 L 580.511719 255.5 L 580.511719 281.5 L 575.421875 281.5 Z M 575.421875 255.5 "/>
328<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 580.511719 255.5 L 585.601562 255.5 L 585.601562 281.5 L 580.511719 281.5 Z M 580.511719 255.5 "/>
329<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 585.601562 255.5 L 590.691406 255.5 L 590.691406 281.5 L 585.601562 281.5 Z M 585.601562 255.5 "/>
330<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 590.6875 255.5 L 595.777344 255.5 L 595.777344 281.5 L 590.6875 281.5 Z M 590.6875 255.5 "/>
331<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 595.777344 255.5 L 600.867188 255.5 L 600.867188 281.5 L 595.777344 281.5 Z M 595.777344 255.5 "/>
332<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 600.867188 255.5 L 605.957031 255.5 L 605.957031 281.5 L 600.867188 281.5 Z M 600.867188 255.5 "/>
333<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 605.957031 255.5 L 611.046875 255.5 L 611.046875 281.5 L 605.957031 281.5 Z M 605.957031 255.5 "/>
334<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 611.042969 255.5 L 616.132812 255.5 L 616.132812 281.5 L 611.042969 281.5 Z M 611.042969 255.5 "/>
335<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 616.132812 255.5 L 621.222656 255.5 L 621.222656 281.5 L 616.132812 281.5 Z M 616.132812 255.5 "/>
336<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 621.222656 255.5 L 626.3125 255.5 L 626.3125 281.5 L 621.222656 281.5 Z M 621.222656 255.5 "/>
337<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 626.3125 255.5 L 631.402344 255.5 L 631.402344 281.5 L 626.3125 281.5 Z M 626.3125 255.5 "/>
338<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 631.398438 255.5 L 723 255.5 L 723 281.5 L 631.398438 281.5 Z M 631.398438 255.5 "/>
339<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 275 150 L 295 150 L 295 176 L 275 176 Z M 275 150 "/>
340<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 295 150 L 315 150 L 315 176 L 295 176 Z M 295 150 "/>
341<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 341 150 L 361 150 L 361 176 L 341 176 Z M 341 150 "/>
342<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 361 150 L 381 150 L 381 176 L 361 176 Z M 361 150 "/>
343<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 381 150 L 401 150 L 401 176 L 381 176 Z M 381 150 "/>
344<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 401 150 L 421 150 L 421 176 L 401 176 Z M 401 150 "/>
345<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 421 150 L 441 150 L 441 176 L 421 176 Z M 421 150 "/>
346<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 441 150 L 461 150 L 461 176 L 441 176 Z M 441 150 "/>
347<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 461 150 L 481 150 L 481 176 L 461 176 Z M 461 150 "/>
348<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 507 150 L 527 150 L 527 176 L 507 176 Z M 507 150 "/>
349<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 527 150 L 547 150 L 547 176 L 527 176 Z M 527 150 "/>
350<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 547 150 L 567 150 L 567 176 L 547 176 Z M 547 150 "/>
351<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 567 150 L 587 150 L 587 176 L 567 176 Z M 567 150 "/>
352<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613 150 L 633 150 L 633 176 L 613 176 Z M 613 150 "/>
353<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 633 150 L 653 150 L 653 176 L 633 176 Z M 633 150 "/>
354<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 653 150 L 673 150 L 673 176 L 653 176 Z M 653 150 "/>
355<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 673 150 L 693 150 L 693 176 L 673 176 Z M 673 150 "/>
356<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 693 150 L 713 150 L 713 176 L 693 176 Z M 693 150 "/>
357<path style="fill-rule:nonzero;fill:rgb(80%,80%,80%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 402.398438 376.5 L 494 376.5 L 494 402.5 L 402.398438 402.5 Z M 402.398438 376.5 "/>
358<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 494 376.5 L 499.089844 376.5 L 499.089844 402.5 L 494 402.5 Z M 494 376.5 "/>
359<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 499.089844 376.5 L 504.179688 376.5 L 504.179688 402.5 L 499.089844 402.5 Z M 499.089844 376.5 "/>
360<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 504.179688 376.5 L 509.269531 376.5 L 509.269531 402.5 L 504.179688 402.5 Z M 504.179688 376.5 "/>
361<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 509.265625 376.5 L 514.355469 376.5 L 514.355469 402.5 L 509.265625 402.5 Z M 509.265625 376.5 "/>
362<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 514.355469 376.5 L 519.445312 376.5 L 519.445312 402.5 L 514.355469 402.5 Z M 514.355469 376.5 "/>
363<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 519.445312 376.5 L 524.535156 376.5 L 524.535156 402.5 L 519.445312 402.5 Z M 519.445312 376.5 "/>
364<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.535156 376.5 L 529.625 376.5 L 529.625 402.5 L 524.535156 402.5 Z M 524.535156 376.5 "/>
365<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 529.621094 376.5 L 534.710938 376.5 L 534.710938 402.5 L 529.621094 402.5 Z M 529.621094 376.5 "/>
366<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 534.710938 376.5 L 539.800781 376.5 L 539.800781 402.5 L 534.710938 402.5 Z M 534.710938 376.5 "/>
367<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 539.800781 376.5 L 544.890625 376.5 L 544.890625 402.5 L 539.800781 402.5 Z M 539.800781 376.5 "/>
368<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 544.890625 376.5 L 549.980469 376.5 L 549.980469 402.5 L 544.890625 402.5 Z M 544.890625 376.5 "/>
369<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 549.976562 376.5 L 555.066406 376.5 L 555.066406 402.5 L 549.976562 402.5 Z M 549.976562 376.5 "/>
370<path style="fill-rule:nonzero;fill:rgb(50%,50%,50%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.066406 376.5 L 560.15625 376.5 L 560.15625 402.5 L 555.066406 402.5 Z M 555.066406 376.5 "/>
371<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 560.15625 376.5 L 565.246094 376.5 L 565.246094 402.5 L 560.15625 402.5 Z M 560.15625 376.5 "/>
372<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 565.246094 376.5 L 570.335938 376.5 L 570.335938 402.5 L 565.246094 402.5 Z M 565.246094 376.5 "/>
373<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 570.332031 376.5 L 575.421875 376.5 L 575.421875 402.5 L 570.332031 402.5 Z M 570.332031 376.5 "/>
374<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 575.421875 376.5 L 580.511719 376.5 L 580.511719 402.5 L 575.421875 402.5 Z M 575.421875 376.5 "/>
375<path style="fill-rule:nonzero;fill:rgb(35%,35%,100%);fill-opacity:1;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 580.511719 376.5 L 585.601562 376.5 L 585.601562 402.5 L 580.511719 402.5 Z M 580.511719 376.5 "/>
376</g>
377</svg>
diff --git a/z3-solver/Cargo.toml b/z3-solver/Cargo.toml
new file mode 100644
index 0000000..6f63e1c
--- /dev/null
+++ b/z3-solver/Cargo.toml
@@ -0,0 +1,12 @@
1[package]
2name = "diaphragm-z3-solver"
3version = "0.1.0"
4authors = ["Minijackson <minijackson@riseup.net>"]
5edition = "2021"
6
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
9[dependencies]
10diaphragm-core = { path = "../core" }
11
12z3 = "0.9"
diff --git a/z3-solver/src/lib.rs b/z3-solver/src/lib.rs
new file mode 100644
index 0000000..04d77eb
--- /dev/null
+++ b/z3-solver/src/lib.rs
@@ -0,0 +1,691 @@
1pub use z3;
2
3use diaphragm_core::{
4 solving::VariableHandle,
5 types::{Bool, Float},
6 SolverContext, SolverModel,
7};
8
9use z3::ast::Ast;
10
11use std::collections::HashMap;
12
13#[derive(Debug)]
14pub struct Z3Context<'z3> {
15 ctx: &'z3 z3::Context,
16 solver: z3::Solver<'z3>,
17
18 floats: HashMap<VariableHandle, z3::ast::Real<'z3>>,
19 max_float_id: u32,
20
21 bools: HashMap<VariableHandle, z3::ast::Bool<'z3>>,
22 pub max_bool_id: u32,
23}
24
25impl Drop for Z3Context<'_> {
26 fn drop(&mut self) {
27 eprintln!("bool: {}", self.max_bool_id);
28 eprintln!("float: {}", self.max_float_id);
29 }
30}
31
32fn value_to_num_den(value: f64) -> (i32, i32) {
33 let fract = value.fract();
34 let number_of_fract_digits = -fract.log10().floor();
35
36 if number_of_fract_digits >= 1. && !number_of_fract_digits.is_infinite() {
37 let den = 10f64.powf(number_of_fract_digits);
38 ((value * den) as i32, den as i32)
39 } else {
40 (value as i32, 1)
41 }
42}
43
44impl<'z3> Z3Context<'z3> {
45 pub fn new(ctx: &'z3 z3::Context) -> Self {
46 Self {
47 ctx,
48 solver: z3::Solver::new(&ctx),
49 floats: HashMap::new(),
50 max_float_id: 0,
51 bools: HashMap::new(),
52 max_bool_id: 0,
53 }
54 }
55
56 fn anon_float(&mut self, f: z3::ast::Real<'z3>) -> Float {
57 self.max_float_id += 1;
58 let id = self.max_float_id;
59 let handle = VariableHandle::new(id as usize);
60 self.floats.insert(handle, f);
61 Float::from_handle(handle)
62 }
63
64 fn anon_bool(&mut self, f: z3::ast::Bool<'z3>) -> Bool {
65 self.max_bool_id += 1;
66 let id = self.max_bool_id;
67 let handle = VariableHandle::new(id as usize);
68 self.bools.insert(handle, dbg!(f));
69 Bool::new(handle)
70 }
71
72 /*
73 fn float_handle(&mut self, f: Float) -> VariableHandle {
74 match f {
75 Float::Fixed(value) => {
76 let new_float = self.new_fixed_float(value);
77 self.float_handle(new_float)
78 }
79 Float::Variable(handle) => handle,
80 }
81 }
82 */
83
84 fn float(&self, f: Float) -> z3::ast::Real<'z3> {
85 let handle = match f {
86 Float::Fixed(value) => {
87 let (num, den) = value_to_num_den(value);
88 return z3::ast::Real::from_real(&self.ctx, num, den);
89 }
90 Float::Variable(handle) => handle,
91 };
92
93 self.floats
94 .get(&handle)
95 .expect("Couldn't get float")
96 .clone()
97 }
98
99 fn bool(&self, f: Bool) -> &z3::ast::Bool<'z3> {
100 self.bools.get(&f.handle()).expect("Couldn't get float")
101 }
102}
103
104impl<'z3> SolverContext for Z3Context<'z3> {
105 fn solve<'a>(&'a self) -> Box<dyn SolverModel + 'a> {
106 match self.solver.check() {
107 z3::SatResult::Unsat | z3::SatResult::Unknown => panic!("Failed solving"),
108 z3::SatResult::Sat => {}
109 }
110 Box::new(Z3Model {
111 ctx: self,
112 model: self.solver.get_model().unwrap(),
113 })
114 }
115
116 fn constrain(&mut self, assertion: Bool) {
117 self.solver.assert(
118 self.bools
119 .get(&assertion.handle())
120 .expect("Couldn't get bool"),
121 );
122 }
123
124 // Floats
125
126 fn new_free_float(&mut self) -> Float {
127 self.max_float_id += 1;
128 let id = self.max_float_id;
129 let handle = VariableHandle::new(id as usize);
130 self.floats
131 .insert(handle, z3::ast::Real::new_const(&self.ctx, id));
132 Float::from_handle(handle)
133 }
134
135 fn new_fixed_float(&mut self, value: f64) -> Float {
136 self.max_float_id += 1;
137 let id = self.max_float_id;
138 let handle = VariableHandle::new(id as usize);
139
140 let (num, den) = value_to_num_den(value);
141
142 self.floats
143 .insert(handle, z3::ast::Real::from_real(&self.ctx, num, den));
144 Float::from_handle(handle)
145 }
146
147 // TODO: that's a lot of copying things
148
149 fn float_add(&mut self, values: &[Float]) -> Float {
150 let values = values.iter().map(|f| self.float(*f)).collect::<Vec<_>>();
151 let result = z3::ast::Real::add(
152 self.ctx,
153 &values.iter().collect::<Vec<_>>()
154 );
155
156 self.anon_float(result)
157 }
158
159 fn float_sub(&mut self, values: &[Float]) -> Float {
160 let values = values.iter().map(|f| self.float(*f)).collect::<Vec<_>>();
161 let result = z3::ast::Real::sub(
162 self.ctx,
163 &values.iter().collect::<Vec<_>>()
164 );
165
166 self.anon_float(result)
167 }
168
169 fn float_mul(&mut self, values: &[Float]) -> Float {
170 let values = values.iter().map(|f| self.float(*f)).collect::<Vec<_>>();
171 let result = z3::ast::Real::mul(
172 self.ctx,
173 &values.iter().collect::<Vec<_>>()
174 );
175
176 self.anon_float(result)
177 }
178
179 fn float_div(&mut self, lhs: Float, rhs: Float) -> Float {
180 let lhs = self.float(lhs);
181 let rhs = self.float(rhs);
182 let result = lhs.div(&rhs);
183 self.anon_float(result)
184 }
185
186 fn float_neg(&mut self, value: Float) -> Float {
187 self.anon_float(self.float(value).unary_minus())
188 }
189
190 fn float_eq(&mut self, lhs: Float, rhs: Float) -> Bool {
191 let lhs = self.float(lhs);
192 let rhs = self.float(rhs);
193 let result = lhs._eq(&rhs);
194 self.anon_bool(result)
195 }
196
197 fn float_ne(&mut self, lhs: Float, rhs: Float) -> Bool {
198 let lhs = self.float(lhs);
199 let rhs = self.float(rhs);
200 let result = lhs._eq(&rhs).not();
201 self.anon_bool(result)
202 }
203
204 fn float_gt(&mut self, lhs: Float, rhs: Float) -> Bool {
205 let lhs = self.float(lhs);
206 let rhs = self.float(rhs);
207 let result = lhs.gt(&rhs);
208 self.anon_bool(result)
209 }
210
211 fn float_ge(&mut self, lhs: Float, rhs: Float) -> Bool {
212 let lhs = self.float(lhs);
213 let rhs = self.float(rhs);
214 let result = lhs.ge(&rhs);
215 self.anon_bool(result)
216 }
217
218 fn float_lt(&mut self, lhs: Float, rhs: Float) -> Bool {
219 let lhs = self.float(lhs);
220 let rhs = self.float(rhs);
221 let result = lhs.lt(&rhs);
222 self.anon_bool(result)
223 }
224
225 fn float_le(&mut self, lhs: Float, rhs: Float) -> Bool {
226 let lhs = self.float(lhs);
227 let rhs = self.float(rhs);
228 let result = lhs.le(&rhs);
229 self.anon_bool(result)
230 }
231
232 // Bools
233
234 fn new_free_bool(&mut self) -> Bool {
235 self.max_bool_id += 1;
236 let id = self.max_bool_id;
237 let handle = VariableHandle::new(id as usize);
238 self.bools
239 .insert(handle, z3::ast::Bool::new_const(&self.ctx, id));
240 Bool::new(handle)
241 }
242
243 fn new_fixed_bool(&mut self, value: bool) -> Bool {
244 self.max_bool_id += 1;
245 let id = self.max_bool_id;
246 let handle = VariableHandle::new(id as usize);
247
248 self.bools
249 .insert(handle, z3::ast::Bool::from_bool(&self.ctx, value));
250 Bool::new(handle)
251 }
252
253 fn bool_eq(&mut self, lhs: Bool, rhs: Bool) -> Bool {
254 let lhs = self.bool(lhs);
255 let rhs = self.bool(rhs);
256 let result = lhs._eq(&rhs);
257 self.anon_bool(result)
258 }
259
260 fn bool_ne(&mut self, lhs: Bool, rhs: Bool) -> Bool {
261 let lhs = self.bool(lhs);
262 let rhs = self.bool(rhs);
263 let result = lhs._eq(&rhs).not();
264 self.anon_bool(result)
265 }
266
267 fn bool_and(&mut self, values: &[Bool]) -> Bool {
268 let result = z3::ast::Bool::and(
269 self.ctx,
270 &values.iter().map(|b| self.bool(*b)).collect::<Vec<_>>(),
271 );
272
273 self.anon_bool(result)
274 }
275
276 fn bool_or(&mut self, values: &[Bool]) -> Bool {
277 let result = z3::ast::Bool::or(
278 self.ctx,
279 &values.iter().map(|b| self.bool(*b)).collect::<Vec<_>>(),
280 );
281
282 self.anon_bool(result)
283 }
284
285 fn bool_not(&mut self, value: Bool) -> Bool {
286 self.anon_bool(self.bool(value).not())
287 }
288
289 fn bool_implies(&mut self, lhs: Bool, rhs: Bool) -> Bool {
290 let lhs = self.bool(lhs);
291 let rhs = self.bool(rhs);
292 let result = lhs.implies(rhs);
293 self.anon_bool(result)
294 }
295}
296
297pub struct Z3Model<'z3> {
298 ctx: &'z3 Z3Context<'z3>,
299 model: z3::Model<'z3>,
300}
301
302impl SolverModel for Z3Model<'_> {
303 fn eval_float(&self, f: Float) -> Option<f64> {
304 let handle = match f {
305 Float::Fixed(value) => return Some(value),
306 Float::Variable(handle) => handle,
307 };
308
309 let (num, den) = self
310 .model
311 .eval::<z3::ast::Real>(self.ctx.floats.get(&handle).expect("Couldn't find float"))
312 .unwrap()
313 .as_real()
314 .unwrap();
315 // TODO: handle errors
316 Some(num as f64 / den as f64)
317 }
318
319 fn eval_bool(&self, f: Bool) -> Option<bool> {
320 Some(
321 self.model
322 .eval::<z3::ast::Bool>(&self.ctx.bool(f))
323 .unwrap()
324 .as_bool()
325 .unwrap(),
326 )
327 // TODO: handle errors
328 }
329}
330
331/*
332use std::cell::RefCell;
333use std::collections::HashMap;
334use std::rc::Rc;
335
336#[derive(Clone, Eq, PartialEq, Debug)]
337pub struct Z3Float<'z3> {
338 id: u32,
339 real: z3::ast::Real<'z3>,
340 ctx: Z3Context<'z3>,
341}
342
343// TODO: try to remove this clone?
344fn get_real<'z3>(f: &dyn VariableFloat, ctx: &Z3Context<'z3>) -> z3::ast::Real<'z3> {
345 let id = f.id() as u32;
346 ctx.0
347 .borrow()
348 .floats
349 .get(&id)
350 .expect("Couldn't find float")
351 .clone()
352}
353
354impl<'z3> VariableFloat<'z3> for Z3Float<'z3> {
355 fn id(&self) -> usize {
356 self.id as usize
357 }
358
359 fn dyn_clone(&self) -> Box<dyn VariableFloat<'z3> + 'z3> {
360 Box::new(Z3Float {
361 id: self.id,
362 real: self.real.clone(),
363 ctx: self.ctx.clone(),
364 })
365 }
366
367 fn eq(&self, other: &dyn VariableFloat) -> Bool<'z3> {
368 let other = get_real(other, &self.ctx);
369 let result = self.real._eq(&other);
370 let id = self.ctx.anon_bool(&result);
371
372 Bool::new(Box::new(Z3Bool {
373 id,
374 real: result,
375 ctx: self.ctx.clone(),
376 }))
377 }
378
379 fn neq(&self, other: &dyn VariableFloat) -> Bool<'z3> {
380 let other = get_real(other, &self.ctx);
381 let result = self.real._eq(&other).not();
382 let id = self.ctx.anon_bool(&result);
383
384 Bool::new(Box::new(Z3Bool {
385 id,
386 real: result,
387 ctx: self.ctx.clone(),
388 }))
389 }
390
391 fn gt(&self, other: &dyn VariableFloat) -> Bool<'z3> {
392 let other = get_real(other, &self.ctx);
393 let result = self.real.gt(&other);
394 let id = self.ctx.anon_bool(&result);
395
396 Bool::new(Box::new(Z3Bool {
397 id,
398 real: result,
399 ctx: self.ctx.clone(),
400 }))
401 }
402
403 fn ge(&self, other: &dyn VariableFloat) -> Bool<'z3> {
404 let other = get_real(other, &self.ctx);
405 let result = self.real.ge(&other);
406 let id = self.ctx.anon_bool(&result);
407
408 Bool::new(Box::new(Z3Bool {
409 id,
410 real: result,
411 ctx: self.ctx.clone(),
412 }))
413 }
414
415 fn lt(&self, other: &dyn VariableFloat) -> Bool<'z3> {
416 let other = get_real(other, &self.ctx);
417 let result = self.real.lt(&other);
418 let id = self.ctx.anon_bool(&result);
419
420 Bool::new(Box::new(Z3Bool {
421 id,
422 real: result,
423 ctx: self.ctx.clone(),
424 }))
425 }
426
427 fn le(&self, other: &dyn VariableFloat) -> Bool<'z3> {
428 let other = get_real(other, &self.ctx);
429 let result = self.real.le(&other);
430 let id = self.ctx.anon_bool(&result);
431
432 Bool::new(Box::new(Z3Bool {
433 id,
434 real: result,
435 ctx: self.ctx.clone(),
436 }))
437 }
438
439 fn add(&self, other: &dyn VariableFloat) -> Float<'z3> {
440 let other = get_real(other, &self.ctx);
441 let result = &self.real + &other;
442 let id = self.ctx.anon_float(&result);
443
444 Float::new(Box::new(Z3Float {
445 id,
446 real: result,
447 ctx: self.ctx.clone(),
448 }))
449 }
450
451 fn sub(&self, other: &dyn VariableFloat) -> Float<'z3> {
452 let other = get_real(other, &self.ctx);
453 let result = &self.real - &other;
454 let id = self.ctx.anon_float(&result);
455
456 Float::new(Box::new(Z3Float {
457 id,
458 real: result,
459 ctx: self.ctx.clone(),
460 }))
461 }
462
463 fn mul(&self, other: &dyn VariableFloat) -> Float<'z3> {
464 let other = get_real(other, &self.ctx);
465 let result = &self.real * &other;
466 let id = self.ctx.anon_float(&result);
467
468 Float::new(Box::new(Z3Float {
469 id,
470 real: result,
471 ctx: self.ctx.clone(),
472 }))
473 }
474
475 fn div(&self, other: &dyn VariableFloat) -> Float<'z3> {
476 let other = get_real(other, &self.ctx);
477 let result = &self.real / &other;
478 let id = self.ctx.anon_float(&result);
479
480 Float::new(Box::new(Z3Float {
481 id,
482 real: result,
483 ctx: self.ctx.clone(),
484 }))
485 }
486
487 fn neg(&self) -> Float<'z3> {
488 let result = self.real.unary_minus();
489 let id = self.ctx.anon_float(&result);
490
491 Float::new(Box::new(Z3Float {
492 id,
493 real: result,
494 ctx: self.ctx.clone(),
495 }))
496 }
497}
498
499#[derive(Clone, Eq, PartialEq, Debug)]
500pub struct Z3Bool<'z3> {
501 id: u32,
502 real: z3::ast::Bool<'z3>,
503 ctx: Z3Context<'z3>,
504}
505
506// TODO: try to remove this clone?
507fn get_bool<'z3>(f: &dyn VariableBool, ctx: &Z3Context<'z3>) -> z3::ast::Bool<'z3> {
508 let id = f.id() as u32;
509 ctx.0
510 .borrow()
511 .bools
512 .get(&id)
513 .expect("Couldn't find bool")
514 .clone()
515}
516
517impl<'z3> VariableBool<'z3> for Z3Bool<'z3> {
518 fn id(&self) -> usize {
519 self.id as usize
520 }
521
522 fn dyn_clone(&self) -> Box<dyn VariableBool<'z3> + 'z3> {
523 Box::new(Z3Bool {
524 id: self.id,
525 real: self.real.clone(),
526 ctx: self.ctx.clone(),
527 })
528 }
529
530 fn eq(&self, other: &dyn VariableBool) -> Bool<'z3> {
531 let other = get_bool(other, &self.ctx);
532 let result = self.real._eq(&other);
533 let id = self.ctx.anon_bool(&result);
534
535 Bool::new(Box::new(Z3Bool {
536 id,
537 real: result,
538 ctx: self.ctx.clone(),
539 }))
540 }
541
542 fn neq(&self, other: &dyn VariableBool) -> Bool<'z3> {
543 let other = get_bool(other, &self.ctx);
544 let result = self.real._eq(&other).not();
545 let id = self.ctx.anon_bool(&result);
546
547 Bool::new(Box::new(Z3Bool {
548 id,
549 real: result,
550 ctx: self.ctx.clone(),
551 }))
552 }
553
554 fn and(&self, other: &dyn VariableBool) -> Bool<'z3> {
555 let other = get_bool(other, &self.ctx);
556 let result = &self.real & &other;
557 let id = self.ctx.anon_bool(&result);
558
559 Bool::new(Box::new(Z3Bool {
560 id,
561 real: result,
562 ctx: self.ctx.clone(),
563 }))
564 }
565
566 fn or(&self, other: &dyn VariableBool) -> Bool<'z3> {
567 let other = get_bool(other, &self.ctx);
568 let result = &self.real | &other;
569 let id = self.ctx.anon_bool(&result);
570
571 Bool::new(Box::new(Z3Bool {
572 id,
573 real: result,
574 ctx: self.ctx.clone(),
575 }))
576 }
577
578 fn not(&self) -> Bool<'z3> {
579 let result = self.real.not();
580 let id = self.ctx.anon_bool(&result);
581
582 Bool::new(Box::new(Z3Bool {
583 id,
584 real: result,
585 ctx: self.ctx.clone(),
586 }))
587 }
588}
589
590#[derive(Clone, Eq, PartialEq, Debug)]
591pub struct Z3Context<'z3>(Rc<RefCell<Z3ContextImpl<'z3>>>);
592
593#[derive(Eq, PartialEq, Debug)]
594pub struct Z3ContextImpl<'z3> {
595 ctx: z3::Context,
596 floats: HashMap<u32, z3::ast::Real<'z3>>,
597 max_float_id: u32,
598 bools: HashMap<u32, z3::ast::Bool<'z3>>,
599 max_bool_id: u32,
600}
601
602impl<'z3> Z3Context<'z3> {
603 pub fn new() -> Self {
604 let conf = z3::Config::new();
605 let ctx = z3::Context::new(&conf);
606 Z3Context(Rc::new(RefCell::new(Z3ContextImpl {
607 ctx,
608 floats: HashMap::new(),
609 max_float_id: 0,
610 bools: HashMap::new(),
611 max_bool_id: 0,
612 })))
613 }
614
615 fn anon_float(&self, f: &z3::ast::Real<'z3>) -> u32 {
616 let mut ctx = self.0.borrow_mut();
617
618 ctx.max_float_id += 1;
619 let id = ctx.max_float_id;
620 ctx.floats.insert(id, f.clone());
621 id
622 }
623
624 fn anon_bool(&self, f: &z3::ast::Bool<'z3>) -> u32 {
625 let mut ctx = self.0.borrow_mut();
626
627 ctx.max_float_id += 1;
628 let id = ctx.max_float_id;
629 ctx.bools.insert(id, f.clone());
630 id
631 }
632}
633
634impl<'z3> SolverContext<'z3> for Z3Context<'z3> {
635 fn new_float(&'z3 mut self) -> Box<dyn VariableFloat<'z3> + 'z3> {
636 let mut ctx: std::cell::RefMut<'z3, _> = self.0.borrow_mut();
637
638 ctx.max_float_id += 1;
639 let id = ctx.max_float_id;
640 // :(
641 // Should be safe since the z3 context inside the RefCell of self cannot be dropped while
642 // the Box is still alive
643 let f = z3::ast::Real::new_const(unsafe { std::mem::transmute(&ctx.ctx) }, id);
644 ctx.floats.insert(id, f.clone());
645 Box::new(Z3Float {
646 id,
647 real: f,
648 ctx: self.clone(),
649 })
650 }
651
652 fn new_bool(&'z3 mut self) -> Box<dyn VariableBool<'z3> + 'z3> {
653 let mut ctx = self.0.borrow_mut();
654
655 ctx.max_bool_id += 1;
656 let id = ctx.max_float_id;
657 // :(
658 // Should be safe since the z3 context inside the RefCell of self cannot be dropped while
659 // the Box is still alive
660 let b = z3::ast::Bool::new_const(unsafe { std::mem::transmute(&ctx.ctx) }, id);
661 ctx.bools.insert(id, b.clone());
662 Box::new(Z3Bool {
663 id: id,
664 real: b,
665 ctx: self.clone(),
666 })
667 }
668}
669
670pub struct Z3Solver<'z3>(z3::Solver<'z3>);
671
672impl<'z3> Z3Solver<'z3> {
673 pub fn new(ctx: &'z3 Z3Context) -> Self {
674 Self(z3::Solver::new(unsafe {
675 // :(
676 // again
677 std::mem::transmute(&ctx.0.borrow().ctx)
678 }))
679 }
680}
681
682impl<'z3> Solver for Z3Solver<'z3> {
683 fn constrain(&mut self, assertion: &Bool) {
684 todo!()
685 }
686
687 fn solve(&self) -> Box<dyn SolverModel> {
688 todo!()
689 }
690}
691*/
diff --git a/z3-solver/src/solving/mod.rs b/z3-solver/src/solving/mod.rs
new file mode 100644
index 0000000..f3f6673
--- /dev/null
+++ b/z3-solver/src/solving/mod.rs
@@ -0,0 +1,9 @@
1pub mod z3;
2
3#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
4pub struct FloatHandle(u32);
5
6pub trait Solver {
7 // TODO: make handles generic?
8 fn new_float<'a>(&'a mut self, handles: &mut z3::Handles<'a>) -> FloatHandle;
9}
diff --git a/z3-solver/src/solving/z3/mod.rs b/z3-solver/src/solving/z3/mod.rs
new file mode 100644
index 0000000..2f29073
--- /dev/null
+++ b/z3-solver/src/solving/z3/mod.rs
@@ -0,0 +1,44 @@
1use super::{Solver, FloatHandle};
2
3use std::collections::HashMap;
4
5pub struct Z3Solver {
6 ctx: z3::Context,
7}
8
9pub struct Handles<'a> {
10 float: HashMap<u32, z3::ast::Real<'a>>,
11 float_max_id: u32,
12}
13
14impl<'a> Handles<'a> {
15 pub fn new() -> Self {
16 Self {
17 float: HashMap::new(),
18 float_max_id: 0,
19 }
20 }
21}
22
23impl Z3Solver {
24 pub fn new<'a>() -> (Self, Handles<'a>) {
25 let config = z3::Config::new();
26
27 (
28 Self {
29 ctx: z3::Context::new(&config),
30 },
31 Handles::new(),
32 )
33 }
34}
35
36impl Solver for Z3Solver {
37 fn new_float<'a>(&'a mut self, handles: &mut Handles<'a>) -> FloatHandle {
38 let id = handles.float_max_id;
39 let float = z3::ast::Real::new_const(&self.ctx, id);
40 handles.float_max_id += 1;
41 handles.float.insert(id, float);
42 FloatHandle(id)
43 }
44}