1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
//! A second, compatible spelling of the document API, built on the facade.
//!
//! This module holds an alternative API surface over [`PdfDocument`] that
//! mirrors the call shapes of a widely used PDF library, so existing code
//! written against that library ports over with mechanical edits. It adds no
//! behaviour of its own: every method here delegates to the facade, and every
//! error it returns is an existing [`crate::Error`] variant — no new error
//! variants are introduced.
//!
//! Conventions every lane follows:
//!
//! - Coordinates are top-left origin, y down, in points, matching the rest of
//! the facade. Lanes convert at the boundary where the mirrored spelling
//! assumes otherwise.
//! - This module is feature-free: it must not pull optional dependencies
//! (no `ort`, no model tiers). Lanes needing a model go through the
//! facade's existing feature-gated paths.
//!
//! # Lane ownership
//!
//! Five lanes fill this module in parallel, and each touches only its own
//! files so no two lanes ever edit the same code:
//!
//! | Lane | Rust file here | Python native file | Python names file |
//! |---|---|---|
//! | P0 value types | `geometry.rs` | `compat/geometry.rs` | `_compat_geometry.py` |
//! | L1 text | `text.rs` | `compat/text.rs` | `_compat_text.py` |
//! | L2 document ops | `document.rs` | `compat/document.rs` | `_compat_document.py` |
//! | L3 images | `pixmap.rs` | `compat/pixmap.rs` | `_compat_pixmap.py` |
//! | L4 editing | `edit.rs` | `compat/edit.rs` | `_compat_edit.py` |
//! | L5 module entry points | `functions.rs` | — | — |
//!
//! Each lane adds its methods as further `impl Page` / `impl PageMut` blocks
//! (or `impl PdfDocument` blocks, or extension traits) inside its own file —
//! multiple inherent impl blocks across files of one crate are fine. The L5
//! free functions live in `functions.rs`. This file holds only the shared
//! views below; lane code never lands here. The Node binding mirrors the
//! layout under `pdf-node/src/compat/`.
//!
//! # Borrowing
//!
//! [`Page`] borrows the document shared (`&PdfDocument`) for the read lanes;
//! [`PageMut`] borrows it exclusively (`&mut PdfDocument`) for the editing
//! lane. That is the facade's existing rule — [`PdfDocument`] is `Send + Sync`
//! and not `Clone`, mutation goes through `&mut self` or a scoped `_mut`
//! accessor ([`MetadataMut`](crate::MetadataMut), [`PdfFormMut`](crate::PdfFormMut))
//! — so no new interior mutability is introduced here. (The interior
//! mutability [`PdfDocument`] already has, the diagnostics collector, stays an
//! implementation detail of the facade.)
// Copyright (c) 2026 Innovation Trigger B.V.
//
// PDFluent is available under two licences, at your option: the GNU AGPLv3, or
// the PDFluent Commercial Licence. See the LICENSE file in this repository --
// that file travels with the copy you received, which a URL does not.
use cratePdfDocument;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
/// Borrowed handle to a single page for the compatible API.
///
/// A read-side view: the text (L1), document (L2) and image (L3) lanes add
/// their methods as further `impl Page` blocks in their own files. The index
/// is 0-based, matching [`PdfDocument::page`]'s numbering once adjusted (that
/// method takes a 1-based page number; see [`new`](Self::new)).
/// Exclusively borrowed handle to a single page for the compatible API.
///
/// The editing lane (L4) adds its methods as further `impl PageMut` blocks in
/// `edit.rs`. Exclusive rather than shared because every mutation on
/// [`PdfDocument`] takes `&mut self`; holding `&mut` here keeps the compatible
/// spelling under the same rule instead of adding interior mutability.
/// A dynamically shaped value for structures no recording pins down yet.
///
/// Lanes replace `Value` fields and returns with typed structs as recordings
/// land; until then this keeps the signatures compilable and explicit about
/// what is still unshaped.
/// Compat failure classes: one kind per recorded exception shape.
///
/// Every lane method that can fail returns [`crate::Error`]; the kind records
/// which recorded exception class the failure answers to, so the bindings
/// raise the matching error. The mapping from recorded classes:
///
/// | Recorded classes | Kind |
/// |---|---|
/// | `TypeError`, `AttributeError` | [`WrongType`](Self::WrongType) |
/// | `ValueError`, `AssertionError`, `ZeroDivisionError` | [`BadValue`](Self::BadValue) |
/// | `KeyError` | [`UnknownKey`](Self::UnknownKey) |
/// | `IndexError` | [`IndexOutOfRange`](Self::IndexOutOfRange) |
/// | `FileNotFoundError` | [`MissingFile`](Self::MissingFile) |
/// | `FileDataError`, `FzErrorFormat` | [`UnreadableFile`](Self::UnreadableFile) |
/// | `EmptyFileError` | [`EmptyFile`](Self::EmptyFile) |
/// | `FzErrorSystem`, `FzErrorArgument`, `RuntimeError`, `Exception` | [`EngineFault`](Self::EngineFault) |
/// | `ModuleNotFoundError` | [`MissingComponent`](Self::MissingComponent) |
/// | `FitzDeprecation` | [`Deprecation`](Self::Deprecation) |
///
/// No new [`crate::Error`] variant is introduced: file failures map onto the
/// existing file variants, and everything else rides inside [`crate::Error::Io`]
/// with [`std::io::ErrorKind::InvalidInput`], following the `OptionsError`
/// pattern, readable through [`crate::Error::compat_kind`].
/// Typed cause carried inside the I/O error [`ErrorKind::to_error`] builds.
/// Build the shared "not supported in this version" error for a compat member.
///
/// Every silent no-op on the compatible surface fails with this instead of
/// returning success: one [`crate::Error::Unsupported`] kind (no new variants
/// in 1.x) whose reason names the member and the differences file. Bindings
/// surface the reason verbatim.