···1919 scale(size, content, reflow: true),
2020)
21212222-#let codesnippet(caption: "", content, lang: "rust") = block(
2323- inset: 2em,
2222+#let codesnippet(caption: "", content, lang: "rust", size: 1em) = text(size: size, block(
2323+ inset: 1.5em,
2424 fill: luma(230),
2525 radius: 4pt,
2626 width: 100%,
···2929 lang: lang,
3030 content,
3131 ),
3232-)
3232+))
33333434#show link: underline
3535···352352 }
353353 ```,
354354)
355355-Les arguments `cell_size` et `object_sizes` permettent de réaliser en valeur concrètes (pixels) les valeurs de taille abstraites: la distance unitaire entre deux points est définie par `cell_size`, et les tailles des objets, qui, par choix, n'est pas contrôlable finement, sont définies par `object_sizes`.
356355357357-#codesnippet(
358358- lang: "rust",
359359- cut-around(
360360- it => it.trim().starts-with("pub struct ObjectSizes"),
361361- it => it == "}",
362362- read("../src/graphics/objects.rs"),
356356+#grid(
357357+ columns: (1fr, 1fr),
358358+ gutter: 2em,
359359+ [
360360+ Les arguments `cell_size` et `object_sizes` permettent de réaliser en valeur concrètes (pixels) les valeurs de taille abstraites: la distance unitaire entre deux points est définie par `cell_size`, et les tailles des objets, qui, par choix, n'est pas contrôlable finement, sont définies par `object_sizes`.
361361+ ],
362362+ codesnippet(
363363+ lang: "rust",
364364+ size: 0.9em,
365365+ cut-around(
366366+ it => it.trim().starts-with("pub struct ObjectSizes"),
367367+ it => it == "}",
368368+ read("../src/graphics/objects.rs"),
369369+ ),
363370 ),
364371)
372372+373373+En suite, pour convertir en PNG, on utilise une autre bibliothèque, _resvg_, qui implémente presque complétement la spécification SVG 1.1, et l'implémente même mieux que Firefox, Safari et Chrome @resvg. L'arbre SVG que l'on a construit est sérialisé en string, puis parsé par _resvg_, qui le transforme en un arbre de rendu, qui est ensuite rasterisé en une pixmap#footnote[Matrice plate de pixels RGBA], qui est finalement écrit dans un fichier PNG.
374374+375375+#diagram(
376376+ caption: [Rendu d'un canvas SVG en PNG],
377377+ ```dot
378378+ digraph {
379379+ rankdir="LR";
380380+ node [shape="record"];
381381+ "svg tree" -> "svg string"
382382+ "svg string" -> "usvg tree"
383383+ "usvg tree" -> "pixmap"
384384+ pixmap -> "png file"
385385+ }
386386+ ```
387387+)
388388+389389+Le passage par une string svg est évidemment une perte de performance, qui est discutée #ref(<perf-svgstring>, form: "page")
365390366391367392= Render loop et hooks
···572597 lang: "rust",
573598)
574599575575-= Performance
600600+= Performance
576601577602#grid(
578603 columns: (auto, auto),
···612637 ..csv("../results.csv").slice(1).flatten()
613638 ),
614639 )
640640+641641+ == Pixmap et libx264: le problème des multiples standards
642642+643643+ == SVG vers string vers SVG <perf-svgstring>
615644616645 Comme on peut le remarquer, il y a un gain de performance assez conséquent de possible si l'on parvient à utiliser usvg, non seulement pour la rastérisation, mais également pour la construction de l'arbre SVG: sur une boule de rendu de 167 ms, *on passe 29% du temps à parser un arbre SVG sérialisé, alors que l'on vient de construire cette arbre*.
617646 ],
+20-2
paper/utils.typ
···4848 keep_delimiting: true,
4949)
50505151+#let dedent = content => {
5252+ let lines = content.split(regex("\r?\n"))
5353+ let min_indent = lines
5454+ .filter(it => it.trim() != "")
5555+ .map(it => it.split().position(c => c.find(regex("[^\s]")) != none))
5656+ .fold(0, (a, b) => calc.min(a, b))
5757+ lines.map(it => it.slice(min_indent)).join("\n")
5858+}
5959+51605261#let include-function = (
5362 filepath,
5463 name,
5564 lang: none,
6565+ is_method: false,
5666 transform: it => it,
5767) => {
5868 let start_pattern = if lang == "rust" {
5959- regex("^pub fn " + name)
6969+ if is_method {
7070+ regex("^ (pub )?fn " + name)
7171+ } else {
7272+ regex("^(pub )?fn " + name)
7373+ }
6074 } else if lang == "python" {
6175 regex("^def " + name)
6276 } else if lang == none {
···6680 }
67816882 let end_pattern = if lang == "rust" {
8383+ if is_method {
8484+ regex("^ \}")
8585+ } else {
6986 regex("^\}")
8787+ }
7088 } else if lang == "python" {
7189 regex("^# end") // TODO pass next line to cut-between
7290 } else {
···87105 #raw(lang: lang, read(filepath))
88106 ]
89107 } else {
9090- raw(lang: lang, transform(contents))
108108+ raw(lang: lang, transform(dedent(contents)))
91109 }
92110}