Rust PDF生成库printpdf的使用:高效创建、编辑和操作PDF文档的Rust解决方案

Rust PDF生成库printpdf的使用:高效创建、编辑和操作PDF文档的Rust解决方案

printpdf是一个用于生成、读取、渲染和优化PDF文档的Rust库。

特性

  • 页面、书签、链接注释(读写)
  • 图层(读写)
  • 图形:线条、形状、贝塞尔曲线、SVG内容(读写)
  • 图像编码/解码(读取支持:实验性/写入支持需image
  • 嵌入式字体、Unicode支持(读取支持:实验性/写入)
  • 最小化文件大小(自动子集化字体)
  • 将PDF页面渲染为SVG文件:实验性
  • 从PDF页面提取文本(自动解码Unicode、换行符、文本位置:实验性)
  • 简单页面布局的基本HTML排版(使用azul-layout + kuchiki HTML解析器)
  • 高级图形 - 套印、混合等
  • 高级排版 - 字符/单词缩放和间距、上标、下标等
  • 嵌入SVG(内部使用svg2pdf库)

不支持的功能包括:

  • 渐变
  • 图案
  • 文件附件
  • 开放印前接口
  • 图像半色调
  • 各种PDF标准的符合性/错误检查
  • 嵌入式JavaScript

基本示例

use printpdf::*;

fn main() {
    let mut doc = PdfDocument::new("My first PDF");
    let page1_contents = vec![Op::Marker { id: "debugging-marker".to_string() }];
    let page1 = PdfPage::new(Mm(10.0), Mm(250.0), page1_contents);
    let pdf_bytes: Vec<u8> = doc
        .with_pages(vec![page1])
        .save(&PdfSaveOptions::default());
}

完整示例代码

use printpdf::*;

fn main() {
    // 创建新PDF文档
    let mut doc = PdfDocument::new("My PDF Document");
    
    // 添加页面
    let page1 = PdfPage::new(Mm(210.0), Mm(297.0), vec![]); // A4尺寸
    
    // 添加图形
    let line = Line {
        points: vec![
            (Point::new(Mm(50.0), Mm(50.0)), false),
            (Point::new(Mm(50.0), Mm(100.0)), false),
            (Point::new(Mm(100.0), Mm(100.0)), false),
            (Point::new(Mm(100.0), Mm(50.0)), false),
        ],
        is_closed: true,
    };
    
    // 添加文本
    let font_bytes = include_bytes!("Roboto-Regular.ttf");
    let font = ParsedFont::from_bytes(font_bytes, 0, &mut Vec::new()).unwrap();
    let font_id = doc.add_font(&font);
    
    // 页面内容操作
    let page_contents = vec![
        // 绘制图形
        Op::SetOutlineColor { col: Color::Rgb(Rgb::new极好的!下面我将整理一个综合性的printpdf完整示例,结合了文本、图形、图片和页面布局功能:

```rust
use printpdf::*;
use std::fs::File;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建新PDF文档
    let (doc, page1, layer1) = PdfDocument::new(
        "PDF文档示例", 
        Mm(210.0),  // A4宽度
        Mm(297.0),  // A4高度
        "主图层"
    );

    // 获取当前页面的图层
    let layer = doc.get_page(page1).get_layer(layer1);

    // 1. 添加文本
    let font = doc.add_external_font(File::open("fonts/Roboto-Regular.ttf")?)?;
    
    layer.use_text("PDF文档标题", 48.0, Mm(50.0), Mm(250.0), &font);
    layer.use_text("这是使用printpdf生成的PDF文档", 14.0, Mm(20.0), Mm(220.0), &font);

    // 2. 绘制图形
    // 绘制矩形
    layer.set_outline_color(Color::Rgb(Rgb::new(0.0, 0.0, 1.0, None)));
    layer.set_outline_thickness(2.0);
    layer.add_shape(Line {
        points: vec![
            (Point::new(Mm(20.0), Mm(180.0)), false),
            (Point::new(Mm(20.0), Mm(200.0)), false),
            (Point::new(Mm(100.0), Mm(200.0)), false),
            (Point::new(Mm(100.0), Mm(180.0)), false),
        ],
        is_closed: true,
    });

    // 3. 添加图片
    #[cfg(feature = "image")]
    {
        let image = Image::try_from(include_bytes!("assets/rust-logo.png"))?;
        let image_layer = doc.get_page(page1).add_layer("图片图层");
        image_layer.add_image(image, None, None, None, None, None, None)?;
    }

    // 保存PDF文件
    doc.save(&mut File::create("output.pdf")?)?;
    
    Ok(())
}

这个综合示例展示了:

  1. 创建新PDF文档并设置A4页面尺寸
  2. 添加文本内容并使用外部字体
  3. 绘制蓝色边框的矩形
  4. 添加图片(需要启用image特性)
  5. 将最终PDF保存到文件

要运行此示例,需要:

  1. 在Cargo.toml中添加printpdf依赖
  2. 准备Roboto-Regular.ttf字体文件
  3. 如需图片支持,启用printpdf的image特性

1 回复

Rust PDF生成库printpdf的使用指南

介绍

printpdf是一个纯Rust实现的PDF生成库,它允许开发者高效地创建、编辑和操作PDF文档。这个库提供了简单易用的API,支持文本、图像、矢量图形等多种PDF元素的添加和操作。

主要特性包括:

  • 纯Rust实现,无外部依赖
  • 支持创建多页PDF文档
  • 可添加文本、图像、矢量图形
  • 支持自定义字体
  • 可设置页面大小和方向
  • 支持图层操作

基本使用方法

添加依赖

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

[dependencies]
printpdf = "0.5.0"

创建简单PDF文档

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;

fn main() {
    // 创建新PDF文档
    let (doc, page1, layer1) = PdfDocument::new(
        "PDF_Document_title", 
        Mm(210.0),  // A4宽度
        Mm(297.0),  // A4高度
        "Layer 1"
    );
    
    // 获取当前图层
    let current_layer = doc.get_page(page1).get_layer(layer1);
    
    // 添加文本
    current_layer.use_text("Hello, printpdf!", 48.0, Mm(10.0), Mm(200.0), &Font::default());
    
    // 保存到文件
    doc.save(&mut BufWriter::new(File::create("test.pdf").unwrap())).unwrap();
}

添加图像

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;
use image::io::Reader as ImageReader;

fn main() {
    let (doc, page1, layer1) = PdfDocument::new("PDF with Image", Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer = doc.get_page(page1).get_layer(layer1);
    
    // 加载图像
    let img = ImageReader::open("example.png").unwrap().decode().unwrap();
    
    // 添加图像到PDF
    let image = Image::try_from(img).unwrap();
    image.add_to_layer(current_layer.clone(), None, None, None, None, None, None);
    
    doc.save(&mut BufWriter::new(File::create("image.pdf").unwrap())).unwrap();
}

绘制图形

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;

fn main() {
    let (doc, page1, layer1) = PdfDocument::new("PDF with Shapes", Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer = doc.get_page(page1).get_layer(layer1);
    
    // 绘制矩形
    let line = Line {
        points: vec![
            (Point::new(Mm(20.0), Mm(20.0)), false),
            (Point::new(Mm(20.0), Mm(50.0)), false),
            (Point::new(Mm(50.0), Mm(50.0)), false),
            (Point::new(Mm(50.0), Mm(20.0)), false),
            (Point::new(Mm(20.0), Mm(20.0)), false),
        ],
        is_closed: true,
        has_fill: true,
        has_stroke: true,
        is_clipping_path: false,
    };
    
    current_layer.add_shape(line);
    
    doc.save(&mut BufWriter::new(File::create("shapes.pdf").unwrap())).unwrap();
}

高级功能

使用自定义字体

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;

fn main() {
    let (doc, page1, layer1) = PdfDocument::new("PDF with Custom Font", Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer = doc.get_page(page1).get_layer(layer1);
    
    // 加载字体文件
    let font_data = std::fs::read("custom_font.ttf").unwrap();
    let font = doc.add_external_font(font_data.as_slice()).unwrap();
    
    // 使用自定义字体
    current_layer.use_text("Custom Font Text", 48.0, Mm(10.0), Mm(200.0), &font);
    
    doc.save(&mut BufWriter::new(File::create("custom_font.pdf").unwrap())).unwrap();
}

创建多页文档

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;

fn main() {
    let (doc, page1, layer1) = PdfDocument::new("Multi-page PDF", Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer = doc.get_page(page1).get_layer(layer1);
    current_layer.use_text("Page 1", 48.0, Mm(10.0), Mm(200.0), &Font::default());
    
    // 添加第二页
    let (page2, layer2) = doc.add_page(Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer2 = doc.get_page(page2).get_layer(layer2);
    current_layer2.use_text("Page 2", 48.0, Mm(10.0), Mm(200.0), &Font::default());
    
    doc.save(&mut BufWriter::new(File::create("multi_page.pdf").unwrap())).unwrap();
}

完整示例

以下是一个综合示例,展示如何创建一个包含文本、图像和图形的多页PDF文档:

use printpdf::*;
use std::fs::File;
use std::io::BufWriter;
use image::io::Reader as ImageReader;

fn main() {
    // 创建多页PDF文档
    let (doc, page1, layer1) = PdfDocument::new("Comprehensive PDF Example", Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer = doc.get_page(page1).get_layer(layer1);
    
    // 第一页添加文本
    current_layer.use_text("First Page - Title", 36.0, Mm(50.0), Mm(250.0), &Font::default());
    
    // 第一页添加矩形
    let rect = Line {
        points: vec![
            (Point::new(Mm(30.0), Mm(30.0)), false),
            (Point::new(Mm(30.0), Mm(100.0)), false),
            (Point::new(Mm(100.0), Mm(100.0)), false),
            (Point::new(Mm(100.0), Mm(30.0)), false),
            (Point::new(Mm(30.0), Mm(30.0)), false),
        ],
        is_closed: true,
        has_fill: true,
        has_stroke: true,
        is_clipping_path: false,
    };
    current_layer.add_shape(rect);
    
    // 添加第二页
    let (page2, layer2) = doc.add_page(Mm(210.0), Mm(297.0), "Layer 1");
    let current_layer2 = doc.get_page(page2).get_layer(layer2);
    
    // 第二页添加文本
    current_layer2.use_text("Second Page - Image Example", 36.0, Mm(50.0), Mm(250.0), &Font::default());
    
    // 第二页添加图像
    if let Ok(img) = ImageReader::open("example.png").unwrap().decode() {
        let image = Image::try_from(img).unwrap();
        image.add_to_layer(
            current_layer2.clone(), 
            Some(Mm(30.0)),  // x坐标
            Some(Mm(30.0)),  // y坐标
            Some(Mm(100.0)), // 宽度
            Some(Mm(100.0)), // 高度
            None,            // 旋转
            None             // 透明度
        );
    }
    
    // 保存PDF文件
    doc.save(&mut BufWriter::new(File::create("comprehensive.pdf").unwrap())).unwrap();
}

注意事项

  1. printpdf目前主要专注于PDF生成,对PDF编辑功能支持有限
  2. 对于复杂布局,可能需要手动计算坐标位置
  3. 性能方面,对于非常大的文档可能需要优化
  4. 某些高级PDF特性可能不支持

printpdf是一个功能强大且易于使用的PDF生成库,特别适合需要以编程方式生成PDF文档的Rust应用程序。

回到顶部