use tiny_skia as sk;
use reflexo::{
error::prelude::*,
vector::{
incr::IncrDocClient,
ir::{ImmutStr, Module, Page, Rect},
vm::RenderVm,
},
};
use crate::{set_transform, CanvasDevice, CanvasOp, CanvasPage, CanvasTask, DefaultExportFeature};
pub struct IncrVec2CanvasPass {
pub pixel_per_pt: f32,
pub fill: ImmutStr,
pub pages: Vec<CanvasPage>,
}
impl Default for IncrVec2CanvasPass {
fn default() -> Self {
Self {
pixel_per_pt: 3.,
fill: "#ffffff".into(),
pages: vec![],
}
}
}
impl IncrVec2CanvasPass {
pub fn interpret_changes(&mut self, module: &Module, pages: &[Page]) {
let mut t = CanvasTask::<DefaultExportFeature>::default();
let mut ct = t.fork_canvas_render_task(module);
let pages: Vec<CanvasPage> = pages
.iter()
.enumerate()
.map(|(idx, Page { content, size })| {
if idx < self.pages.len() && self.pages[idx].content == *content {
return self.pages[idx].clone();
}
CanvasPage {
content: *content,
elem: ct.render_item(content),
size: *size,
}
})
.collect();
self.pages = pages;
}
pub async fn flush_page(&mut self, idx: usize, canvas: &dyn CanvasDevice, ts: sk::Transform) {
let pg = &self.pages[idx];
if !set_transform(canvas, ts) {
return;
}
canvas.set_fill_style_str(self.fill.as_ref());
canvas.fill_rect(0., 0., pg.size.x.0 as f64, pg.size.y.0 as f64);
pg.elem.realize(ts, canvas).await;
}
}
#[derive(Default)]
pub struct IncrCanvasDocClient {
pub vec2canvas: IncrVec2CanvasPass,
pub doc_view: Option<Vec<Page>>,
}
impl IncrCanvasDocClient {
pub fn reset(&mut self) {}
pub fn set_pixel_per_pt(&mut self, pixel_per_pt: f32) {
self.vec2canvas.pixel_per_pt = pixel_per_pt;
}
pub fn set_fill(&mut self, fill: ImmutStr) {
self.vec2canvas.fill = fill;
}
fn patch_delta(&mut self, kern: &IncrDocClient) {
if let Some(layout) = &kern.layout {
let pages = layout.pages(&kern.doc.module);
if let Some(pages) = pages {
self.vec2canvas
.interpret_changes(pages.module(), pages.pages());
}
}
}
pub async fn render_page_in_window(
&mut self,
kern: &mut IncrDocClient,
canvas: &dyn CanvasDevice,
idx: usize,
_rect: Rect,
) -> Result<()> {
self.patch_delta(kern);
if idx >= self.vec2canvas.pages.len() {
Err(error_once!("Renderer.OutofPageRange", idx: idx))?;
}
let s = self.vec2canvas.pixel_per_pt;
let ts = sk::Transform::from_scale(s, s);
self.vec2canvas.flush_page(idx, canvas, ts).await;
Ok(())
}
}