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可以通过多种方式安装:
- 从GitHub releases页面下载预编译二进制文件
- 使用包管理器:
- Linux: 查看Repology上的Typst
- macOS:
brew install typst
- Windows:
winget install --id Typst.Typst
- 使用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),
}
}
示例说明
- 首先在Cargo.toml中添加typst-pdf依赖
- 创建Typst源代码字符串,包含标题、数学公式和表格
- 配置编译选项(CompileOpts)
- 调用compile函数将Typst代码编译为PDF字节
- 将生成的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);
}
}
注意事项
- 确保在添加图像前检查图像数据是否有效
- 坐标系统原点(0,0)在页面左下角
- 尺寸单位默认为点(1点=1/72英寸)
- 对于复杂文档,考虑使用typst-pdf的更高级排版功能
typst-pdf提供了丰富的功能来满足各种PDF生成需求,从简单的文本输出到复杂的多页文档都能胜任。