this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

:memo: finish image rendering section

+71 -13
+11
paper/bibliography.yaml
··· 139 139 url: 140 140 value: https://doc.rust-lang.org/book/ch10-02-traits.html 141 141 date: 2025-03-23 142 + 143 + resvg: 144 + title: "linebender/resvg: An SVG rendering library" 145 + type: repository 146 + author: 147 + - Yevhenii Reizner 148 + publisher: 149 + name: Linebender 150 + url: 151 + value: https://github.com/linebender/resvg 152 + date: 2025-03-23
paper/main.pdf

This is a binary file and will not be displayed.

+40 -11
paper/main.typ
··· 19 19 scale(size, content, reflow: true), 20 20 ) 21 21 22 - #let codesnippet(caption: "", content, lang: "rust") = block( 23 - inset: 2em, 22 + #let codesnippet(caption: "", content, lang: "rust", size: 1em) = text(size: size, block( 23 + inset: 1.5em, 24 24 fill: luma(230), 25 25 radius: 4pt, 26 26 width: 100%, ··· 29 29 lang: lang, 30 30 content, 31 31 ), 32 - ) 32 + )) 33 33 34 34 #show link: underline 35 35 ··· 352 352 } 353 353 ```, 354 354 ) 355 - 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`. 356 355 357 - #codesnippet( 358 - lang: "rust", 359 - cut-around( 360 - it => it.trim().starts-with("pub struct ObjectSizes"), 361 - it => it == "}", 362 - read("../src/graphics/objects.rs"), 356 + #grid( 357 + columns: (1fr, 1fr), 358 + gutter: 2em, 359 + [ 360 + 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`. 361 + ], 362 + codesnippet( 363 + lang: "rust", 364 + size: 0.9em, 365 + cut-around( 366 + it => it.trim().starts-with("pub struct ObjectSizes"), 367 + it => it == "}", 368 + read("../src/graphics/objects.rs"), 369 + ), 363 370 ), 364 371 ) 372 + 373 + 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. 374 + 375 + #diagram( 376 + caption: [Rendu d'un canvas SVG en PNG], 377 + ```dot 378 + digraph { 379 + rankdir="LR"; 380 + node [shape="record"]; 381 + "svg tree" -> "svg string" 382 + "svg string" -> "usvg tree" 383 + "usvg tree" -> "pixmap" 384 + pixmap -> "png file" 385 + } 386 + ``` 387 + ) 388 + 389 + Le passage par une string svg est évidemment une perte de performance, qui est discutée #ref(<perf-svgstring>, form: "page") 365 390 366 391 367 392 = Render loop et hooks ··· 572 597 lang: "rust", 573 598 ) 574 599 575 - = Performance 600 + = Performance 576 601 577 602 #grid( 578 603 columns: (auto, auto), ··· 612 637 ..csv("../results.csv").slice(1).flatten() 613 638 ), 614 639 ) 640 + 641 + == Pixmap et libx264: le problème des multiples standards 642 + 643 + == SVG vers string vers SVG <perf-svgstring> 615 644 616 645 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*. 617 646 ],
+20 -2
paper/utils.typ
··· 48 48 keep_delimiting: true, 49 49 ) 50 50 51 + #let dedent = content => { 52 + let lines = content.split(regex("\r?\n")) 53 + let min_indent = lines 54 + .filter(it => it.trim() != "") 55 + .map(it => it.split().position(c => c.find(regex("[^\s]")) != none)) 56 + .fold(0, (a, b) => calc.min(a, b)) 57 + lines.map(it => it.slice(min_indent)).join("\n") 58 + } 59 + 51 60 52 61 #let include-function = ( 53 62 filepath, 54 63 name, 55 64 lang: none, 65 + is_method: false, 56 66 transform: it => it, 57 67 ) => { 58 68 let start_pattern = if lang == "rust" { 59 - regex("^pub fn " + name) 69 + if is_method { 70 + regex("^ (pub )?fn " + name) 71 + } else { 72 + regex("^(pub )?fn " + name) 73 + } 60 74 } else if lang == "python" { 61 75 regex("^def " + name) 62 76 } else if lang == none { ··· 66 80 } 67 81 68 82 let end_pattern = if lang == "rust" { 83 + if is_method { 84 + regex("^ \}") 85 + } else { 69 86 regex("^\}") 87 + } 70 88 } else if lang == "python" { 71 89 regex("^# end") // TODO pass next line to cut-between 72 90 } else { ··· 87 105 #raw(lang: lang, read(filepath)) 88 106 ] 89 107 } else { 90 - raw(lang: lang, transform(contents)) 108 + raw(lang: lang, transform(dedent(contents))) 91 109 } 92 110 }