1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
mod shapes;
use dessin::{vec2, Drawing, Vec2};
use printpdf::{IndirectFontRef, Mm, PdfDocument, PdfDocumentReference, PdfLayerReference};
use std::{error::Error, io::BufWriter};
const ARIAL_REGULAR: &[u8] = include_bytes!("Arial.ttf");
const ARIAL_BOLD: &[u8] = include_bytes!("Arial Bold.ttf");
const ARIAL_ITALIC: &[u8] = include_bytes!("Arial Italic.ttf");
const ARIAL_BOLD_ITALIC: &[u8] = include_bytes!("Arial Bold Italic.ttf");
const DPI: f64 = 96.;
pub struct PDF(pub PdfDocumentReference);
impl PDF {
pub fn into_bytes(self) -> Result<Vec<u8>, Box<dyn Error>> {
let mut buff = BufWriter::new(vec![]);
self.0.save(&mut buff)?;
Ok(buff.into_inner()?)
}
}
pub trait ToPDF {
fn to_pdf(&self) -> Result<PDF, Box<dyn Error>>;
}
impl ToPDF for Drawing {
fn to_pdf(&self) -> Result<PDF, Box<dyn Error>> {
let Vec2 {
x: width,
y: height,
} = self.canvas_size();
let (doc, page1, layer1) =
PdfDocument::new("PDF", Mm(width as f64), Mm(height as f64), "Layer1");
let font = doc.add_external_font(ARIAL_REGULAR)?;
let current_layer = doc.get_page(page1).get_layer(layer1);
let offset = vec2(self.canvas_size().x / 2., self.canvas_size().x / 2.);
self.shapes()
.iter()
.map(|v| v.to_pdf_part(DPI, offset, &font, ¤t_layer))
.collect::<Result<(), Box<dyn std::error::Error>>>()?;
Ok(PDF(doc))
}
}
trait ToPDFPart {
fn to_pdf_part(
&self,
dpi: f64,
offset: Vec2,
font: &IndirectFontRef,
layer: &PdfLayerReference,
) -> Result<(), Box<dyn Error>>;
}