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, &current_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>>;
}

//     let armees = Image::try_from(JpegDecoder::new(IMAGE_ARMEES)?)?;
//     armees.add_to_layer(
//         current_layer.clone(),
//         Some(Mm(10.)),
//         Some(Mm(260.)),
//         None,
//         Some(1.5),
//         Some(1.5),
//         None,
//     );