126 lines
3.9 KiB
Rust
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}");
|
|
}
|
|
}
|