Kilian Schuettler 30a0f1beb7 initial-commit
2025-01-31 01:44:54 +01:00

126 lines
3.9 KiB
Rust

extern crate pdf;
use std::collections::HashMap;
use std::env::args;
use pdf::content::{FormXObject, Op, serialize_ops};
use pdf::error::PdfError;
use pdf::file::{FileOptions, Log};
use pdf::font::{Font, FontData, TFont};
use pdf::object::*;
use pdf::primitive::{PdfString, Primitive, Name};
fn run() -> Result<(), PdfError> {
let path = args().nth(1).expect("no file given");
println!("read: {}", path);
let mut file = FileOptions::cached().open(&path)?;
let mut to_update_field: Option<_> = None;
let font = Font {
data: FontData::TrueType(TFont{
base_font: Some(Name::from("Helvetica")),
first_char: None,
font_descriptor: None,
last_char: None,
widths: None,
}),
encoding: Some(pdf::encoding::Encoding::standard()),
name: None,
subtype: pdf::font::FontType::TrueType,
to_unicode: None,
_other: Default::default()
};
let font_name = Name::from("Helvetica");
let font = file.create(font)?;
let mut fonts = HashMap::new();
fonts.insert("Helvetica".into(), font.into());
let resources = Resources {
fonts,
.. Default::default()
};
let resources = file.create(resources)?;
let page0 = file.get_page(0).unwrap();
let annots = page0.annotations.load(&file.resolver()).expect("can't load annotations");
for annot in &*annots {
if let Some(ref a) = annot.appearance_streams {
let normal = file.resolver().get(a.normal);
if let Ok(normal) = normal {
match *normal {
AppearanceStreamEntry::Single(ref s) => {
//dbg!(&s.stream.resources);
let form_dict = FormDict {
resources: Some(resources.clone().into()),
.. (**s.stream).clone()
};
let ops = vec![
Op::Save,
Op::TextFont { name: font_name.clone(), size: 14.0 },
Op::TextDraw { text: PdfString::from("Hello World!") },
Op::EndText,
Op::Restore
];
let stream = Stream::new(form_dict, serialize_ops(&ops)?);
let normal2 = AppearanceStreamEntry::Single(FormXObject { stream });
file.update(a.normal.get_inner(), normal2)?;
}
_ => {}
}
}
}
}
if let Some(ref forms) = file.get_root().forms {
println!("Forms:");
for field in forms.fields.iter().take(1) {
print!(" {:?} = ", field.name);
match field.value {
Primitive::String(ref s) => println!("{}", s.to_string_lossy()),
Primitive::Integer(i) => println!("{}", i),
Primitive::Name(ref s) => println!("{}", s),
ref p => println!("{:?}", p),
}
if to_update_field.is_none() {
to_update_field = Some(field.clone());
}
}
}
if let Some(to_update_field) = to_update_field {
println!("\nUpdating field:");
println!("{:?}\n", to_update_field);
let text = "Hello World!";
let new_value: PdfString = PdfString::new(text.into());
let mut updated_field = (*to_update_field).clone();
updated_field.value = Primitive::String(new_value);
//dbg!(&updated_field);
let reference = file.update(
to_update_field.get_ref().get_inner(),
updated_field,
)?;
file.save_to("output/out.pdf")?;
println!("\nUpdated field:");
//println!("{:?}\n", reference);
}
Ok(())
}
fn main() {
if let Err(e) = run() {
println!("{e}");
}
}