使用Rust的printpdf crate(0.7.0)如何获取文本的毫米宽度?
在printpdf 0.7.0中测量文本宽高并实现居中
核心解决方案
printpdf 0.7.0本身没有内置文本测量API,但可以借助它底层依赖的fontdue库来计算文本的宽高,步骤如下:
1. 添加依赖
在Cargo.toml中加入fontdue:
[dependencies] printpdf = "0.7.0" fontdue = "0.8.0"
2. 加载字体并计算文本尺寸
通过fontdue解析字体文件,计算文本的布局数据,再转换为毫米单位适配PDF页面:
use std::{fs::File, io::Read, io::BufWriter}; use printpdf::{Mm, PdfDocument}; use fontdue::Font; fn main() { let doc = PdfDocument::empty("PDF test"); let (page1, layer1) = doc.add_page(Mm(210.0), Mm(297.0), "page 1"); let page_layer = doc.get_page(page1).get_layer(layer1); // 读取字体文件,同时供printpdf和fontdue使用 let mut font_file = File::open("C:\\Windows\\Fonts\\Roboto-Regular.ttf").unwrap(); let mut font_data = Vec::new(); font_file.read_to_end(&mut font_data).unwrap(); // 初始化printpdf字体对象 let print_font = doc.add_external_font(&font_data).unwrap(); // 初始化fontdue字体对象用于测量 let font = Font::from_bytes(&font_data, fontdue::FontSettings::default()).unwrap(); let text = "Hello World!"; let font_size = 12.0; // 计算文本布局信息(宽度、基线偏移等) let (metrics, _) = font.layout(text, font_size, 0.0); // 像素转毫米:1英寸=96像素=25.4毫米 let px_to_mm = 25.4 / 96.0; let text_width_mm = metrics.width * px_to_mm; let text_height_mm = (metrics.ascent - metrics.descent) * px_to_mm; // 计算居中坐标 let page_width = 210.0; let page_height = 297.0; let center_x = (page_width - text_width_mm) / 2.0; // 从顶部往下10mm的位置 let center_y = page_height - 10.0; // 绘制居中文本 page_layer.begin_text_section(); page_layer.set_font(&print_font, font_size); page_layer.set_text_cursor(Mm(center_x), Mm(center_y)); page_layer.set_line_height(font_size); page_layer.write_text(text, &print_font); page_layer.end_text_section(); doc.save(&mut BufWriter::new(File::create("doc.pdf").unwrap())).unwrap(); }
其他可行测量方式
- Harfbuzz + Rusttype组合:如果需要处理复杂排版(如多语言、连字、字形替换),可以用Harfbuzz做字形布局,再用Rusttype测量每个字形的宽高并累加,精度更高但实现更繁琐。
- 预渲染位图测量:将文本渲染为位图后获取宽高,这种方式开销大,仅适合不需要矢量精度的特殊场景。
内容的提问来源于stack exchange,提问作者magg
相关产品推荐
相关产品推荐

