pdfium-impl-page-objects-edit
What this skill covers
A PDF page holds a collection of page objects: text, path, image, shading, and
XObject form objects. This skill covers MUTATING that collection: creating
objects, adding and removing them, transforming them with a PdfMatrix, and
relocating them between pages with PdfPageGroupObject and the
copy_to_page / move_to_page methods.
For reading and inspecting existing page objects see
pdfium-syntax-page-objects. For copying whole pages between documents see
pdfium-impl-multi-page. For PdfPoints and coordinate geometry see
pdfium-core-coordinates. Default API surface here is 0.9.x.
Quick reference
| Goal | Call |
|---|---|
| Get a mutable collection | page.objects_mut() |
| Create and add an image in one step | objects.create_image_object(x, y, &image, w, h) |
| Create and add a bezier path | objects.create_path_object_bezier(...) |
| Build a detached image object | PdfPageImageObject::new(&document, &image) |
| Attach a detached object | objects.add_image_object(obj) / add_path_object(obj) |
| Remove an object | objects.remove_object(obj) / remove_object_at_index(i) |
| Transform an object | object.apply_matrix(matrix) |
| Relocate an object | object.copy_to_page(&mut page) / move_to_page(&mut page) |
ALWAYS call objects_mut() to mutate. objects() returns an immutable
&PdfPageObjects; the create_, add_, and remove_ methods all take
&mut self and will not compile against it.
Two ways to create an object
pdfium-render offers two distinct construction styles. NEVER mix them for the
same object.
Style A : create_* (build and add in one call)
The create_* methods on PdfPageObjects build the object AND add it to the
page, returning the added PdfPageObject:
use pdfium_render::prelude::*;
let object = page.objects_mut().create_image_object(
PdfPoints::new(100.0), // x
PdfPoints::new(500.0), // y
&image, // an image::DynamicImage
Some(PdfPoints::new(200.0)), // width
Some(PdfPoints::new(150.0)), // height
)?;
Path variants: create_path_object_line, create_path_object_bezier,
create_path_object_rect, create_path_object_circle,
create_path_object_circle_at, create_path_object_ellipse,
create_path_object_ellipse_at. Also create_text_object.
Style B : new then add_* (build detached, then attach)
PdfPageImageObject constructors build a detached object bound to a document.
A separate add_image_object call attaches it to a page:
let object = PdfPageImageObject::new_from_jpeg_file(&document, "logo.jpg")?;
let added = page.objects_mut().add_image_object(object)?;
NEVER call both a create_* method and an add_* method for the same object:
create_* already added it. A second add_* adds a duplicate or fails.
PdfPageImageObject constructors
| Constructor | Use |
|---|---|
new(&document, &image) |
image at its natural size |
new_with_width(&document, &image, width) |
width fixed, height from aspect ratio |
new_with_height(&document, &image, height) |
height fixed, width from aspect ratio |
new_with_size(&document, &image, width, height) |
exact size |
new_from_jpeg_file(&document, path) |
load straight from a JPEG file (0.8.29) |
new_from_jpeg_reader(&document, reader) |
load from any Read + Seek (0.8.29) |
Every constructor returns Result<PdfPageImageObject, PdfiumError> and takes
the PdfDocument the object will belong to. Use set_image() to replace the
image, get_raw_image() / get_processed_image() to read it back.
Transforming an object with PdfMatrix
A PdfPageObject carries a transformation matrix. Apply a PdfMatrix with
apply_matrix:
use pdfium_render::prelude::*;
let matrix = PdfMatrix::IDENTITY
.scale(2.0, 2.0)?
.rotate_clockwise_degrees(45.0)?;
object.apply_matrix(matrix)?;
PdfMatrix factory methods (translate, scale, rotate_clockwise_degrees,
rotate_counter_clockwise_degrees, flip_horizontally, flip_vertically)
each return Result<PdfMatrix, PdfiumError>, so chain them with ?.
| Method on a page object | Effect |
|---|---|
apply_matrix(matrix) |
compose matrix onto the object's current transform |
transform(a, b, c, d, e, f) |
apply a raw six-value matrix |
reset_matrix(matrix) |
replace the object's transform |
reset_matrix_to_identity() |
clear the transform |
matrix() |
read the current transform |
Version trap: set_matrix() was deprecated in 0.8.15 and removed in 0.9.0.
ALWAYS use apply_matrix() (or reset_matrix() to replace rather than
compose).
Removing objects
// By value : you must own the PdfPageObject
let removed = page.objects_mut().remove_object(object)?;
// By index
let removed = page.objects_mut().remove_object_at_index(0)?;
Both return the removed PdfPageObject. Version trap: the 0.6.x names
delete_object / delete_object_at_index were renamed to remove_object /
remove_object_at_index in 0.7.4.
Relocating objects between pages
NEVER hand-roll object moving as remove-from-page-A then add-to-page-B. That pattern fights the borrow checker, because removing requires a mutable borrow of one page's objects while inserting requires a mutable borrow of another (issues #60, #25). ALWAYS use the dedicated relocation methods.
| Method | Source | Effect |
|---|---|---|
object.copy_to_page(&mut page) |
a single PdfPageObject |
duplicate onto page |
object.move_to_page(&mut page) |
a single PdfPageObject |
move onto page |
group.copy_to_page(&mut page) |
a PdfPageGroupObject |
duplicate the whole group |
group.move_to_page(&mut page) |
a PdfPageGroupObject |
move the whole group |
PdfPageGroupObject collects several objects so one transform or one
relocation applies to all of them at once. Build a group with
objects.create_group(...) or create_empty_group(), then call apply_matrix,
copy_to_page, move_to_page, or move_to_annotation on the group.
Version trap: the PdfPageGroupObject::copy_onto_new_page_* methods were
removed in 0.9.0. ALWAYS use copy_to_page().
Common failures (quick triage)
| Symptom | Likely cause | Fix |
|---|---|---|
compile error: method takes &mut self |
called a mutator on objects() |
use objects_mut() |
compile error: set_matrix not found |
removed 0.9.0 name | use apply_matrix() |
compile error: copy_onto_new_page not found |
removed 0.9.0 name | use copy_to_page() |
compile error: delete_object not found |
renamed in 0.7.4 | use remove_object() |
| borrow-checker error moving an object | hand-rolled remove-then-insert | use move_to_page() |
CannotMoveObjectAcrossDocuments |
move_to_page targeted another document's page |
see pdfium-impl-multi-page |
| duplicate object on the page | both create_* and add_* called |
use exactly one construction style |
Reference files
references/methods.md: complete signatures forPdfPageObjects,PdfPageImageObject,PdfMatrix,PdfPageGroupObject, and the object transform methods, with version annotations.references/examples.md: verified editing code, from stamping an image to moving objects between pages.references/anti-patterns.md: real editing failures, why each fails, and the fix.
Companion skills
pdfium-syntax-page-objects: reading and inspecting existing page objects.pdfium-impl-multi-page: copying whole pages between documents.pdfium-core-coordinates:PdfPoints,PdfRectvsPdfQuadPoints.pdfium-impl-saving: persisting the edited document.