tinymist_task/compute/
png.rs1use std::sync::Arc;
4
5use tinymist_std::error::prelude::*;
6use tinymist_std::typst::TypstPagedDocument;
7use tinymist_world::{CompilerFeat, ExportComputation, WorldComputeGraph};
8use typst::foundations::Bytes;
9use typst::model::Document;
10
11use crate::compute::{parse_color, parse_length, select_pages};
12use crate::model::ExportPngTask;
13use crate::{ImageOutput, PageMerge, PagedOutput};
14
15pub struct PngExport;
17
18impl<F: CompilerFeat> ExportComputation<F, TypstPagedDocument> for PngExport {
19 type Output = ImageOutput<Bytes>;
20 type Config = ExportPngTask;
21
22 fn run(
23 _graph: &Arc<WorldComputeGraph<F>>,
24 doc: &Arc<TypstPagedDocument>,
25 config: &ExportPngTask,
26 ) -> Result<Self::Output> {
27 let ppi = config.ppi.to_f32();
28 if ppi <= 1e-6 {
29 bail!("invalid ppi: {ppi}");
30 }
31
32 let fill = if let Some(fill) = &config.fill {
33 Some(parse_color(fill).map_err(|err| anyhow::anyhow!("invalid fill ({err})"))?)
34 } else {
35 None
36 };
37
38 let ppp = ppi / 72.;
39 let render_options = typst_render::RenderOptions {
40 pixel_per_pt: f64::from(ppp).into(),
41 ..Default::default()
42 };
43
44 let exported_pages = select_pages(doc, &config.pages);
45 if let Some(PageMerge { ref gap }) = config.merge {
46 let dummy_doc = TypstPagedDocument::new(
47 exported_pages
48 .into_iter()
49 .map(|(_, page)| page.clone())
50 .collect(),
51 doc.info().clone(),
52 );
53 let gap = gap
54 .as_ref()
55 .and_then(|gap| parse_length(gap).ok())
56 .unwrap_or_default();
57 let pixmap = typst_render::render_merged(&dummy_doc, &render_options, gap, fill);
58 let png = pixmap
59 .encode_png()
60 .map(Bytes::new)
61 .context_ut("failed to encode PNG")?;
62 Ok(ImageOutput::Merged(png))
63 } else {
64 let exported = exported_pages
65 .into_iter()
66 .map(|(i, page)| {
67 let pixmap = typst_render::render(page, &render_options);
68 let png = pixmap
69 .encode_png()
70 .map(Bytes::new)
71 .context_ut("failed to encode PNG")?;
72 Ok(PagedOutput {
73 page: i,
74 value: png,
75 })
76 })
77 .collect::<Result<Vec<_>>>()?;
78 Ok(ImageOutput::Paged(exported))
79 }
80 }
81}
82
83