pdfrx

repository·master·Indexed 42 days ago

https://github.com/espresso3389/pdfrx

A multi-package ecosystem for PDF rendering, viewing, and manipulation in Dart and Flutter, primarily powered by the PDFium engine. It provides high-level UI widgets for Flutter and low-level engine APIs for pure Dart environments. Features include text search and selection, document outline navigation, page layout customization, and PDF editing capabilities such as page manipulation and image integration. It also offers an experimental CoreGraphics-backed renderer for iOS and macOS via the pdfrx_coregraphics package.

Tokens
37.8K
Snippets
111
Records
151
Agent score
54%

What's inside pdfrx

  1. Core Features of pdfrx

    master

    The pdfrx plugin provides a wide range of features for PDF interaction, categorized into:

    Text Features

    • Text Search: Implement functionality to find specific text within a document.
    • Text Selection: Enable users to select and interact with text.
    • Document Outline (Bookmarks): Work with PDF bookmarks to navigate the document structure.
    • PDF Link Handling: Manage how links within the PDF are processed.
    • Page Layout Customization: Adjust how pages are displayed.
    • Double-tap to Zoom: Implement standard zoom gestures.

    UI Customization

    • Page Numbers: Display page numbers at the bottom of pages.
    • Loading Indicators: Show progress during document loading.
    • Scroll Thumbs: Display scroll indicators for easier navigation.
    • Dark/Night Mode: Implement support for dark themes.
  2. Advanced pdfrx Usage and PDF Editing

    master

    For complex implementations, pdfrx supports advanced manipulation and low-level access:

    Advanced Topics

    • Coordinate Conversion: Convert between different coordinate systems used in PDF rendering.
    • Custom Key Handling: Define custom keyboard shortcuts for the PdfViewer.
    • Password Protected PDFs: Use a PasswordProvider to handle encrypted files.
    • Overlays: Use viewerOverlayBuilder and pageOverlaysBuilder to add custom UI layers.
    • Dynamic Fonts: Load custom fonts dynamically for rendering.
    • Low-Level Access: Access PDFium bindings directly or manage interoperability with other PDFium-based libraries.

    PDF Editing

    • Page Manipulation: Re-arrange, combine, or extract specific pages from a PDF.
    • Image Integration: Convert images to PDF format or insert existing images into a PDF document.
  3. What is Progressive Loading and when to use it

    master

    Progressive loading allows PDF documents to be loaded page-by-page instead of all at once. This reduces initial load time and memory usage, making it ideal for large PDF files (hundreds of pages) or memory-constrained environments.

    There are two modes:

    1. Standard Loading (default): All pages load immediately.
    2. Progressive Loading: Only the first page loads initially; others load on-demand.

    Note on defaults:

    • PdfViewer uses progressive loading by default.
    • PdfDocument (engine-level) requires explicit opt-in.
  4. Concepts of Text Selection Points and Ranges

    master

    The text selection system relies on three main abstractions:

    • PdfTextSelectionPoint: Represents a specific location in the document text. It combines a PdfPageText object (the page's text structure) with a character index.
    • PdfTextSelectionRange: Defines a span of text. It is created via PdfTextSelectionRange.fromPoints(start, end). This constructor automatically ensures that the start point precedes the end point, regardless of the order provided.
    • PdfTextSelectionDelegate: The interface (accessed via controller.textSelection) used to programmatically manipulate the selection, such as setting a new range.

    Key Rule: Character indices are inclusive. When defining the end of a selection, the index must point to the last character you wish to include.

  5. Make a document self-contained with PdfDocument.assemble()

    master

    When you combine pages from multiple PdfDocument instances, the target document maintains internal references to those source documents. To make the document independent and allow you to safely dispose of the source documents, call PdfDocument.assemble().

    Key Details:

    • PdfDocument.assemble() re-organizes the document to be self-contained.
    • PdfDocument.encodePdf() calls assemble() automatically, so explicit calling is only necessary if you want to release source documents early to free up memory.
    • Once assemble() is called, the source documents can be safely disposed.
    // After combining pages from multiple documents
    doc1.pages = [...doc1.pages, ...doc2.pages, ...doc3.pages];
    
    // Assemble to make doc1 independent
    await doc1.assemble();
    
    // Now you can safely dispose doc2 and doc3
    doc2.dispose();
    doc3.dispose();
    
    // doc1 is still valid and can be encoded later
    final bytes = await doc1.encodePdf();
    
    doc1.dispose();
  6. Coordinate raw PDFium calls with pdfrx workers

    master

    When using pdfrx APIs in the same process, you must prevent conflicts between your raw PDFium calls and pdfrx's internal PDFium worker. Wrap your direct calls with PdfrxEntryFunctions.instance.suspendPdfiumWorkerDuringAction() to temporarily pause the pdfrx worker.

    Note: This is required to ensure thread safety and prevent concurrent access to the PDFium instance.

    import 'package:pdfium_dart/pdfium_dart.dart';
    import 'package:pdfrx_engine/pdfrx_engine.dart';
    
    await PdfrxEntryFunctions.instance.suspendPdfiumWorkerDuringAction(() {
      // Perform raw PDFium operations here
    });
  7. Choose the right pdfrx package for your project

    master

    The pdfrx ecosystem is split into several packages depending on your environment and requirements:

    • Flutter Apps with UI: Use pdfrx. It provides high-level viewer widgets, text selection, search, and zoom controls.
    • Pure Dart / CLI / Server-side: Use pdfrx_engine. It provides a low-level PDF document API for rendering and manipulation (page re-arrangement, combining, image import) without Flutter dependencies.
    • Apple-specific (iOS/macOS) System Rendering: Use pdfrx_coregraphics (Experimental). This is a drop-in replacement for pdfrx that uses PDFKit/CoreGraphics instead of PDFium.
    • Direct PDFium Access (Flutter): Use pdfium_flutter if you need low-level FFI access to PDFium on native platforms.
    • Direct PDFium Access (Pure Dart): Use pdfium_dart for low-level FFI bindings in non-Flutter projects.
  8. Understand pdfrx coordinate systems

    master

    pdfrx utilizes four distinct coordinate systems. Understanding the difference between them is critical for accurate positioning of overlays, handling touch events, and interacting with PDF content:

    1. Global Coordinates: Screen or window coordinates where the origin (0,0) is at the top-left of the screen.
    2. Local Coordinates: The coordinate system of the specific Flutter widget, where (0,0) is at the top-left of the widget.
    3. Document Coordinates: The PDF document layout coordinates. These are at 72 DPI, unzoomed, and follow the layout mode (e.g., single page or continuous scroll). The origin is at the top-left of the document layout.
    4. Page Coordinates: Individual PDF page coordinates following the PDF standard, where the origin (0,0) is at the bottom-left corner of the page.

    Note on Rotation: When converting to/from Page Coordinates, pdfrx automatically handles PDF page rotation metadata so that (0,0) in page coordinates always represents the bottom-left corner of the page as it appears visually.

  9. When to use progressive loading

    master

    Progressive loading is a performance optimization for handling PDF documents.

    Use progressive loading when:

    • Working with large PDFs (100+ pages).
    • Initial load time is critical.
    • Users typically view only a few pages.
    • Memory usage is a concern.
    • Loading from a network (reduces initial bandwidth).

    Avoid progressive loading when:

    • Working with small PDFs (< 20 pages).
    • You need to process all pages immediately.
    • All pages will be accessed anyway.
    • Simplicity is preferred over optimization.
  10. Native library deployment for pdfium_flutter

    master

    The package handles native library loading differently depending on the platform:

    Android, Windows, and Linux

    PDFium binaries are downloaded and bundled at build time using Dart native assets. On Linux, pdfium_dart resolves the shared library from the Flutter app's shared library directory relative to the executable.

    iOS and macOS

    PDFium is integrated via an XCFramework (downloaded via CocoaPods or Swift Package Manager). pdfium_dart detects Flutter on these platforms and uses the symbols from the XCFramework instead of loading a separate libpdfium.dylib native asset. This prevents duplicate bundling of the library.

  11. Memory management with progressive loading

    master

    While progressive loading reduces initial memory usage, it does not automatically unload pages. Once a page is loaded, it remains in memory until the PdfDocument is disposed.

    For very large documents, consider these strategies:

    • Loading and processing pages in batches.
    • Disposing and reopening the document periodically if processing thousands of pages.
    • Using PdfViewer, which handles the page lifecycle automatically.