pdfium-render Page Objects (Read and Inspect)
A PDF page's visible content is a flat list of page objects: text runs, vector paths, images, shadings, and XObject form containers. This skill covers reading and inspecting that list: reaching it, iterating it, discriminating object types, reading object geometry, and recursing into nested containers.
This skill is read and inspect only. Creating, transforming, and deleting page objects is the scope of pdfium-impl-page-objects-edit.
Quick Reference: Object Access Flow
PdfPage
.objects() -> &PdfPageObjects immutable collection (inspect)
PdfPageObjects (methods from the PdfPageObjectsCommon trait)
.len() -> usize
.is_empty() -> bool
.get(index) -> Result<PdfPageObject, PdfiumError> index is usize
.first() -> Result<PdfPageObject, PdfiumError>
.last() -> Result<PdfPageObject, PdfiumError>
.iter() -> PdfPageObjectsIterator yields PdfPageObject
PdfPageObject (enum, six variants)
match it, or narrow with .as_text_object() etc.
PdfPageObjectCommon (trait on every object)
.bounds() -> Result<PdfQuadPoints, PdfiumError>
.width() .height() -> Result<PdfPoints, PdfiumError>
.has_transparency() -> bool
.is_inside_rect(&r) / .does_overlap_rect(&r) -> bool
ALWAYS reach page objects through PdfPage::objects(). NEVER assume a page
object can be inspected standalone; it borrows from its PdfPage.
1. Reaching the Object Collection
PdfPage::objects() returns &PdfPageObjects<'a>, the immutable collection
of every content object on the page.
pub fn objects(&self) -> &PdfPageObjects<'a>
For mutation (adding, transforming, removing objects) the page exposes
objects_mut(); that path is documented in pdfium-impl-page-objects-edit.
This skill uses only the immutable objects().
PdfPageObjects gets its methods from the PdfPageObjectsCommon trait:
fn len(&self) -> usize
fn is_empty(&self) -> bool
fn get(&self, index: usize) -> Result<PdfPageObject<'a>, PdfiumError>
fn first(&self) -> Result<PdfPageObject<'a>, PdfiumError>
fn last(&self) -> Result<PdfPageObject<'a>, PdfiumError>
fn iter(&self) -> PdfPageObjectsIterator<'a>
Page objects are indexed by usize. This differs from pages, which use the
PdfPageIndex (c_int) type. ALWAYS index page objects with usize. An
out-of-range index returns PdfiumError::PageObjectIndexOutOfBounds.
2. The PdfPageObject Enum
PdfPageObject<'a> is an enum with six variants, each wrapping a concrete
object type:
pub enum PdfPageObject<'a> {
Text(PdfPageTextObject<'a>),
Path(PdfPagePathObject<'a>),
Image(PdfPageImageObject<'a>),
Shading(PdfPageShadingObject<'a>),
XObjectForm(PdfPageXObjectFormObject<'a>),
Unsupported(PdfPageUnsupportedObject<'a>),
}
Text: a run of rendered text. Character-level reading is pdfium-syntax-text.Path: a vector path (lines, bezier curves, fills).Image: a raster image embedded on the page.Shading: a gradient or shading pattern.XObjectForm: a reusable content container holding nested page objects.Unsupported: an object type pdfium-render does not model further.
ALWAYS handle the Unsupported variant in a match. NEVER write a match
on only five variants and assume it compiles; the enum has six.
3. Discriminating Object Type
Two ways to tell what kind of object you have.
A match on the enum is exhaustive and the compiler enforces coverage:
for object in page.objects().iter() {
match object {
PdfPageObject::Text(text) => { /* inspect text object */ }
PdfPageObject::Path(path) => { /* inspect path */ }
PdfPageObject::Image(image) => { /* inspect image */ }
PdfPageObject::Shading(shading) => { /* inspect shading */ }
PdfPageObject::XObjectForm(form) => { /* recurse, see section 5 */ }
PdfPageObject::Unsupported(_) => { /* skip */ }
}
}
Narrowing methods return an Option and are useful when only one type
matters:
fn as_text_object(&self) -> Option<&PdfPageTextObject<'_>>
fn as_path_object(&self) -> Option<&PdfPagePathObject<'_>>
fn as_image_object(&self) -> Option<&PdfPageImageObject<'_>>
fn as_shading_object(&self) -> Option<&PdfPageShadingObject<'_>>
fn as_x_object_form_object(&self) -> Option<&PdfPageXObjectFormObject<'_>>
Each returns Some(&...) only when the variant matches, otherwise None.
Mutable _mut variants exist for the edit skill.
ALWAYS treat a narrowing call as fallible: it returns None for every other
variant. NEVER unwrap() an as_*_object() result unless the variant is
already known.
4. Common Properties: the PdfPageObjectCommon Trait
PdfPageObjectCommon is implemented by every concrete object type. It carries
the geometry and transparency reads that work regardless of object kind:
fn bounds(&self) -> Result<PdfQuadPoints, PdfiumError>
fn width(&self) -> Result<PdfPoints, PdfiumError>
fn height(&self) -> Result<PdfPoints, PdfiumError>
fn has_transparency(&self) -> bool
fn is_inside_rect(&self, rect: &PdfRect) -> bool
fn does_overlap_rect(&self, rect: &PdfRect) -> bool
bounds() returns a PdfQuadPoints (a quadrilateral, because an object can
be rotated). Call .to_rect() on it for an axis-aligned PdfRect. All
geometry is in PdfPoints; converting to pixels is pdfium-core-coordinates.
is_inside_rect() and does_overlap_rect() answer spatial queries directly,
which is simpler and more reliable than comparing bounds() coordinates by
hand.
ALWAYS use is_inside_rect() / does_overlap_rect() for "is this object in
this region" checks. NEVER hand-compare quadrilateral corners for a spatial
test when the trait already provides it.
5. Recursing into XObject Form Containers
A PdfPageXObjectFormObject is a content container: it holds its own list of
nested page objects. PdfPage::objects().iter() yields the form container as
a single object; it does not flatten the container's children into the
page-level iteration.
PdfPageXObjectFormObject implements the same PdfPageObjectsCommon access
methods, so its children are reached the same way:
fn iter(&self) -> PdfPageObjectsIterator<'a>
fn len(&self) -> usize
fn get(&self, index: usize) -> Result<PdfPageObject<'a>, PdfiumError>
To inspect every object on a page including nested ones, write a recursive
visitor: for each object, if it is an XObjectForm, recurse into its
iter(). The repository text-extraction example documents exactly this:
text can live inside XObject form containers, so a complete extractor needs
the recursive walk.
ALWAYS recurse into XObjectForm objects when the task must see all content.
NEVER assume a single flat objects().iter() reaches nested objects; it
stops at the container.
6. Version Traps
| Item | 0.8.x | 0.9.x | Consequence |
|---|---|---|---|
PdfPageObjectCommon::bounds() return |
PdfRect before 0.8.28, Result<PdfQuadPoints, _> from 0.8.28 |
Result<PdfQuadPoints, PdfiumError> |
Code reading bounds() as a PdfRect fails to compile on 0.8.28+ |
| Text-object character reads | wrong characters before 0.8.31 (issue #98) | corrected | Reading characters per text object needs pdfium-render 0.8.31+ and a PDFium build at or above chromium build 6611 |
When the compiler reports "expected PdfRect, found PdfQuadPoints" on a
bounds() call, append .to_rect() or handle the quadrilateral. Reading the
characters that belong to a specific text object is pdfium-syntax-text;
respect the PDFium build requirement there.
Decision Tree: Inspecting Page Objects
What do I need from the page's objects?
How many objects
-> page.objects().len()
Walk every object on the page surface
-> page.objects().iter() then match the variant
Only one kind (for example, every image)
-> iter(), then .as_image_object() and keep the Some results
An object's position or size
-> PdfPageObjectCommon::bounds() / width() / height()
Objects inside a region
-> PdfPageObjectCommon::is_inside_rect() / does_overlap_rect()
Everything including nested content
-> recursive visitor : recurse into XObjectForm.iter()
Create / move / delete an object
-> not this skill : see pdfium-impl-page-objects-edit
ALWAYS / NEVER
- ALWAYS reach page objects through
PdfPage::objects(). - ALWAYS index page objects with
usize(notPdfPageIndex). - ALWAYS handle all six
PdfPageObjectvariants in amatch, includingUnsupported. - ALWAYS treat
as_*_object()as returning anOption. - ALWAYS recurse into
XObjectFormobjects to see nested content. - ALWAYS use
is_inside_rect()/does_overlap_rect()for spatial tests. - NEVER read
bounds()as aPdfRecton 0.8.28 or later; it is aPdfQuadPoints. - NEVER
unwrap()a narrowing call without knowing the variant. - NEVER assume
objects().iter()flattens XObject form children. - NEVER mutate objects through
objects(); mutation needsobjects_mut()and the edit skill.
Cross-References
- pdfium-impl-page-objects-edit : creating, transforming, and removing
page objects through
objects_mut(). - pdfium-syntax-text : reading text content and characters, including the PDFium build requirement for per-object character reads.
- pdfium-core-coordinates :
PdfQuadPoints,PdfRect,PdfPoints, and converting object geometry to pixels. - pdfium-core-architecture : where
PdfPageObjectssits in the ownership tree.
Reference Files
references/methods.md: signatures ofPdfPage::objects(), thePdfPageObjectsCommonandPdfPageObjectCommontraits, thePdfPageObjectenum, andPdfPageXObjectFormObject, with version notes.references/examples.md: verified Rust code for counting, iterating, discriminating, reading geometry, and recursing into containers.references/anti-patterns.md: real inspection failures with the cause and the fix.
Sources
API names and signatures verified on 2026-05-20 via WebFetch against the
package SOURCES.md:
https://docs.rs/pdfium-render/latest/pdfium_render/prelude/enum.PdfPageObject.htmlhttps://docs.rs/pdfium-render/latest/pdfium_render/prelude/struct.PdfPageObjects.htmlhttps://docs.rs/pdfium-render/latest/pdfium_render/prelude/trait.PdfPageObjectCommon.htmlhttps://docs.rs/pdfium-render/latest/pdfium_render/prelude/struct.PdfPageXObjectFormObject.htmlhttps://github.com/ajrcarey/pdfium-render(README, version history, issue #98).