Name Message Date
📄 main.rs POC printing Typst 9 hours ago
📄 main.rs
use std::{env::args, time::Duration};

use escpos::{
    driver::NetworkDriver,
    printer::Printer,
    utils::{BitImageOption, BitImageSize, Protocol},
};
use typst::layout::PagedDocument;
use typst_as_lib::{TypstEngine, typst_kit_options::TypstKitFontOptions};

fn main() {
    let args: Vec<_> = args().skip(1).collect();
    if args.len() != 2 {
        println!("Please provide the printer connection string and .typ template as arguments");
        return;
    };
    let Some((printer_host, printer_port)) = args[0]
        .split_once(':')
        .map(|(a, b)| b.parse::<u16>().ok().map(|b| (a, b)))
        .flatten()
    else {
        println!("Printer connection string must be on format `host:port`");
        return;
    };
    let template_path = &args[1];

    let engine = TypstEngine::builder()
        .with_file_system_resolver(".")
        .search_fonts_with(TypstKitFontOptions::new().include_system_fonts(true))
        .build();

    println!("Compiling document...");
    let document: PagedDocument = match engine.compile(template_path.as_ref()).output {
        Ok(document) => document,
        Err(error) => {
            println!("Failed to compile with message: {error}");
            return;
        }
    };

    let width_pixel = 72*8;
    let width_cm = 7.2;
    let width_pt = width_cm / 0.03527;
    let pixel_per_pt = width_pixel as f32 / width_pt;

    println!("Rendering document...");
    let pixmap = typst_render::render(&document.pages[0], pixel_per_pt);
    println!("Pixel size: {}x{}", pixmap.width(), pixmap.height());
    let png = match pixmap.encode_png() {
        Ok(png) => png,
        Err(error) => {
            println!("Could not encode image to PNG: {error}");
            return;
        }
    };

    println!("Connecting to printer...");
    let driver = match NetworkDriver::open(printer_host, printer_port, Some(Duration::from_secs(5)))
    {
        Ok(driver) => driver,
        Err(error) => {
            println!("Error connecting to printer: {error}");
            return;
        }
    };
    println!("Initializing printer...");
    let mut printer = Printer::new(driver, Protocol::default(), None);
    if let Err(error) = printer.init() {
        println!("Error initializing printer: {error}");
        return;
    }
    println!("Sending image to printer...");
    if let Err(error) = printer.bit_image_from_bytes_option(
        &png,
        BitImageOption::new(Some(width_pixel), None, BitImageSize::Normal).unwrap(),
    ) {
        println!("Error when printing document: {error}");
        return;
    }
    println!("Printing...");
    if let Err(error) = printer.print_cut() {
        println!("Error when printing: {error}");
        return;
    }
    println!("Done!");
}