Rust PDF生成库typst-pdf的使用,typst-pdf提供高性能的PDF文档生成与处理功能

Rust PDF生成库typst-pdf的使用

Typst是一个基于标记的新排版系统,设计为与LaTeX一样强大,同时更容易学习和使用。Typst具有以下特点:

  • 内置常见格式化任务的标记
  • 灵活的脚本系统
  • 数学排版、参考文献管理等功能
  • 由于增量编译而具有快速的编译时间

示例

以下是Typst的一个示例代码:

#set page(width: 10cm, height: auto)
#set heading(numbering: "1.")

= Fibonacci sequence
The Fibonacci sequence is defined through the
recurrence relation $F_n = F_(n-1) + F_(n-2)$.
It can also be expressed in _closed form:_

$ F_n = round(1 / sqrt(5) phi.alt^n), quad
  phi.alt = (1 + sqrt(5)) / 2 $

#let count = 8
#let nums = range(1, count + 1)
#let fib(n) = (
  if n <= 2 { 1 }
  else { fib(n - 1) + fib(n - 2) }
)

The first #count numbers of the sequence are:

#align(center, table(
  columns: count,
  ..nums.map(n => $F_#n$),
  ..nums.map(n => str(fib(n))),
))

安装

Typst可以通过多种方式安装:

  1. 从GitHub releases页面下载预编译二进制文件
  2. 使用包管理器:
    • Linux: 查看Repology上的Typst
    • macOS: brew install typst
    • Windows: winget install --id Typst.Typst
  3. 使用Rust工具链:
    cargo install --locked typst-cli
    

使用

安装Typst后,可以这样使用:

# 创建file.pdf
typst compile file.typ

# 在指定路径创建PDF
typst compile path/to/source.typ path/to/output.pdf

也可以监视源文件并在更改时自动重新编译:

typst watch file.typ

在Rust项目中使用typst-pdf

要在Rust项目中使用typst-pdf库,首先在Cargo.toml中添加依赖:

[dependencies]
typst-pdf = "0.13.1"

完整示例代码

以下是一个完整的Rust项目示例,展示如何使用typst-pdf生成PDF:

use typst_pdf::{compile, CompileOpts};

fn main() {
    // Typst源代码 - 创建一个包含表格和数学公式的文档
    let source = r#"
        #set page(width: 15cm, height: auto)
        #set heading(numbering: "1.")
        
        = 数学报告
        
        这是一个使用Typst生成的数学报告示例。
        
        ## 斐波那契数列
        斐波那契数列由以下递推关系定义:
        $ F_n = F_(n-1) + F_(n-2) $
        
        ## 表格示例
        #let data = (
            ("姓名", "年龄", "分数"),
            ("张三", "20", "85"),
            ("李四", "22", "92"),
            ("王五", "21", "78")
        )
        
        #table(
            columns: (auto, auto, auto),
            ..data
        )
    "#;

    // 编译选项配置
    let opts = CompileOpts {
        input: "report.typ".to_string(),  // 输入文件名
        root: None,                      // 根目录
        font_paths: Vec::new(),          // 自定义字体路径
    };

    // 编译为PDF
    match compile(source, &opts) {
        Ok(pdf_bytes) => {
            // 将PDF保存到文件
            std::fs::write("math_report.pdf", pdf_bytes).unwrap();
            println!("PDF生成成功: math_report.pdf");
        }
        Err(e) => eprintln!("编译错误: {}", e),
    }
}

示例说明

  1. 首先在Cargo.toml中添加typst-pdf依赖
  2. 创建Typst源代码字符串,包含标题、数学公式和表格
  3. 配置编译选项(CompileOpts)
  4. 调用compile函数将Typst代码编译为PDF字节
  5. 将生成的PDF字节写入文件

这个完整示例展示了如何在Rust程序中使用typst-pdf生成包含复杂内容的PDF文档,包括数学公式和表格。Typst-pdf非常适合需要程序化生成专业排版文档的应用场景。


1 回复

Rust PDF生成库typst-pdf的使用指南

介绍

typst-pdf是一个高性能的Rust库,专门用于PDF文档的生成与处理。它提供了简洁的API和强大的排版能力,适合需要动态生成PDF文档的应用场景。

主要特性

  • 高性能PDF生成
  • 简洁的API设计
  • 支持文本、图像和矢量图形
  • 灵活的页面布局控制
  • 内置排版引擎

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
typst-pdf = "0.7"

基本示例

use typst_pdf::{PdfDocument, Page, Rect, Text};

fn main() {
    // 创建新PDF文档
    let mut doc = PdfDocument::new();
    
    // 添加页面(A4尺寸: 595.0×842.0点)
    let mut page = Page::new(Rect::new(0.0, 0.0, 595.0, 842.0));
    
    // 在(100,700)位置添加24点大小的文本
    let text = Text::new("Hello, typst-pdf!")
        .with_size(24.0)
        .at(100.0, 700.0);
    page.add(text);
    
    // 将页面添加到文档
    doc.add_page(page);
    
    // 保存PDF文件
    doc.save("output.pdf").expect("Failed to save PDF");
}

高级功能示例

use typst_pdf::{PdfDocument, Page, Rect, Text, Image, Color};

fn advanced_example() {
    let mut doc = PdfDocument::new();
    
    // 创建带边距和背景色的页面
    let mut page = Page::new(Rect::new(0.0, 0.0, 595.0, 842.0))
        .with_margin(50.0)
        .with_background(Color::rgb(0.9, 0.95, 1.0));
    
    // 添加带颜色的标题
    let title = Text::new("Advanced PDF Example")
        .with_size(32.0)
        .with_color(Color::rgb(0.2, 0.4, 0.6))
        .at(50.0, 750.0);
    page.add(title);
    
    // 从文件添加图像
    if let Ok(image_data) = std::fs::read("logo.png") {
        let image = Image::from_bytes(&image_data)
            .unwrap()
            .with_size(200.0, 100.0)  // 设置图像尺寸
            .at(200.0, 600.0);        // 设置图像位置
        page.add(image);
    }
    
    // 添加固定宽度的多行文本
    let lorem = "Lorem ipsum dolor sit amet..."; // 长文本
    let text_block = Text::new(lorem)
        .with_size(12.0)
        .with_width(400.0)  // 设置文本块宽度
        .at(50.0, 500.0);
    page.add(text_block);
    
    doc.add_page(page);
    doc.save("advanced.pdf").unwrap();
}

表格生成示例

use typst_pdf::{PdfDocument, Page, Rect, Text, Color};

fn table_example() {
    let mut doc = PdfDocument::new();
    let mut page = Page::new(Rect::new(0.0, 0.0, 595.0, 842.0));
    
    // 表格数据
    let headers = ["Name", "Age", "Occupation"];
    let rows = [
        ["Alice", "28", "Engineer"],
        ["Bob", "34", "Designer"],
        ["Charlie", "22", "Student"],
    ];
    
    let mut y = 700.0;  // 起始Y坐标
    
    // 绘制表头(带背景色)
    let mut x = 50.0;
    for header in headers {
        let cell = Text::new(header)
            .with_size(14.0)
            .with_color(Color::WHITE)
            .with_background(Color::rgb(0.2, 0.4, 0.6))
            .at(x, y);
        page.add(cell);
        x += 150.0;  // 列宽150点
    }
    
    y -= 30.0;  // 下移一行
    
    // 绘制表格内容
    for row in rows {
        let mut x = 50.0;
        for cell_text in row {
            let cell = Text::new(cell_text)
                .with_size(12.0)
                .at(x, y);
            page.add(cell);
            x += 150.0;
        }
        y -= 25.0;  // 行高25点
    }
    
    doc.add_page(page);
    doc.save("table.pdf").unwrap();
}

完整示例

use typst_pdf::{PdfDocument, Page, Rect, Text, Image, Color};
use std::path::Path;

fn generate_invoice() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化PDF文档
    let mut doc = PdfDocument::new();
    
    // 创建A4页面(595×842点)
    let mut page = Page::new(Rect::new(0.0, 0.0, 595.0, 842.0))
        .with_margin(40.0);
    
    // 添加标题
    let title = Text::new("销售发票")
        .with_size(28.0)
        .with_color(Color::rgb(0.1, 0.3, 0.6))
        .at(50.0, 750.0);
    page.add(title);
    
    // 添加公司logo
    if let Ok(image_data) = std::fs::read("company_logo.png") {
        let logo = Image::from_bytes(&image_data)?
            .with_size(120.0, 60.0)
            .at(400.0, 750.0);
        page.add(logo);
    }
    
    // 添加客户信息
    let client_info = Text::new("客户: ABC公司\n联系人: 张经理\n电话: 13800138000")
        .with_size(12.0)
        .at(50.0, 700.0);
    page.add(client_info);
    
    // 添加发票表格
    let headers = ["商品名称", "数量", "单价", "金额"];
    let items = [
        ["笔记本电脑", "1", "¥6,999.00", "¥6,999.00"],
        ["无线鼠标", "2", "¥199.00", "¥398.00"],
        ["键盘套装", "1", "¥499.00", "¥499.00"],
    ];
    
    let mut y = 600.0;
    
    // 表头
    let mut x = 50.0;
    for header in headers {
        let cell = Text::new(header)
            .with_size(12.0)
            .with_color(Color::WHITE)
            .with_background(Color::rgb(0.3, 0.5, 0.8))
            .at(x, y);
        page.add(cell);
        x += 120.0;
    }
    
    y -= 25.0;
    
    // 表格内容
    for item in items {
        let mut x = 50.0;
        for text in item {
            let cell = Text::new(text)
                .with_size(11.0)
                .at(x, y);
            page.add(cell);
            x += 120.0;
        }
        y -= 20.0;
    }
    
    // 添加总计
    let total = Text::new("总计: ¥7,896.00")
        .with_size(14.0)
        .with_color(Color::rgb(0.8, 0.2, 0.2))
        .at(350.0, y - 30.0);
    page.add(total);
    
    // 添加页脚
    let footer = Text::new("感谢您的惠顾!")
        .with_size(12.0)
        .at(50.0, 50.0);
    page.add(footer);
    
    doc.add_page(page);
    doc.save("invoice.pdf")?;
    
    Ok(())
}

fn main() {
    if let Err(e) = generate_invoice() {
        eprintln!("生成PDF失败: {}", e);
    }
}

注意事项

  1. 确保在添加图像前检查图像数据是否有效
  2. 坐标系统原点(0,0)在页面左下角
  3. 尺寸单位默认为点(1点=1/72英寸)
  4. 对于复杂文档,考虑使用typst-pdf的更高级排版功能

typst-pdf提供了丰富的功能来满足各种PDF生成需求,从简单的文本输出到复杂的多页文档都能胜任。

回到顶部