Un PDF minimal

Le plus petit fichier complet : une page, et des formes dessinées dessus.

Rust write_pdf.rs 79 lignes
 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
71
72
73
74
75
76
77
78
79
//! Writes a small PDF to disk, so that real readers can be pointed at it.
//!
//! Unit tests can only check that the bytes look right to us. Whether the file
//! is actually a PDF is a question only a PDF reader can answer, which is what
//! `scripts/check_pdf_validity.sh` uses this for.
//!
//! Usage: `cargo run --example write_pdf -- tmp/out.pdf [--licensed]`

use std::env;
use std::fs;
use std::path::Path;

use hqf_pdf::content::Content;
use hqf_pdf::cos::Name;
use hqf_pdf::{Document, Page};

#[path = "shared/out.rs"]
mod out;

#[path = "shared/licence.rs"]
mod licence;

/// Draws a page of an invoice: a header block, a frame, and a run of table
/// rules.
fn invoice_page() -> Result<Page, hqf_pdf::Error> {
    let mut c = Content::new();
    c.save_state();

    c.set_fill_rgb(0.20, 0.40, 0.80)?;
    c.rect(50.0, 700.0, 495.0, 90.0)?;
    c.fill();

    c.set_stroke_rgb(0.0, 0.0, 0.0)?;
    c.set_line_width(1.0)?;
    c.rect(50.0, 50.0, 495.0, 742.0)?;
    c.stroke();

    c.set_line_width(0.4)?;
    for row in 0..24 {
        let y = f64::from(row).mul_add(-22.0, 640.0);
        c.rect(50.0, y, 495.0, 22.0)?;
        c.stroke();
    }
    c.restore_state();

    let mut page = Page::a4();
    page.content = c.into_bytes();
    Ok(page)
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut args = env::args().skip(1);
    let path = args.next().unwrap_or_else(|| out::default_path("out"));
    let licensed = env::args().any(|a| a == "--licensed");

    let mut doc = Document::new();
    if licensed {
        doc.set_license(licence::licensed());
    }
    doc.set_info(Name::new("Title"), "hqf-pdf sample invoice");
    doc.set_info(Name::new("Creator"), "hqf-pdf");

    doc.add_page(invoice_page()?)?;
    doc.add_page(invoice_page()?)?;

    let bytes = doc.to_bytes()?;
    if let Some(parent) = Path::new(&path).parent() {
        fs::create_dir_all(parent)?;
    }
    fs::write(&path, &bytes)?;

    println!(
        "wrote {path}: {} bytes, {} pages, {}",
        bytes.len(),
        doc.page_count(),
        if licensed { "licensed" } else { "evaluation" }
    );
    Ok(())
}