توليد تقارير PDF بلغة Rust باستخدام مكتبة printpdf
في تطوير الويب الحديث، لا يزال إنشاء مستندات PDF مهمة مطلوبة - بدءًا من إعداد الفواتير والتقارير وصولاً إلى تصدير البيانات. إذا كان مشروعك مكتوبًا بلغة Rust أو كنت تستخدمها للواجهة الخلفية، فإن مكتبة printpdf ستكون أداة موثوقة لتوليد PDF. في هذه المقالة، سنستعرض إمكانيات printpdf، ونعرض أمثلة برمجية، ونناقش كيفية دمجها في مشروع تعليمي.
ما هي printpdf؟
printpdf هي مكتبة Rust خالصة لإنشاء مستندات PDF بدون تبعيات خارجية. تتيح لك:
- إنشاء مستندات متعددة الصفحات بمحتوى مخصص
- إضافة نصوص بخطوط مختلفة (بما في ذلك TrueType و OpenType)
- رسم خطوط ومستطيلات وأشكال بيضاوية ومسارات معقدة
- تضمين الصور (JPEG, PNG)
- العمل مع الجداول والشبكات
- إدارة مساحات الألوان (RGB, CMYK, Grayscale)
الميزة الرئيسية هي الاستقلالية الكاملة: لا حاجة لتثبيت LaTeX أو wkhtmltopdf أو أنظمة أخرى. وهذا يجعل printpdf خيارًا مثاليًا للموقع التعليمي pythonlib.ru، حيث تكون بساطة النشر وقابلية تكرار الأمثلة أمرًا مهمًا.
التثبيت وأول مستند
أضف التبعية في ملف Cargo.toml:
[dependencies]printpdf = "0.7"لننشئ أبسط PDF مع نص:
use printpdf::*;use std::fs::File;use std::io::BufWriter;
fn main() { // إنشاء مستند بحجم A4 let (doc, page1, layer1) = PdfDocument::new( "أول PDF لي", Mm(210.0), Mm(297.0), "Layer 1" );
// الحصول على الخط الافتراضي let font = doc.add_builtin_font(BuiltinFont::Helvetica).unwrap();
// إضافة نص let current_layer = doc.get_page(page1).get_layer(layer1); current_layer.use_text( "مرحبًا، PythonLib!", 24.0, Mm(10.0), Mm(280.0), &font );
// حفظ الملف let file = File::create("hello.pdf").unwrap(); let writer = BufWriter::new(file); doc.save(&mut writer).unwrap();
println!("تم إنشاء PDF: hello.pdf");}يقوم هذا الكود بإنشاء PDF من صفحة واحدة مع نص. لاحظ: use_text يستقبل الإحداثيات بالميليمترات، وحجم الخط بالنقاط.
العمل مع الرسومات والألوان
تدعم printpdf رسم الأشكال الأولية. لننشئ تقريرًا مع خط ومستطيل مملوء:
use printpdf::*;
fn create_report() -> (PdfDocumentReference, PdfPageIndex, PdfLayerIndex) { let (doc, page, layer) = PdfDocument::new( "تقرير", Mm(210.0), Mm(297.0), "Data" );
let layer = doc.get_page(page).get_layer(layer);
// رسم خط أحمر let points = vec![ (Point::new(Mm(20.0), Mm(250.0)), false), (Point::new(Mm(190.0), Mm(250.0)), false), ]; let line = Line { points, is_closed: false, }; layer.set_color(Color::Rgb(Rgb::new(1.0, 0.0, 0.0))); layer.add_line(line);
// مستطيل أزرق مملوء let rect = Polygon { vertices: vec![ (Point::new(Mm(50.0), Mm(200.0)), false), (Point::new(Mm(150.0), Mm(200.0)), false), (Point::new(Mm(150.0), Mm(180.0)), false), (Point::new(Mm(50.0), Mm(180.0)), false), ], is_closed: true, }; layer.set_color(Color::Rgb(Rgb::new(0.0, 0.0, 1.0))); layer.add_polygon(rect);
(doc, page, layer)}يتم تحديد الألوان في نطاق 0.0–1.0. لاستخدام CMYK، استخدم Color::Cmyk(Cmyk::new(0.0, 1.0, 0.0, 0.0)).
تضمين الصور
لنضف شعارًا إلى التقرير:
use printpdf::*;use std::fs::Fi