Line data Source code
1 : // Copyright 2026 The Authors.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // https://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : // Typed message protocol for the PdfiumIsolate.
16 : //
17 : // All communication with the PDFium isolate uses this sealed class hierarchy.
18 : // Each message carries a [SendPort] for the response so that concurrent
19 : // requests can be tracked and matched independently.
20 : //
21 : // Future plans (text extraction, annotations, rendering) extend this protocol
22 : // by adding new [PdfiumCommand] subtypes without coupling their public APIs
23 : // to this file.
24 :
25 : import 'dart:isolate';
26 : import 'dart:typed_data';
27 :
28 : import 'pdf_types.dart';
29 : import '../rendering/pdf_page_size.dart';
30 :
31 : /// Base class for all commands sent to the [PdfiumIsolate].
32 : ///
33 : /// Each command carries a [replyPort] — the [SendPort] on which the isolate
34 : /// sends the [PdfiumResponse] for this specific request.
35 : sealed class PdfiumCommand {
36 : /// Creates a command with the given [replyPort].
37 11 : const PdfiumCommand(this.replyPort);
38 :
39 : /// The port on which the isolate must send the response for this command.
40 : final SendPort replyPort;
41 : }
42 :
43 : /// Initialise the PDFium library within the isolate.
44 : ///
45 : /// This is the first message sent after the isolate starts. The isolate
46 : /// responds with a [PdfiumInitResponse] carrying the [SendPort] for
47 : /// subsequent commands.
48 : class PdfiumInitCommand extends PdfiumCommand {
49 : /// Creates an init command.
50 10 : const PdfiumInitCommand(super.replyPort, this.dylibPath);
51 :
52 : /// The filesystem path to the PDFium dynamic library, or `null` to let
53 : /// the isolate auto-detect the library via [_openLibrary].
54 : ///
55 : /// Pass a non-null path to override auto-detection (e.g. for the legacy
56 : /// `third_party/pdfium_bin/` developer layout populated by
57 : /// `make fetch_pdfium`). Pass `null` when the native-assets hook has staged
58 : /// the library (pub.dev users, CI without `make fetch_pdfium`) or when
59 : /// loading from the process image (iOS static link).
60 : final String? dylibPath;
61 : }
62 :
63 : /// Load a PDF document from raw bytes.
64 : ///
65 : /// The isolate calls `FPDF_LoadMemDocument64()` and returns a document token
66 : /// (an opaque integer handle) that the caller uses in subsequent commands.
67 : class PdfiumLoadDocumentCommand extends PdfiumCommand {
68 : /// Creates a load-document command.
69 10 : const PdfiumLoadDocumentCommand(super.replyPort, this.bytes);
70 :
71 : /// The raw PDF bytes to load.
72 : final Uint8List bytes;
73 : }
74 :
75 : /// Read the Info dictionary metadata for an open document.
76 : ///
77 : /// The isolate reads all eight standard Info dictionary fields using
78 : /// `FPDF_GetMetaText()` and returns a [PdfiumGetMetadataResponse].
79 : class PdfiumGetMetadataCommand extends PdfiumCommand {
80 : /// Creates a get-metadata command for the document identified by [token].
81 2 : const PdfiumGetMetadataCommand(super.replyPort, this.token);
82 :
83 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
84 : final int token;
85 : }
86 :
87 : /// Read document-level properties (version and file identifiers).
88 : ///
89 : /// The isolate calls `FPDF_GetFileVersion()` and `FPDF_GetFileIdentifier()`
90 : /// in a single round-trip and returns a [PdfiumGetDocumentInfoResponse].
91 : class PdfiumGetDocumentInfoCommand extends PdfiumCommand {
92 : /// Creates a get-document-info command for the document identified by [token].
93 2 : const PdfiumGetDocumentInfoCommand(super.replyPort, this.token);
94 :
95 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
96 : final int token;
97 : }
98 :
99 : /// Close a previously loaded document and release its native handle.
100 : ///
101 : /// The isolate calls `FPDF_CloseDocument()` and responds with a
102 : /// [PdfiumCloseDocumentResponse].
103 : class PdfiumCloseDocumentCommand extends PdfiumCommand {
104 : /// Creates a close-document command for the document identified by [token].
105 10 : const PdfiumCloseDocumentCommand(super.replyPort, this.token);
106 :
107 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
108 : final int token;
109 : }
110 :
111 : /// Get the total number of pages in an open document.
112 : ///
113 : /// The isolate calls `FPDF_GetPageCount()` and responds with a
114 : /// [PdfiumGetPageCountResponse].
115 : class PdfiumGetPageCountCommand extends PdfiumCommand {
116 : /// Creates a get-page-count command for the document identified by [token].
117 7 : const PdfiumGetPageCountCommand(super.replyPort, this.token);
118 :
119 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
120 : final int token;
121 : }
122 :
123 : /// Extract plain text from a single page of an open document.
124 : ///
125 : /// The isolate loads the page, loads the text page, extracts all text, then
126 : /// closes both handles in a single round-trip. The response is a
127 : /// [PdfiumExtractPageTextResponse] carrying the result.
128 : ///
129 : /// [PdfiumExtractPageTextResponse.hasTextLayer] is true whenever PDFium
130 : /// extracts at least one character from the page — the only reliable signal
131 : /// that a text layer exists.
132 : class PdfiumExtractPageTextCommand extends PdfiumCommand {
133 : /// Creates an extract-page-text command.
134 2 : const PdfiumExtractPageTextCommand(
135 : super.replyPort,
136 : this.token,
137 : this.pageIndex,
138 : );
139 :
140 : /// The opaque document token.
141 : final int token;
142 :
143 : /// Zero-based index of the page to extract text from.
144 : final int pageIndex;
145 : }
146 :
147 : /// Get the intrinsic size of a single page of an open document.
148 : ///
149 : /// The isolate calls `FPDF_GetPageWidthF()` and `FPDF_GetPageHeightF()` and
150 : /// returns a [PdfiumGetPageSizeResponse] containing a [PdfPageSize].
151 : class PdfiumGetPageSizeCommand extends PdfiumCommand {
152 : /// Creates a get-page-size command.
153 3 : const PdfiumGetPageSizeCommand(super.replyPort, this.token, this.pageIndex);
154 :
155 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
156 : final int token;
157 :
158 : /// Zero-based index of the page whose size is requested.
159 : final int pageIndex;
160 : }
161 :
162 : /// Render a single page of an open document to a BGRA pixel buffer.
163 : ///
164 : /// The isolate allocates a bitmap of [pixelWidth] × [pixelHeight] pixels,
165 : /// fills it with [backgroundColor] (in `0xAARRGGBB` format), calls
166 : /// `FPDF_RenderPageBitmap()` with the given [renderFlags], copies the
167 : /// resulting BGRA bytes into a [Uint8List], then destroys the bitmap handle
168 : /// and closes the page handle.
169 : ///
170 : /// Render flags are the raw PDFium integer flags (e.g. `FPDF_ANNOT`,
171 : /// `FPDF_LCD_TEXT`). The public [PdfDocument.renderPage] method converts
172 : /// [PdfRenderOptions] fields to these flags before dispatching this command.
173 : class PdfiumRenderPageCommand extends PdfiumCommand {
174 : /// Creates a render-page command.
175 3 : const PdfiumRenderPageCommand(
176 : super.replyPort,
177 : this.token,
178 : this.pageIndex,
179 : this.pixelWidth,
180 : this.pixelHeight,
181 : this.renderFlags,
182 : this.backgroundColor,
183 : );
184 :
185 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
186 : final int token;
187 :
188 : /// Zero-based index of the page to render.
189 : final int pageIndex;
190 :
191 : /// Width of the output bitmap in pixels.
192 : final int pixelWidth;
193 :
194 : /// Height of the output bitmap in pixels.
195 : final int pixelHeight;
196 :
197 : /// PDFium render flags (e.g. `FPDF_ANNOT`, `FPDF_LCD_TEXT`).
198 : final int renderFlags;
199 :
200 : /// Background colour in `0xAARRGGBB` format, used to fill the bitmap before
201 : /// rendering. Opaque white is `0xFFFFFFFF`.
202 : final int backgroundColor;
203 : }
204 :
205 : /// Retrieve the complete bookmark/outline tree for an open document.
206 : ///
207 : /// The isolate walks the bookmark tree using `FPDFBookmark_GetFirstChild`,
208 : /// `FPDFBookmark_GetNextSibling`, and `FPDFBookmark_GetAction` / destination
209 : /// resolution, building a `List<PdfTocEntry>` in a single recursive pass.
210 : ///
211 : /// Documents without any bookmarks produce an empty list — not an error.
212 : ///
213 : /// The recursive [PdfTocEntry] tree is deep-copied across the isolate
214 : /// boundary by Dart's message-passing mechanism (Dart serialises arbitrary
215 : /// Dart objects by value when they are sent across isolate boundaries). This
216 : /// is acceptable for the bounded sizes of typical PDF bookmark trees (hundreds
217 : /// to low thousands of entries at most).
218 : class PdfiumGetTocCommand extends PdfiumCommand {
219 : /// Creates a get-TOC command for the document identified by [token].
220 1 : const PdfiumGetTocCommand(super.replyPort, this.token);
221 :
222 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
223 : final int token;
224 : }
225 :
226 : /// Extract all annotations from a single page of an open document.
227 : ///
228 : /// The isolate opens the page, iterates all annotations via
229 : /// `FPDFPage_GetAnnotCount()` / `FPDFPage_GetAnnot()`, extracts all fields,
230 : /// closes each annotation handle and the page handle, then sends a
231 : /// [PdfiumExtractPageAnnotationsResponse].
232 : ///
233 : /// Pages with no annotations produce a response with an empty [annotations]
234 : /// list — not an error.
235 : class PdfiumExtractPageAnnotationsCommand extends PdfiumCommand {
236 : /// Creates an extract-page-annotations command.
237 2 : const PdfiumExtractPageAnnotationsCommand(
238 : super.replyPort,
239 : this.token,
240 : this.pageIndex,
241 : );
242 :
243 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
244 : final int token;
245 :
246 : /// Zero-based index of the page whose annotations are to be extracted.
247 : final int pageIndex;
248 : }
249 :
250 : /// Extract all image objects from a single page of an open document.
251 : ///
252 : /// The isolate opens the page, iterates all page objects via
253 : /// `FPDFPage_CountObjects()` / `FPDFPage_GetObject()`, filters for objects
254 : /// of type `FPDF_PAGEOBJ_IMAGE`, extracts metadata and (optionally) renders
255 : /// the bitmap for each, then closes the page handle and sends a
256 : /// [PdfiumExtractPageImagesResponse].
257 : ///
258 : /// Pages with no image objects produce a response with an empty [images] list
259 : /// — not an error.
260 : ///
261 : /// When [includeBitmap] is `false` (the default), the bitmap is not rendered;
262 : /// [PdfImage.bgra], [PdfImage.bitmapWidth], and [PdfImage.bitmapHeight] will
263 : /// be `null` in every [PdfImage] in the response.
264 : class PdfiumExtractPageImagesCommand extends PdfiumCommand {
265 : /// Creates an extract-page-images command.
266 1 : const PdfiumExtractPageImagesCommand(
267 : super.replyPort,
268 : this.token,
269 : this.pageIndex, {
270 : this.includeBitmap = false,
271 : });
272 :
273 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
274 : final int token;
275 :
276 : /// Zero-based index of the page whose images are to be extracted.
277 : final int pageIndex;
278 :
279 : /// When true, the rendered BGRA bitmap is fetched for each image object.
280 : ///
281 : /// Setting this to `true` calls `FPDFImageObj_GetRenderedBitmap` for every
282 : /// image on the page, which is significantly more expensive than metadata-
283 : /// only extraction. For selective on-demand bitmap fetches, prefer sending
284 : /// individual [PdfiumRenderImageCommand] requests.
285 : final bool includeBitmap;
286 : }
287 :
288 : /// Search for text on a single page of an open document.
289 : ///
290 : /// The isolate loads the page's text layer via `FPDFText_LoadPage`, then
291 : /// calls `FPDFText_FindStart` with the provided [query] (encoded as UTF-16LE)
292 : /// and [flags] bitmask. It iterates `FPDFText_FindNext` to collect all
293 : /// matches, calling `FPDFText_GetSchResultIndex`, `FPDFText_GetSchCount`,
294 : /// `FPDFText_CountRects`, and `FPDFText_GetRect` for each. All handles are
295 : /// closed in a `try/finally` block. The response is a
296 : /// [PdfiumSearchPageResponse].
297 : ///
298 : /// The [flags] field is a PDFium bitmask built from [PdfSearchFlag] values:
299 : /// - `0x01` = `FPDF_MATCHCASE`
300 : /// - `0x02` = `FPDF_MATCHWHOLEWORD`
301 : /// - `0x04` = `FPDF_CONSECUTIVE`
302 : ///
303 : /// An empty [query] string must be rejected by the caller before dispatching
304 : /// this command; the isolate does not guard against it.
305 : ///
306 : /// Pages with no text layer produce a response with an empty matches list —
307 : /// not an error.
308 : class PdfiumSearchPageCommand extends PdfiumCommand {
309 : /// Creates a search-page command.
310 1 : const PdfiumSearchPageCommand(
311 : super.replyPort,
312 : this.token,
313 : this.pageIndex,
314 : this.query,
315 : this.flags,
316 : );
317 :
318 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
319 : final int token;
320 :
321 : /// Zero-based index of the page to search.
322 : final int pageIndex;
323 :
324 : /// The search query string (must be non-empty; the caller is responsible for
325 : /// guarding against empty queries).
326 : final String query;
327 :
328 : /// PDFium search flags bitmask (`FPDF_MATCHCASE | FPDF_MATCHWHOLEWORD |
329 : /// FPDF_CONSECUTIVE`).
330 : final int flags;
331 : }
332 :
333 : /// Fetch the rendered BGRA bitmap for a single image object on a page.
334 : ///
335 : /// The isolate opens the page, retrieves the object at [objectIndex] via
336 : /// `FPDFPage_GetObject`, verifies that its type is `FPDF_PAGEOBJ_IMAGE`,
337 : /// calls `FPDFImageObj_GetRenderedBitmap`, copies the BGRA bytes, destroys
338 : /// the bitmap handle, and closes the page handle. Sends a
339 : /// [PdfiumRenderImageResponse].
340 : ///
341 : /// The response carries `bitmap: null` when the object at [objectIndex] is
342 : /// not an image object, or when `FPDFImageObj_GetRenderedBitmap` returns null
343 : /// (e.g. a mask-only object).
344 : ///
345 : /// The caller is responsible for range-checking [objectIndex] before
346 : /// dispatching this command. If the object index is out of range for the page,
347 : /// `FPDFPage_GetObject` returns null, and the response will carry
348 : /// `bitmap: null`.
349 : class PdfiumRenderImageCommand extends PdfiumCommand {
350 : /// Creates a render-image command.
351 1 : const PdfiumRenderImageCommand(
352 : super.replyPort,
353 : this.token,
354 : this.pageIndex,
355 : this.objectIndex,
356 : );
357 :
358 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
359 : final int token;
360 :
361 : /// Zero-based index of the page containing the image.
362 : final int pageIndex;
363 :
364 : /// Zero-based index of the page object to render (as returned by
365 : /// `FPDFPage_GetObject`). Must be an image-type object.
366 : final int objectIndex;
367 : }
368 :
369 : /// Retrieve the embedded thumbnail bitmap for a single page of an open document.
370 : ///
371 : /// The isolate opens the page via `FPDF_LoadPage`, calls
372 : /// `FPDFPage_GetThumbnailAsBitmap`, and—if a bitmap is returned—reads its
373 : /// pixel data into a [Uint8List] in BGRA format before destroying both the
374 : /// bitmap and page handles. Sends a [PdfiumGetPageThumbnailResponse].
375 : ///
376 : /// When the page has no embedded thumbnail, `FPDFPage_GetThumbnailAsBitmap`
377 : /// returns `nullptr`. The isolate treats this as a success with a `null` pixel
378 : /// buffer (not an error), so the caller can decide whether to fall back to
379 : /// rendering.
380 : ///
381 : /// The [token] is the opaque document token from a prior
382 : /// [PdfiumLoadDocumentCommand]. The [pageIndex] is zero-based.
383 : class PdfiumGetPageThumbnailCommand extends PdfiumCommand {
384 : /// Creates a get-page-thumbnail command.
385 1 : const PdfiumGetPageThumbnailCommand(
386 : super.replyPort,
387 : this.token,
388 : this.pageIndex,
389 : );
390 :
391 : /// The opaque document token returned by a prior [PdfiumLoadDocumentCommand].
392 : final int token;
393 :
394 : /// Zero-based index of the page whose embedded thumbnail is requested.
395 : final int pageIndex;
396 : }
397 :
398 : // ---------------------------------------------------------------------------
399 : // Responses
400 : // ---------------------------------------------------------------------------
401 :
402 : /// Base class for all responses sent from the [PdfiumIsolate].
403 : sealed class PdfiumResponse {
404 : /// Creates a response.
405 19 : const PdfiumResponse();
406 : }
407 :
408 : /// Sent when a command handler throws an unexpected Dart exception.
409 : ///
410 : /// This response is a diagnostic fallback — it means a bug exists in the
411 : /// isolate handler code. The [error] and [stack] fields contain the exception
412 : /// details so they surface in the main isolate's [StateError] rather than
413 : /// disappearing into the spawned isolate's stderr.
414 : class PdfiumHandlerErrorResponse extends PdfiumResponse {
415 : /// Creates a handler error response.
416 1 : const PdfiumHandlerErrorResponse(this.error, this.stack);
417 :
418 : /// A human-readable description of the exception.
419 : final String error;
420 :
421 : /// The stack trace at the point of the exception.
422 : final String stack;
423 : }
424 :
425 : /// Sent by the isolate after it has started and initialised PDFium.
426 : ///
427 : /// The [commandPort] is used for all subsequent commands.
428 : class PdfiumInitResponse extends PdfiumResponse {
429 : /// Creates an init response.
430 10 : const PdfiumInitResponse(this.commandPort);
431 :
432 : /// The [SendPort] on which the isolate accepts subsequent [PdfiumCommand]s.
433 : final SendPort commandPort;
434 : }
435 :
436 : /// Sent by the isolate when PDFium library initialisation fails.
437 : ///
438 : /// This occurs when the dynamic library cannot be loaded (e.g. the path is
439 : /// wrong or the binary is missing). The [message] field contains the
440 : /// underlying error description.
441 : class PdfiumInitFailedResponse extends PdfiumResponse {
442 : /// Creates a failure response with the given error [message].
443 2 : const PdfiumInitFailedResponse(this.message);
444 :
445 : /// A human-readable description of why initialisation failed.
446 : final String message;
447 : }
448 :
449 : /// Sent when a [PdfiumLoadDocumentCommand] succeeds.
450 : class PdfiumLoadDocumentResponse extends PdfiumResponse {
451 : /// Creates a successful load response with the given document [token].
452 10 : const PdfiumLoadDocumentResponse.success(this.token) : error = null;
453 :
454 : /// Creates a failed load response with the given [error].
455 1 : const PdfiumLoadDocumentResponse.failure(this.error) : token = null;
456 :
457 : /// The opaque document token, or `null` on failure.
458 : final int? token;
459 :
460 : /// The error that occurred, or `null` on success.
461 : final PdfError? error;
462 :
463 : /// Whether the document was loaded successfully.
464 20 : bool get isSuccess => token != null;
465 : }
466 :
467 : /// Sent when a [PdfiumGetMetadataCommand] completes.
468 : class PdfiumGetMetadataResponse extends PdfiumResponse {
469 : /// Creates a successful metadata response.
470 2 : const PdfiumGetMetadataResponse.success(this.metadata) : error = null;
471 :
472 : /// Creates a failed metadata response.
473 1 : const PdfiumGetMetadataResponse.failure(this.error) : metadata = null;
474 :
475 : /// The extracted metadata, or `null` on failure.
476 : final PdfMetadata? metadata;
477 :
478 : /// The error that occurred, or `null` on success.
479 : final PdfError? error;
480 : }
481 :
482 : /// Sent when a [PdfiumGetDocumentInfoCommand] completes.
483 : class PdfiumGetDocumentInfoResponse extends PdfiumResponse {
484 : /// Creates a successful document-info response.
485 2 : const PdfiumGetDocumentInfoResponse.success(this.info) : error = null;
486 :
487 : /// Creates a failed document-info response.
488 1 : const PdfiumGetDocumentInfoResponse.failure(this.error) : info = null;
489 :
490 : /// The document info, or `null` on failure.
491 : final PdfDocumentInfo? info;
492 :
493 : /// The error that occurred, or `null` on success.
494 : final PdfError? error;
495 : }
496 :
497 : /// Sent when a [PdfiumCloseDocumentCommand] completes.
498 : class PdfiumCloseDocumentResponse extends PdfiumResponse {
499 : /// Creates a close-document response.
500 19 : const PdfiumCloseDocumentResponse();
501 : }
502 :
503 : /// Sent when a [PdfiumGetPageCountCommand] completes.
504 : class PdfiumGetPageCountResponse extends PdfiumResponse {
505 : /// Creates a successful page-count response.
506 7 : const PdfiumGetPageCountResponse.success(this.pageCount) : error = null;
507 :
508 : /// Creates a failed page-count response.
509 1 : const PdfiumGetPageCountResponse.failure(this.error) : pageCount = null;
510 :
511 : /// The total number of pages, or `null` on failure.
512 : final int? pageCount;
513 :
514 : /// The error that occurred, or `null` on success.
515 : final PdfError? error;
516 : }
517 :
518 : /// Sent when a [PdfiumExtractPageAnnotationsCommand] completes.
519 : class PdfiumExtractPageAnnotationsResponse extends PdfiumResponse {
520 : /// Creates a successful annotation-extraction response.
521 2 : const PdfiumExtractPageAnnotationsResponse.success({
522 : required this.pageIndex,
523 : required List<PdfAnnotation> this._annotations,
524 : }) : error = null;
525 :
526 : /// Creates a failed annotation-extraction response.
527 1 : const PdfiumExtractPageAnnotationsResponse.failure(this.error, this.pageIndex)
528 : : _annotations = null;
529 :
530 : final List<PdfAnnotation>? _annotations;
531 :
532 : /// The zero-based page index this response corresponds to.
533 : final int pageIndex;
534 :
535 : /// The error that occurred, or `null` on success.
536 : final PdfError? error;
537 :
538 : /// Whether this response represents a successful extraction.
539 4 : bool get isSuccess => error == null;
540 :
541 : /// The list of extracted annotations. Only valid when [isSuccess] is true.
542 4 : List<PdfAnnotation> get annotations => _annotations!;
543 : }
544 :
545 : /// Sent when a [PdfiumGetPageSizeCommand] completes.
546 : class PdfiumGetPageSizeResponse extends PdfiumResponse {
547 : /// Creates a successful page-size response.
548 3 : const PdfiumGetPageSizeResponse.success(this.pageSize) : error = null;
549 :
550 : /// Creates a failed page-size response.
551 1 : const PdfiumGetPageSizeResponse.failure(this.error) : pageSize = null;
552 :
553 : /// The page size, or `null` on failure.
554 : final PdfPageSize? pageSize;
555 :
556 : /// The error that occurred, or `null` on success.
557 : final PdfError? error;
558 :
559 : /// Whether the response represents a successful operation.
560 6 : bool get isSuccess => error == null;
561 : }
562 :
563 : /// Sent when a [PdfiumRenderPageCommand] completes.
564 : class PdfiumRenderPageResponse extends PdfiumResponse {
565 : /// Creates a successful render response carrying the BGRA [_pixels] buffer
566 : /// and the actual rendered [pixelWidth] × [pixelHeight] dimensions.
567 3 : const PdfiumRenderPageResponse.success({
568 : required Uint8List this._pixels,
569 : required this.pixelWidth,
570 : required this.pixelHeight,
571 : }) : _errorMessage = null;
572 :
573 : /// Creates a failed render response with a descriptive [errorMessage].
574 2 : const PdfiumRenderPageResponse.failure(this._errorMessage)
575 : : _pixels = null,
576 : pixelWidth = 0,
577 : pixelHeight = 0;
578 :
579 : final Uint8List? _pixels;
580 : final String? _errorMessage;
581 :
582 : /// The width of the rendered bitmap in pixels. Only valid when [isSuccess].
583 : final int pixelWidth;
584 :
585 : /// The height of the rendered bitmap in pixels. Only valid when [isSuccess].
586 : final int pixelHeight;
587 :
588 : /// Whether the render succeeded.
589 6 : bool get isSuccess => _errorMessage == null;
590 :
591 : /// The BGRA pixel buffer. Only valid when [isSuccess] is `true`.
592 6 : Uint8List get pixels => _pixels!;
593 :
594 : /// The error message describing why rendering failed. Only valid when
595 : /// [isSuccess] is `false`.
596 4 : String get errorMessage => _errorMessage!;
597 : }
598 :
599 : /// Sent when a [PdfiumGetTocCommand] completes.
600 : class PdfiumGetTocResponse extends PdfiumResponse {
601 : /// Creates a successful TOC response with the given [entries] tree.
602 1 : const PdfiumGetTocResponse.success(this.entries) : error = null;
603 :
604 : /// Creates a failed TOC response.
605 1 : const PdfiumGetTocResponse.failure(this.error) : entries = null;
606 :
607 : /// The root-level TOC entries, or `null` on failure.
608 : ///
609 : /// An empty list is a valid success — the document simply has no bookmarks.
610 : final List<PdfTocEntry>? entries;
611 :
612 : /// The error that occurred, or `null` on success.
613 : final PdfError? error;
614 :
615 : /// Whether this response represents a successful extraction.
616 4 : bool get isSuccess => error == null;
617 : }
618 :
619 : /// Sent when a [PdfiumExtractPageImagesCommand] completes.
620 : class PdfiumExtractPageImagesResponse extends PdfiumResponse {
621 : /// Creates a successful image-extraction response.
622 1 : const PdfiumExtractPageImagesResponse.success({
623 : required this.pageIndex,
624 : required List<PdfImage> this._images,
625 : }) : error = null;
626 :
627 : /// Creates a failed image-extraction response.
628 1 : const PdfiumExtractPageImagesResponse.failure(this.error, this.pageIndex)
629 : : _images = null;
630 :
631 : final List<PdfImage>? _images;
632 :
633 : /// The zero-based page index this response corresponds to.
634 : final int pageIndex;
635 :
636 : /// The error that occurred, or `null` on success.
637 : final PdfError? error;
638 :
639 : /// Whether this response represents a successful extraction.
640 4 : bool get isSuccess => error == null;
641 :
642 : /// The list of extracted images. Only valid when [isSuccess] is true.
643 2 : List<PdfImage> get images => _images!;
644 : }
645 :
646 : /// Sent when a [PdfiumRenderImageCommand] completes.
647 : class PdfiumRenderImageResponse extends PdfiumResponse {
648 : /// Creates a successful render response carrying the [bitmap].
649 : ///
650 : /// [bitmap] is `null` when the object at the requested index is not an
651 : /// image type or when `FPDFImageObj_GetRenderedBitmap` returned null.
652 19 : const PdfiumRenderImageResponse.success(this.bitmap) : error = null;
653 :
654 : /// Creates a failed render response.
655 1 : const PdfiumRenderImageResponse.failure(this.error) : bitmap = null;
656 :
657 : /// The rendered bitmap, or `null` if the object is not a renderable image.
658 : final PdfImageBitmap? bitmap;
659 :
660 : /// The error that occurred, or `null` on success.
661 : final PdfError? error;
662 :
663 : /// Whether this response represents a successful (non-error) operation.
664 : ///
665 : /// Note: a successful response may still carry a `null` [bitmap] when the
666 : /// object has no renderable bitmap (mask-only etc.). A `false` value here
667 : /// indicates a hard error such as an invalid document token.
668 4 : bool get isSuccess => error == null;
669 : }
670 :
671 : /// Sent when a [PdfiumSearchPageCommand] completes.
672 : class PdfiumSearchPageResponse extends PdfiumResponse {
673 : /// Creates a successful search response with the [_matches] found on the page.
674 : ///
675 : /// An empty [_matches] list means no matches were found on this page — that
676 : /// is a normal, non-error result.
677 1 : const PdfiumSearchPageResponse.success({
678 : required this.pageIndex,
679 : required List<PdfSearchMatch> this._matches,
680 : }) : error = null;
681 :
682 : /// Creates a failed search response.
683 1 : const PdfiumSearchPageResponse.failure(this.error, this.pageIndex)
684 : : _matches = null;
685 :
686 : final List<PdfSearchMatch>? _matches;
687 :
688 : /// The zero-based page index this response corresponds to.
689 : final int pageIndex;
690 :
691 : /// The error that occurred, or `null` on success.
692 : final PdfError? error;
693 :
694 : /// Whether this response represents a successful search.
695 4 : bool get isSuccess => error == null;
696 :
697 : /// The list of matches found on this page. Only valid when [isSuccess] is
698 : /// `true`. May be empty when no matches were found.
699 2 : List<PdfSearchMatch> get matches => _matches!;
700 : }
701 :
702 : /// Sent when a [PdfiumGetPageThumbnailCommand] completes.
703 : ///
704 : /// On success, [bgra] is either:
705 : /// - A non-null [Uint8List] containing the compact BGRA pixel bytes of the
706 : /// embedded thumbnail (`length == width * height * 4`, row-padding stripped).
707 : /// - `null`, indicating the page has no embedded thumbnail — this is a normal
708 : /// result, not an error.
709 : ///
710 : /// On failure (e.g. invalid document token or `FPDF_LoadPage` returning null),
711 : /// [isSuccess] is `false` and [errorMessage] describes the problem.
712 : class PdfiumGetPageThumbnailResponse extends PdfiumResponse {
713 : /// Creates a successful response where the page has an embedded thumbnail.
714 : ///
715 : /// [_bgra] must have length `[width] * [height] * 4`. Pass `null` for [_bgra]
716 : /// (with [width] and [height] of 0) when the page has no embedded thumbnail.
717 19 : const PdfiumGetPageThumbnailResponse.success({
718 : required this._bgra,
719 : required this.width,
720 : required this.height,
721 : }) : _errorMessage = null;
722 :
723 : /// Creates a failed response with a descriptive [errorMessage].
724 1 : const PdfiumGetPageThumbnailResponse.failure(this._errorMessage)
725 : : _bgra = null,
726 : width = 0,
727 : height = 0;
728 :
729 : final Uint8List? _bgra;
730 : final String? _errorMessage;
731 :
732 : /// The pixel width of the embedded thumbnail. Zero when [bgra] is `null`.
733 : final int width;
734 :
735 : /// The pixel height of the embedded thumbnail. Zero when [bgra] is `null`.
736 : final int height;
737 :
738 : /// Whether the operation succeeded (even if no thumbnail was found).
739 4 : bool get isSuccess => _errorMessage == null;
740 :
741 : /// The BGRA pixel buffer of the embedded thumbnail, or `null` when:
742 : /// - The page has no embedded thumbnail (normal result).
743 : ///
744 : /// Only valid when [isSuccess] is `true`.
745 4 : Uint8List? get bgra => _bgra;
746 :
747 : /// The error message. Only valid when [isSuccess] is `false`.
748 2 : String get errorMessage => _errorMessage!;
749 : }
750 :
751 : /// Sent when a [PdfiumExtractPageTextCommand] completes.
752 : class PdfiumExtractPageTextResponse extends PdfiumResponse {
753 : /// Creates a successful text-extraction response.
754 2 : const PdfiumExtractPageTextResponse.success({
755 : required this.pageIndex,
756 : required String this._text,
757 : required bool this._hasUnicodeErrors,
758 : required bool this._hasTextLayer,
759 : }) : error = null;
760 :
761 : /// Creates a failed text-extraction response.
762 1 : const PdfiumExtractPageTextResponse.failure(this.error, this.pageIndex)
763 : : _text = null,
764 : _hasUnicodeErrors = null,
765 : _hasTextLayer = null;
766 :
767 : final String? _text;
768 : final bool? _hasUnicodeErrors;
769 : final bool? _hasTextLayer;
770 :
771 : /// The zero-based page index this response corresponds to.
772 : final int pageIndex;
773 :
774 : /// The error that occurred, or `null` on success.
775 : final PdfError? error;
776 :
777 : /// Whether this response represents a successful extraction.
778 6 : bool get isSuccess => error == null;
779 :
780 : /// The extracted text. Only valid when [isSuccess] is true.
781 4 : String get text => _text!;
782 :
783 : /// Whether any characters had broken Unicode mappings. Only valid when
784 : /// [isSuccess] is true.
785 4 : bool get hasUnicodeErrors => _hasUnicodeErrors!;
786 :
787 : /// Whether this page has a meaningful text layer. Only valid when
788 : /// [isSuccess] is true.
789 4 : bool get hasTextLayer => _hasTextLayer!;
790 : }
|