reflexo_vec2canvas/
incr.rs1use tiny_skia as sk;
2
3use reflexo::{
4 error::prelude::*,
5 vector::{
6 incr::IncrDocClient,
7 ir::{ImmutStr, Module, Page, Rect},
8 vm::RenderVm,
9 },
10};
11
12use crate::{set_transform, CanvasDevice, CanvasOp, CanvasPage, CanvasTask, DefaultExportFeature};
13
14pub struct IncrVec2CanvasPass {
16 pub pixel_per_pt: f32,
18 pub fill: ImmutStr,
23 pub pages: Vec<CanvasPage>,
25}
26
27impl Default for IncrVec2CanvasPass {
28 fn default() -> Self {
29 Self {
30 pixel_per_pt: 3.,
31 fill: "#ffffff".into(),
32 pages: vec![],
33 }
34 }
35}
36
37impl IncrVec2CanvasPass {
38 pub fn interpret_changes(&mut self, module: &Module, pages: &[Page]) {
40 let mut t = CanvasTask::<DefaultExportFeature>::default();
42
43 let mut ct = t.fork_canvas_render_task(module);
44
45 let pages: Vec<CanvasPage> = pages
46 .iter()
47 .enumerate()
48 .map(|(idx, Page { content, size })| {
49 if idx < self.pages.len() && self.pages[idx].content == *content {
50 return self.pages[idx].clone();
51 }
52
53 CanvasPage {
54 content: *content,
55 elem: ct.render_item(content),
56 size: *size,
57 }
58 })
59 .collect();
60
61 self.pages = pages;
62 }
63
64 pub async fn flush_page(&mut self, idx: usize, canvas: &dyn CanvasDevice, ts: sk::Transform) {
66 let pg = &self.pages[idx];
67
68 if !set_transform(canvas, ts) {
69 return;
70 }
71 canvas.set_fill_style_str(self.fill.as_ref());
72 canvas.fill_rect(0., 0., pg.size.x.0 as f64, pg.size.y.0 as f64);
73
74 pg.elem.realize(ts, canvas).await;
75 }
76}
77
78#[derive(Default)]
80pub struct IncrCanvasDocClient {
81 pub vec2canvas: IncrVec2CanvasPass,
83
84 pub doc_view: Option<Vec<Page>>,
87}
88
89impl IncrCanvasDocClient {
90 pub fn reset(&mut self) {}
92
93 pub fn set_pixel_per_pt(&mut self, pixel_per_pt: f32) {
95 self.vec2canvas.pixel_per_pt = pixel_per_pt;
96 }
97
98 pub fn set_fill(&mut self, fill: ImmutStr) {
100 self.vec2canvas.fill = fill;
101 }
102
103 fn patch_delta(&mut self, kern: &IncrDocClient) {
104 if let Some(layout) = &kern.layout {
105 let pages = layout.pages(&kern.doc.module);
106 if let Some(pages) = pages {
107 self.vec2canvas
108 .interpret_changes(pages.module(), pages.pages());
109 }
110 }
111 }
112
113 pub async fn render_page_in_window(
115 &mut self,
116 kern: &mut IncrDocClient,
117 canvas: &dyn CanvasDevice,
118 idx: usize,
119 _rect: Rect,
120 ) -> Result<()> {
121 self.patch_delta(kern);
122
123 if idx >= self.vec2canvas.pages.len() {
124 Err(error_once!("Renderer.OutofPageRange", idx: idx))?;
125 }
126
127 let s = self.vec2canvas.pixel_per_pt;
128 let ts = sk::Transform::from_scale(s, s);
129 self.vec2canvas.flush_page(idx, canvas, ts).await;
130
131 Ok(())
132 }
133}