Giter Club home page Giter Club logo

pdfium-render's Introduction

Idiomatic Rust bindings for Pdfium

pdfium-render provides an idiomatic high-level Rust interface to Pdfium, the C++ PDF library used by the Google Chromium project. Pdfium can render pages in PDF files to bitmaps, load, edit, and extract text and images from existing PDF files, and create new PDF files from scratch.

    use pdfium_render::prelude::*;

    fn export_pdf_to_jpegs(path: &impl AsRef<Path>, password: Option<&str>) -> Result<(), PdfiumError> {
        // Renders each page in the PDF file at the given path to a separate JPEG file.

        // Bind to a Pdfium library in the same directory as our Rust executable;
        // failing that, fall back to using a Pdfium library provided by the operating system.

        let pdfium = Pdfium::new(
            Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))
                .or_else(|_| Pdfium::bind_to_system_library())?,
        );

        // Load the document from the given path...

        let document = pdfium.load_pdf_from_file(path, password)?;

        // ... set rendering options that will be applied to all pages...

        let render_config = PdfRenderConfig::new()
            .set_target_width(2000)
            .set_maximum_height(2000)
            .rotate_if_landscape(PdfPageRenderRotation::Degrees90, true);

        // ... then render each page to a bitmap image, saving each image to a JPEG file.

        for (index, page) in document.pages().iter().enumerate() {
            page.render_with_config(&render_config)?
                .as_image() // Renders this page to an image::DynamicImage...
                .into_rgb8() // ... then converts it to an image::Image...
                .save_with_format(
                    format!("test-page-{}.jpg", index), 
                    image::ImageFormat::Jpeg
                ) // ... and saves it to a file.
                .map_err(|_| PdfiumError::ImageError)?;
        }

        Ok(())
    }

pdfium-render binds to a Pdfium library at run-time, allowing for flexible selection of system-provided or bundled Pdfium libraries and providing idiomatic Rust error handling in situations where a Pdfium library is not available. A key advantage of binding to Pdfium at run-time rather than compile-time is that a Rust application using pdfium-render can be compiled to WASM for running in a browser alongside a WASM-packaged build of Pdfium.

pdfium-render aims to eventually provide bindings to all non-interactive functionality provided by Pdfium. This is a work in progress that will be completed by version 1.0 of this crate.

Examples

Short, commented examples that demonstrate all the major Pdfium document handling features are available at https://github.com/ajrcarey/pdfium-render/tree/master/examples. These examples demonstrate:

  • Rendering pages, and portions of pages, to bitmaps.
  • Text and image extraction.
  • Form field introspection and filling of form fields.
  • Document signature introspection.
  • Document attachment creation and introspection.
  • Document concatenation.
  • Page object introspection.
  • Page annotation introspection.
  • Page link introspection.
  • Creation of new documents and new pages.
  • Creation of page objects for text, paths, and bitmaps.
  • Page object transformation.
  • Multi-page tiled rendering.
  • Watermarking.
  • Thread safety.
  • Compiling to WASM.

What's new

Note: upcoming release 0.9.0 will remove all deprecated items. For a complete list of deprecated items, see #36.

Release 0.8.22 updates all examples and tests that reference functionality from the image crate to use calls compatible with both image 0.25.x and 0.24.x, adds support for static linking to a dynamic Pdfium library at compile time, adds the PdfPages::page_size() and PdfPages::page_sizes() functions for retrieving the size of one or all pages without first needing to load those pages into memory, and removes an unneeded internal dependency on the iter_tools crate, thanks to excellent contributions from both https://github.com/DorianRudolph and https://github.com/aruediger.

Release 0.8.21 adds the PdfFormFieldText::set_value() function for setting the values of text form fields, thanks to an excellent contribution from https://github.com/liammcdermott. A new examples/fill_form_field.rs example demonstrates the new functionality.

Release 0.8.20 adds support for creating new annotations, positioning those annotations, associating them with page objects, and retrieving and setting more annotation properties for each annotation type. A new examples/create_annotations.rs example demonstrates the extended functionality.

Release 0.8.19 adds the PdfBookmark::children_len() function for returning the number of direct child nodes of a bookmark without the need for iteration, and fixes a bug in PdfPage::flatten() to ensure that the flatten operation takes immediate effect; previously, it was necessary to drop and reload the page after calling PdfPage::flatten() in order to see the result of the operation.

Binding to Pdfium

pdfium-render does not include Pdfium itself. You have several options:

  • Bind to a dynamically-built Pdfium library provided by the operating system.
  • Bind to a dynamically-built Pdfium library packaged alongside your Rust executable.
  • Bind to a statically-built Pdfium library linked to your executable at compile time.

When compiling to WASM, packaging an external build of Pdfium as a separate WASM module is essential.

Dynamic linking

Binding to a pre-built Pdfium dynamic library at runtime is the simplest option. On Android, a pre-built libpdfium.so is packaged as part of the operating system (although recent versions of Android no longer permit user applications to access it); alternatively, you can package a dynamic library appropriate for your operating system alongside your Rust executable.

Pre-built Pdfium dynamic libraries suitable for runtime binding are available from several sources:

If you are compiling a native (i.e. non-WASM) build, and you place an appropriate Pdfium library in the same folder as your compiled application, then binding to it at runtime is as simple as:

    use pdfium_render::prelude::*;

    let pdfium = Pdfium::new(
        Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./")).unwrap()
    );

A common pattern used in the examples at https://github.com/ajrcarey/pdfium-render/tree/master/examples is to first attempt to bind to a Pdfium library in the same folder as the compiled example, and attempt to fall back to a system-provided library if that fails:

    use pdfium_render::prelude::*;

    let pdfium = Pdfium::new(
        Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))
            .or_else(|_| Pdfium::bind_to_system_library())
            .unwrap() // Or use the ? unwrapping operator to pass any error up to the caller
    );

This pattern is used to provide an implementation of the Default trait, so the above can be written more simply as:

    use pdfium_render::prelude::*;

    let pdfium = Pdfium::default();

Static linking

The static crate feature offers an alternative to dynamic linking if you prefer to link Pdfium directly into your executable at compile time. This enables the Pdfium::bind_to_statically_linked_library() function which binds directly to the Pdfium functions compiled into your executable:

    use pdfium_render::prelude::*;

    let pdfium = Pdfium::new(Pdfium::bind_to_statically_linked_library().unwrap());

As a convenience, pdfium-render can instruct cargo to link to either a dynamically-built or a statically-built Pdfium library for you. To link to a dynamically-built library, set the PDFIUM_DYNAMIC_LIB_PATH environment variable when you run cargo build, like so:

    PDFIUM_DYNAMIC_LIB_PATH="/path/containing/your/dynamic/pdfium/library" cargo build

pdfium-render will pass the following flags to cargo:

    cargo:rustc-link-lib=dylib=pdfium
    cargo:rustc-link-search=native=$PDFIUM_DYNAMIC_LIB_PATH

To link to a statically-built library, set the path to the directory containing your library using the PDFIUM_STATIC_LIB_PATH environment variable when you run cargo build, like so:

    PDFIUM_STATIC_LIB_PATH="/path/containing/your/static/pdfium/library" cargo build

pdfium-render will pass the following flags to cargo:

    cargo:rustc-link-lib=static=pdfium
    cargo:rustc-link-search=native=$PDFIUM_STATIC_LIB_PATH

These two environment variables save you writing a custom build.rs yourself. If you have your own build pipeline that links Pdfium statically into your executable, simply leave these environment variables unset.

Note that the path you set in either PDFIUM_DYNAMIC_LIB_PATH or PDFIUM_STATIC_LIB_PATH should not include the filename of the library itself; it should just be the path of the containing directory. You must make sure your library is named in the appropriate way for your target platform (libpdfium.so or libpdfium.a on Linux and macOS, for example) in order for the Rust compiler to locate it.

Depending on how your Pdfium library was built, you may need to also link against a C++ standard library. To link against the GNU C++ standard library (libstdc++), use the optional libstdc++ feature. pdfium-render will pass the following additional flag to cargo:

    cargo:rustc-link-lib=dylib=stdc++

To link against the LLVM C++ standard library (libc++), use the optional libc++ feature. pdfium-render will pass the following additional flag to cargo:

    cargo:rustc-link-lib=dylib=c++

Alternatively, use the link-cplusplus crate to link against a C++ standard library. link-cplusplus offers more options for deciding which standard library should be selected, including automatically selecting the build platform's installed default.

pdfium-render will not build Pdfium for you; you must build Pdfium yourself, source a pre-built static archive from elsewhere, or use a dynamically built library downloaded from one of the sources listed above in the "Dynamic linking" section. If you wish to build a static library yourself, an overview of the build process - including a sample build script - is available at #53.

Compiling to WASM

See https://github.com/ajrcarey/pdfium-render/tree/master/examples for a full example that shows how to bundle a Rust application using pdfium-render alongside a pre-built Pdfium WASM module for inspection and rendering of PDF files in a web browser.

Certain functions that access the file system are not available when compiling to WASM. In all cases, browser-specific alternatives are provided, as detailed at the link above.

At the time of writing, the WASM builds of Pdfium at https://github.com/bblanchon/pdfium-binaries/releases are compiled with a non-growable WASM heap memory allocator. This means that attempting to open a PDF document longer than just a few pages will result in an unrecoverable out of memory error. The WASM builds of Pdfium at https://github.com/paulocoutinhox/pdfium-lib/releases are recommended as they do not have this problem.

Multi-threading

Pdfium makes no guarantees about thread safety and should be assumed not to be thread safe. The Pdfium authors specifically recommend that parallel processing, not multi-threading, be used to process multiple documents simultaneously.

pdfium-render achieves thread safety by locking access to Pdfium behind a mutex; each thread must acquire exclusive access to this mutex in order to make any call to Pdfium. This has the effect of sequencing all calls to Pdfium as if they were single-threaded, even when using pdfium-render from multiple threads. This approach offers no performance benefit, but it ensures that Pdfium will not crash when running as part of a multi-threaded application.

An example of safely using pdfium-render as part of a multi-threaded parallel iterator is available at https://github.com/ajrcarey/pdfium-render/tree/master/examples.

Crate features

This crate provides the following optional features:

  • bindings: uses cbindgen to generate Rust bindings to the Pdfium functions defined in the include/*.h files each time cargo build is run. If cbindgen or any of its dependencies are not available then the build will fail.
  • image: controls whether the image crate should be used by pdfium-render to provide page and page object rendering functionality. Projects that do not require page or page object rendering can disable this feature to avoid compiling the image crate into their binaries.
  • libstdc++: links against the GNU C++ standard library when compiling. Requires the static feature. See the "Static linking" section above.
  • libc++: links against the LLVM C++ standard library when compiling. Requires the static feature. See the "Static linking" section above.
  • static: enables binding to a statically-linked build of Pdfium. See the "Static linking" section above.
  • sync: provides implementations of the Send and Sync traits for the Pdfium and PdfDocument structs. This is useful for creating static instances that can be used with lazy_static or once_cell, although those instances are not guaranteed to be thread-safe. Use entirely at your own risk. Requires the thread_safe feature.
  • thread_safe: wraps access to Pdfium behind a mutex to ensure thread-safe access to Pdfium. See the "Multithreading" section above.

The image and thread_safe features are enabled by default. All other features are disabled by default.

Porting existing Pdfium code from other languages

The high-level idiomatic Rust interface provided by pdfium-render is built on top of raw FFI bindings defined in the PdfiumLibraryBindings trait. It is completely feasible to use these raw FFI bindings directly if you wish, making porting existing code that calls FPDF_* functions trivial while still gaining the benefits of late binding and WASM compatibility. For instance, the following code snippet (taken from a C++ sample):

    string test_doc = "test.pdf";

    FPDF_InitLibrary();
    FPDF_DOCUMENT doc = FPDF_LoadDocument(test_doc, NULL);
    // ... do something with doc
    FPDF_CloseDocument(doc);
    FPDF_DestroyLibrary();

would translate to the following Rust code:

    let pdfium = Pdfium::default();
    let bindings = pdfium.bindings();
    let test_doc = "test.pdf";

    bindings.FPDF_InitLibrary();
    let doc = bindings.FPDF_LoadDocument(test_doc, None);
    // ... do something with doc
    bindings.FPDF_CloseDocument(doc);
    bindings.FPDF_DestroyLibrary();

Pdfium's API uses three different string types: classic C-style null-terminated char arrays, UTF-8 byte arrays, and a UTF-16LE byte array type named FPDF_WIDESTRING. For functions that take a C-style string or a UTF-8 byte array, pdfium-render's binding will take the standard Rust &str type. For functions that take an FPDF_WIDESTRING, pdfium-render exposes two functions: the vanilla FPDF_*() function that takes an FPDF_WIDESTRING, and an additional FPDF_*_str() helper function that takes a standard Rust &str and converts it internally to an FPDF_WIDESTRING before calling Pdfium. Examples of functions with additional _str() helpers include FPDFBookmark_Find(), FPDFText_SetText(), FPDFText_FindStart(), FPDFDoc_AddAttachment(), FPDFAnnot_SetStringValue(), and FPDFAttachment_SetStringValue().

The PdfiumLibraryBindings::get_pdfium_utf16le_bytes_from_str() and PdfiumLibraryBindings::get_string_from_pdfium_utf16le_bytes() utility functions are provided for converting to and from FPDF_WIDESTRING in your own code.

Some Pdfium functions return classic C-style integer boolean values, aliased as FPDF_BOOL. The PdfiumLibraryBindings::TRUE(), PdfiumLibraryBindings::FALSE(), PdfiumLibraryBindings::is_true(), PdfiumLibraryBindings::to_result(), and PdfiumLibraryBindings::bool_to_pdfium() utility functions are provided for converting to and from FPDF_BOOL in your own code.

Image pixel data in Pdfium is encoded in either three-channel BGR or four-channel BGRA. The PdfiumLibraryBindings::bgr_to_rgba(), PdfiumLibraryBindings::bgra_to_rgba(), PdfiumLibraryBindings::rgb_to_bgra(), and PdfiumLibraryBindings::rgba_to_bgra() utility functions are provided for converting between RGB and BGR image data in your own code.

Development status

The initial focus of this crate was on rendering pages in a PDF file; consequently, FPDF_* functions related to page rendering were prioritised. By 1.0, the functionality of all FPDF_* functions exported by all Pdfium modules will be available, with the exception of certain functions specific to interactive scripting, user interaction, and printing.

  • Releases numbered 0.4.x added support for basic page rendering Pdfium functions to pdfium-render.
  • Releases numbered 0.5.x-0.6.x added support for most read-only Pdfium functions to pdfium-render.
  • Releases numbered 0.7.x added support for most Pdfium page object creation and editing functions to pdfium-render.
  • Releases numbered 0.8.x aim to progressively add support for all remaining Pdfium editing functions to pdfium-render.
  • Releases numbered 0.9.x aim to fill any remaining gaps in the high-level interface prior to 1.0.

There are 368 FPDF_* functions in the Pdfium API. As of version 0.8.22, 331 (90%) have bindings available in PdfiumLibraryBindings, with the functionality of the majority of these available via the pdfium-render high-level interface.

Some functions and type definitions in the high-level interface have been renamed or revised since their initial implementation. The initial implementations are still available but are marked as deprecated. These deprecated items will be removed in release 0.9.0.

If you need a binding to a Pdfium function that is not currently available, just raise an issue at https://github.com/ajrcarey/pdfium-render/issues.

Version history

  • 0.8.22: adds bindings for FPDFPage_TransformAnnots(), thanks to an excellent contribution from https://github.com/liammcdermott; adds bindings for FPDF_GetPageSizeByIndexF(), thanks to an excellent contribution from https://github.com/DorianRudolph; updates all examples and tests that reference functionality from the image crate to use calls compatible with both image 0.25.x and 0.24.x, thanks to an excellent contribution from https://github.com/DorianRudolph; adds support for both static linking to a dynamically-built Pdfium library at compile time and dynamic binding caching for improved runtime performance, thanks to an excellent contribution from https://github.com/DorianRudolph; adds the PdfPages::get_page_size() and PdfPages::get_page_sizes() functions, thanks to an excellent contribution from https://github.com/DorianRudolph; removes an unneeded internal dependency on the iter_tools crate, thanks to an excellent contribution from https://github.com/aruediger.
  • 0.8.21: adds the PdfFormFieldText::set_value() function for setting the values of text form fields, thanks to an excellent contribution from https://github.com/liammcdermott; adds new examples/fill_form_field.rs example.
  • 0.8.20: adds PdfPageAnnotationAttachmentPoints struct and matching iterator; adds new annotation functions to PdfPageAnnotationCommon along with their matching implementations in PdfPageAnnotationPrivate, including PdfPageAnnotationCommon::set_bounds(), PdfPageAnnotationCommon::set_position(), PdfPageAnnotationCommon::set_width(), PdfPageAnnotationCommon::set_height(), PdfPageAnnotationCommon::set_creation_date(), PdfPageAnnotationCommon::set_modification_date(); PdfPageAnnotationCommon::stroke_color(), PdfPageAnnotationCommon::set_stroke_color(), PdfPageAnnotationCommon::fill_color(), PdfPageAnnotationCommon::set_fill_color() functions; adds PdfPageAnnotationCommon::attachment_points() accessor function; adds conversion from chrono::DateTime types to PDF date strings in utils::dates; adds mutability and annotation creation functions to PdfPageAnnotations collection; adds new create_annotations.rs example; adds PdfPageTextSegment::chars() convenience function.
  • 0.8.19: adds bindings for FORM_OnAfterLoadPage(), FORM_OnBeforeClosePage(), FPDFCatalog_IsTagged(), FPDFBookmark_GetCount(), and FPDF_GetPageAAction() functions; adds the PdfBookmark::children_len() function; adjusts the behaviour of PdfPage::flatten() so that the page is reloaded after the call to FPDFPage_Flatten(). This ensures that the effect of the flatten operation is immediately visible to the caller; previously, it was necessary for the caller to explicitly drop and reload the page. For more details, see #140.
  • 0.8.18: adjusts PdfiumRenderWasmState::bind_to_pdfium() to fall back to Module["wasmExports"]["__indirect_function_table"] if Window.wasmTable global variable is not available, in response to upstream packaging changes at https://github.com/paulocoutinhox/pdfium-lib/releases. For more details, see #134.
  • 0.8.17: updates all examples (except for export.rs) to use extended Pdfium::default() implementation introduced in 0.8.12; fixes a segmentation fault in PdfDocument::drop() that can occur when using a V8/XFA-enabled build of Pdfium; adjusts PdfiumRenderWasmState::bind_to_pdfium() to fall back to Module["wasmExports"]["malloc"] and Module["wasmExports"]["free"] if Module["_malloc"] and Module["_free"] are not available, in response to upstream packaging changes at https://github.com/paulocoutinhox/pdfium-lib/releases. For more details, see #128.
  • 0.8.16: deprecates PdfBitmap::as_bytes() function in favour of PdfBitmap::as_raw_bytes(); adds new PdfBitmap::as_rgba_bytes() for returning pixel byte data with normalized color channels, irrespective of the original bitmap pixel format; updates the WASM-specific PdfBitmap::as_image_data() function to use PdfBitmap::as_rgba_bytes() instead of PdfBitmap::as_raw_bytes(), ensuring the color normalization behaviour of both WASM and non-WASM builds is identical; refactors PdfBookmarksIterator to use a standard depth-first graph traversal algorithm in response to #120; adds PdfBookmark::destination() function for retrieving the target destination of the action assigned to a bookmark, thanks to an excellent contribution from https://github.com/xVanTuring. Deprecated items will be removed in release 0.9.0.
  • 0.8.15: adds new reset_matrix() and reset_matrix_to_identity() functions to consumers of the create_transform_setters!() macro; deprecates set_matrix() in favour of apply_matrix() and PdfPage::set_matrix_with_clip() in favour of PdfPage::apply_matrix_with_clip(); adds a matching corrects a byte alignment bug that could occur when converting three-bytes-per-pixel bitmaps to four-bytes-per-pixel bitmaps, thanks to an excellent contribution from https://github.com/vladmovchan. Deprecated items will be removed in release 0.9.0.
  • 0.8.14: adjusts the PdfSearchOptions::as_pdfium() function introduced in 0.8.13 to return a c_ulong in order to fix a build-time error specific to Windows.
  • 0.8.13: addresses incorrect results returned by PdfPageTextObject::chars() as described in #98; adds new PdfPageTextSearch and PdfSearchOptions objects and new PdfPageText::search() function for running text searches across the text of a single page, thanks to an excellent contribution from https://github.com/zhonghua-wang; adds new examples/text_search.rs example.
  • 0.8.12: improves backwards compatibility with Rust versions prior to 1.62.0 for the PdfAppearanceMode enum added in 0.8.11 and the Ord trait implementation for PdfPoints added in 0.8.10; adds bindings for FPDF_PageToDevice() and FPDF_DeviceToPage() coordinate system conversion functions; exposes equivalent functionality in the high-level interface via new PdfPage::points_to_pixels() and PdfPage::pixels_to_points() functions; adds new examples/export_clip_crop.rs example; extends implementation of Pdfium::default() to try to load a Pdfium library located in the current working directory as well as a system library.
  • 0.8.11: adds the PdfAppearanceMode enum, the PdfFormFieldCommon::appearance_stream() and PdfFormFieldCommon::appearance_mode_value() functions, supporting internal implementation of those functions in PdfFormFieldPrivate; improves implementation of PdfFormRadioButtonField::is_checked() to take appearance streams into account; improves implementation of PdfForm::field_values() to take control groups into account.
  • 0.8.10: adds matrix math operations to PdfMatrix; adds PdfRect::transform() and PdfMatrix::apply_to_points() functions for transforming rectangles and points; uses matrix math operations in PdfMatrix to simplify implementation of PdfRenderConfig; adds PdfPagePathObjectSegments::raw() and PdfPagePathObjectSegments::transform() functions to allow iteration over raw or transformed path segment coordinates respectively; adds PdfDestinationViewSettings enum and PdfDestination::view() function for retrieving the view settings for an internal document destination.
  • 0.8.9: changes Pdfium::bind_to_library() and Pdfium::pdfium_platform_library_name_at_path() to take and return AsRef<Path> and PathBuf types rather than strings, thanks to an excellent contribution from https://github.com/heimmat.
  • 0.8.8: adjusts PdfiumRenderWasmState::bind_to_pdfium() to fall back to Module["asm"]["malloc"] and Module["asm"]["free"] if Module["_malloc"] and Module["_free"] are not available, in response to upstream packaging changes at https://github.com/paulocoutinhox/pdfium-lib/releases. For more details, see #95.
  • 0.8.7: renames PdfBitmapFormat::BRGx to PdfBitmapFormat::BGRx, deprecating the misspelled variant; adds Send and Sync implementations for PdfDocument struct when using the sync crate feature; adds Debug trait implementation to Pdfium for better once_cell compatibility; adds new constants PdfPoints::MAX, PdfPoints::MIN, and PdfRect::MAX; corrects a clipping bug in PdfPage::transform() and PdfPage::set_matrix() by setting the default clipping area to PdfRect::MAX rather than PdfPage::size(). Deprecated items will be removed in release 0.9.0.
  • 0.8.6: fixes a bug in PdfColor::as_pdfium_color() that resulted in the alpha value being ignored when composing the FPDF_DWORD representation of the color value; renames PdfBitmapRotation enum to PdfPageRenderRotation, deprecating the old enum; adds convenience functions PdfColor::mix(), PdfColor::mix_with(), PdfColor::from_hex(), PdfColor::to_hex(), and PdfColor::to_hex_with_alpha(); adds a wide variety of new color constants to PdfColor, deprecating all existing PdfColor::SOLID_* consts in favour of renamed consts with the SOLID_ prefix removed; moves PdfPoints and PdfRect structs out into new files; adds PdfQuadPoints struct; adds implementations of Display to PdfPoints, PdfRect, and PdfQuadPoints; fixes a double-free bug in PdfPageImageObject::get_image_from_bitmap_handle(). Deprecated items will be removed in release 0.9.0.
  • 0.8.5: adds PdfDestination::page_index() function; adds PdfPageObjectCommon::dash_phase() PdfPageObjectCommon::set_dash_phase(), PdfPageObjectCommon::dash_array(), and PdfPageObjectCommon::set_dash_array() functions thanks to an excellent contribution from https://github.com/DorianRudolph.
  • 0.8.4: fixes conditional import of PdfPoints struct into PdfPageImageObject so it is no longer dependent on the image crate feature being enabled; corrects a bug in the calculation of rendered bitmap pixel dimensions, thanks to an excellent contribution from https://github.com/slawekkolodziej.
  • 0.8.3: adds PdfFonts collection, PdfDocument::fonts() and PdfDocument::fonts_mut() accessor functions, and PdfFontToken struct; moves font constructors from PdfFont into PdfFonts, deprecating constructors in PdfFont; adds ToPdfFontToken trait, along with implementations of the trait for PdfFont, &PdfFont, and PdfFontToken; adjusts all functions that previously took a PdfFont or &PdfFont reference so that they now take a impl ToPdfFontToken. Deprecated items in PdfFont will be removed in release 0.9.0.
  • 0.8.2: adds PdfBitmap::from_bytes() function in response to #83; relaxes lifetime requirements on Pdfium::load_pdf_from_reader() and related functions thanks to an excellent contribution from https://github.com/bavardage.
  • 0.8.1: changes the data type of PdfBitmap::Pixels from u16 to c_int and adds the PdfBitmap::bytes_required_for_size() helper function in response to #80.
  • 0.8.0: removes the ability to acquire an owned PdfPages instance from PdfDocument::pages() as per #47; adds new PdfDocument::pages_mut() function to match reworked PdfDocument::pages() function; fixes a bug in the WASM implementation of FPDFText_GetBoundedText() as detailed in #77; reworks handling of FPDF_GetLastError() as detailed in #78.
  • 0.7.34: replaces functions in PdfPageLinks using linear traversal with binary search traversal; adds new PdfFormField enum; renames PdfPageObjectFormFragment to PdfPageXObjectFormObject to disambiguate it from PdfForm and PdfFormField; adds PdfPageAnnotationCommon::as_form_field() accessor function; adds form field structs PdfFormPushButtonField, PdfFormCheckboxField, PdfFormComboBoxField, PdfFormListBoxField, PdfFormRadioButtonField, PdfFormSignatureField, PdfFormTextField, and PdfFormUnknownField; adds PdfFormFieldOption struct and PdfFormFieldOptions collection for retrieving the options displayed within a list box or combo box field; adds PdfFormFieldCommon and PdfFormFieldPrivate traits and associated implementations for all PdfFormField field types; adds the PdfForm::field_values() convenience function; adds examples/form_fields.rs example.
  • 0.7.33: adds the create_transform_setters!() and create_transform_getters!() private macros, ensuring API consistency and maximising code reuse across all transformable objects; adds PdfPage::transform(), PdfPage::transform_with_clip(), and PdfPage::set_matrix_with_clip() functions; adds examples/matrix.rs example; adds bindings for remaining FPDF_*ClipPath*() functions.
  • 0.7.32: fixes off-by-one errors in PdfPageText::chars_inside_rect() and examples/chars.rs thanks to an excellent contribution from https://github.com/luketpeterson, adds support for grayscale image processing to PdfPageImageObject::get_image_from_bitmap_handle() thanks to an excellent contribution from https://github.com/stephenjudkins, and corrects a missing dependency when using pdfium-render without the default image crate feature.
  • 0.7.31: adds the PdfPageLinks collection, the PdfPage::links() and PdfPage::links_mut() functions, the PdfLink and PdfDestination structs, the PdfActionCommon and PdfActionPrivate traits, structs for the action types supported by Pdfium, the PdfActionUri::uri() function to address #68, and the new examples/links.rs example.
  • 0.7.30: deprecates the PdfPages::delete_page_at_index() and PdfPages::delete_page_range() functions; adds PdfPage::delete() function in response to #67. Deprecated items will be removed in release 0.9.0, although it may be possible to restore these functions if safer reference handling in PdfDocument and PdfPages is introduced as part of #47.
  • 0.7.29: removes the sync crate feature from the list of default crate features in response to #66.
  • 0.7.28: removes the PdfPageObjects::take_*() functions; adds PdfPageObject::is_copyable() PdfPageObject::try_copy(), PdfPageObjectGroup::retain(), PdfPageObjectGroup::retain_if_copyable(), PdfPageObjectGroup::is_copyable(), PdfPageObjectGroup::try_copy_onto_existing_page(), PdfPageObjectGroup::copy_onto_new_page_at_start(), PdfPageObjectGroup::copy_onto_new_page_at_end(), and PdfPageObjectGroup::copy_onto_new_page_at_index() functions; adds examples/copy_objects.rs example; fixes a bug in the propagation of a page's content regeneration strategy; removes all use of lazy_static! macro in favour of once_cell::sync::Lazy.
  • 0.7.27: adjusts examples/index.html to take into account upstream packaging changes in the WASM builds of Pdfium published at https://github.com/paulocoutinhox/pdfium-lib/releases; adds the image crate feature.
  • 0.7.26: adds sync default crate feature providing Send and Sync implementations for Pdfium struct; adds Display and Error trait implementations to PdfiumError for anyhow compatibility; adjusts WASM example to account for upstream changes in Emscripten packaging of Pdfium WASM builds; corrects a lifetime problem in Pdfium::load_pdf_from_bytes() and deprecates Pdfium::load_pdf_from_bytes() in favour of Pdfium::load_pdf_from_byte_slice() and Pdfium::load_pdf_from_byte_vec(). Deprecated items will be removed in release 0.9.0.
  • 0.7.25: adds the PdfPageAnnotationObjects collection and the PdfPageAnnotation::objects(), PdfPageInkAnnotation::objects_mut(), and PdfPageStampAnnotation::objects_mut() functions to the high-level interface.
  • 0.7.24: adds bindings for FPDFClipPath_CountPathSegments(), FPDFClipPath_GetPathSegment(), FPDFPath_CountSegments(), FPDFPath_GetPathSegment(), and FPDFPathSegment_*() functions; adds PdfFontGlyphs and PdfPagePathObjectSegments collections to the high-level interface, along with accessor functions in PdfFont and PdfPagePathObject; adds the PdfPathSegments trait; introduces some infrastructure necessary for the future implementation of a PdfClipPath object; adds PdfPages::first(), PdfPages::last(), and PdfPage::fonts() convenience functions.
  • 0.7.23: removes some unnecessary mutable bindings in PdfBitmap; uses #[cfg(doc)] declarations to ensure cargo doc generates documentation for all functionality, irrespective of the platform.
  • 0.7.22: attempts to work around two problems in Pdfium's bitmap generation when retrieving processed renderings of page image objects. See #52 for more information.
  • 0.7.21: adds bindings for FPDF_GetPageAAction(), FPDF_GetFileIdentifier(), and all remaining FPDFDest_*() and FPDFLink_*() functions; adds PdfAttachment::len() and PdfAttachment::is_empty() convenience functions; adds libstdc++ and libc++ crate features; adds color conversion functions to PdfiumLibraryBindings; corrects bugs in color conversion when working with PdfPageImageObject, as detailed in #50; fixes a bug in the WASM implementation of FPDFAnnot_GetAttachmentPoints(); corrects some small typos in examples.
  • 0.7.20: adds bindings for FPDFPage_*Thumbnail*(), FPDFLink_*(), and FPDFText_Find*() functions; adds PdfAttachments::create_attachment_from_bytes(), PdfAttachments::create_attachment_from_file(), PdfAttachments::create_attachment_from_reader(), PdfAttachments::create_attachment_from_fetch(),
    PdfAttachments::create_attachment_from_blob(), PdfAttachments::delete_at_index(), PdfAttachment::save_to_writer(), PdfAttachment::save_to_file(), PdfAttachment::save_to_blob(), PdfPage::has_embedded_thumbnail(), PdfPage::embedded_thumbnail(), and PdfPage::boundaries_mut() functions to the high-level interface; renames PdfAttachment::bytes() function introduced in 0.7.19 to PdfAttachment::save_to_bytes().
  • 0.7.19: adds bindings for FPDFDoc_*Attachment*() functions; adds PdfAttachments and PdfSignatures collections to the high-level interface.
  • 0.7.18: adds convenience bindings() accessor functions to PdfDocument, PdfPage, PdfBitmap, PdfFont, and various other interfaces, thanks to an excellent contribution from https://github.com/LU15W1R7H; deprecates Pdfium::get_bindings() in favour of Pdfium::bindings() for consistency. Deprecated items will be removed in release 0.9.0.
  • 0.7.17: relaxes some unnecessarily restrictive lifetime bounds in PdfPageObjectPath.
  • 0.7.16: adds PdfPageObjects::create_path_object_bezier() and PdfPageObjectPath::new_bezier() convenience functions; corrects some typos in documentation.
  • 0.7.15: adds PdfPageAnnotationCommon::name(), PdfPageAnnotationCommon::contents(), PdfPageAnnotationCommon::author(), PdfPageAnnotationCommon::creation_date(), and PdfPageAnnotationCommon::modification_date() functions for working with annotations; adds PdfPageText::for_annotation() and PdfPageText::chars_for_annotation() for more easily extracting text and characters associated with annotations; adds examples/annotations.rs and examples/image_extract.rs; renames examples/text.rs to examples/text_extract.rs.
  • 0.7.14: fixes a bug in the WASM implementation of FPDF_StructElement_GetStringAttribute(); pins required version of image crate to at least 0.24.0 or later to avoid incompatibility between the image::DynamicImage trait definitions in 0.23.x and 0.24.x; adds compatibility with web workers to the WASM implementation, thanks to an excellent contribution from https://github.com/NyxCode.
  • 0.7.13: adds transformation and clipping functions to PdfRenderConfig; adds bindings for FPDF_RenderPageBitmapWithMatrix(); deprecates PdfRenderConfig::rotate_if_portait() in favour of the correctly-spelled PdfRenderConfig::rotate_if_portrait(). Deprecated items will be removed in release 0.9.0.
  • 0.7.12: adds PdfPage::render_into_bitmap() and PdfPage::render_into_bitmap_with_config() functions for higher performance; deprecates PdfPage::get_bitmap() in favour of PdfPage::render(); deprecates PdfPage::get_bitmap_with_config() in favour of PdfPage::render_with_config(); deprecates PdfBitmapConfig in favour of PdfRenderConfig; deprecates PdfBitmap::render() as the function is no longer necessary. Deprecated items will be removed in release 0.9.0.
  • 0.7.11: adds the new WASM-specific PdfBitmap::as_array() function as a higher performance alternative to the cross-platform PdfBitmap::as_bytes() function, thanks to an excellent contribution from https://github.com/NyxCode.
  • 0.7.10: corrects some typos in documentation; adds additional constructors to PdfPageImageObject that apply a specified width and/or height at object creation time.
  • 0.7.9: adds retrieval of the list of image filters applied to a PdfPageImageObject; adds the PdfColorSpace enum; adds bindings for the FPDF_*Signature*(), FPDFSignatureObj_*(), and FPDF_StructTree_*() functions.
  • 0.7.8: adds image support to the PdfPageImageObject struct, the PdfPageObjects::add_image_object() and PdfPageObjects::create_image_object() functions, additional convenience functions for loading fonts from files and readers to PdfFont, and bindings for FPDF_VIEWERREF_Get*() functions.
  • 0.7.7: adds the thread_safe crate feature and the accompanying example in examples/thread_safe.rs.
  • 0.7.6: adds retrieval of text settings on a character-by-character basis to the PdfPageText and PdfPageTextObject objects; adds PdfPageTextSegment and PdfPageTextChar structs to the high-level interface; adds retrieval of current transformation settings to all page objects; adds the PdfPageTextObject::scaled_font_size() function and renames PdfPageTextObject::font_size() to PdfPageTextObject::unscaled_font_size() as these names make clearer the differences between scaled and unscaled font sizes in text objects; adds bindings for all remaining FPDFText_*() functions.
  • 0.7.5: corrects a bug in error handling on Windows. See #24 for more information.
  • 0.7.4: adds the PdfPageGroupObject::remove_objects_from_page() function; renamed PdfPageObjects::delete_object() and PdfPageObjects::delete_object_at_index() functions to PdfPageObjects::remove_object() and PdfPageObjects::remove_object_at_index() as these names better reflect the underlying operation that occurs.
  • 0.7.3: corrects a bug in the implementation of PdfPages::append() introduced in 0.7.2.
  • 0.7.2: adds object groups for manipulating and transforming groups of page objects as if they were a single object, and the PdfPages::watermark() function for applying individualized watermarks to any or all pages in a document. Fixes a potential double-free bug in PdfFont::drop().
  • 0.7.1: adds path segment creation to the PdfPagePathObject object, convenience functions for quickly creating rectangles, ellipses, and circles, and the PdfPageObjects::add_path_object() function.
  • 0.7.0: adds PdfPermissions collection, adds document loading and saving support, adds initial creation and editing support for documents, pages, and text objects, and improves WASM document file handling.
  • 0.6.0: fixes some typos in documentation, updates upstream Pdfium WASM package source repository name.
  • 0.5.9: corrects a bug in the statically linked bindings implementation. Adjusted tests to cover both dynamic and statically linked bindings implementations.
  • 0.5.8: corrects a bug in the WASM implementation of certain FPDFAnnot_*() functions. Resolves a potential memory leak affecting the WASM implementation of various FPDF_*() functions.
  • 0.5.7: adds support for binding to a statically-linked build of Pdfium, adds bindgen and static crate features.
  • 0.5.6: adds pdfium_render::prelude, adds bindings for FPDFAnnot_*() and FPDFPage_*Annot*() functions, adds PdfPageAnnotations collection and PdfPageAnnotation struct to the high-level interface.
  • 0.5.5: fixes two bugs in the WASM implementation, one to do with colors, one to do with text extraction. See #9 and #11 for more information.
  • 0.5.4: changes default setting of PdfBitmapConfig::set_reverse_byte_order() to true to switch from Pdfium's default BGRA8 pixel format to RGBA8. This is necessary since the image crate dropped support for BGRA8 in version 0.24. See #9 for more information.
  • 0.5.3: adds bindings for FPDFBookmark_*(), FPDFPageObj_*(), FPDFText_*(), and FPDFFont_*() functions, adds PdfPageObjects, PdfPageText, and PdfBookmarks collections to the high-level interface.
  • 0.5.2: adds bindings for FPDF_GetPageBoundingBox(), FPDFDoc_GetPageMode(), FPDFPage_Get*Box(), and FPDFPage_Set*Box() functions, adds PdfPageBoundaries collection to the high-level interface.
  • 0.5.1: adds bindings for FPDFPage_GetRotation() and FPDFPage_SetRotation() functions, adds PdfMetadata collection to the high-level interface.
  • 0.5.0: adds rendering of annotations and form field elements, thanks to an excellent contribution from https://github.com/inzanez.
  • 0.4.2: bug fixes in PdfBitmapConfig implementation.
  • 0.4.1: improvements to documentation and READMEs.
  • 0.4.0: initial release of minimal page rendering functionality.

pdfium-render's People

Contributors

777vasya77 avatar aaronrecord avatar ajrcarey avatar aruediger avatar dorianrudolph avatar dylan-dpc avatar heimmat avatar liammcdermott avatar luiswirth avatar luketpeterson avatar nyxcode avatar samsieber avatar slawekkolodziej avatar stephenjudkins avatar vladmovchan avatar xvanturing avatar zhonghua-wang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pdfium-render's Issues

Add compilation test of static bindings for 0.5.9.

Added simple compilation test of the static bindings feature; this simply checks that the bindings added in 0.5.7 compile correctly. This can be run via cargo test --features static. Bumped crate version to 0.5.9 in Cargo.toml. Published to crates.io.

Standardise lifetime and reference handling for child objects inside PdfDocument.

As of 0.7.19, the child objects inside PdfDocument are created and returned using a variety of different approaches:

  • Some immutable-only collections (with no mutable equivalent) are created fresh each time the accessor function is called, and always return a new object instance, e.g. PdfDocument::bookmarks(), PdfDocument::metadata(), PdfDocument::permissions(), PdfDocument::signatures().
  • Some collections that support both immutable and mutable access, and distinguish between mutable and immutable references, create a private owned collection instance inside the containing object as part of the object's new() constructor, then hand out mutable or immutable references to that owned collection as necessary, e.g. PdfDocument::attachments(), PdfDocument::attachments_mut().
  • PdfPages, which supports both immutable and mutable access but does not distinguish between mutable and immutable references, instead handing out a new object instance each time it is called from PdfDocument::pages().

Standardise the approach. All collections should create private owned collection instances inside the containing object as part of the object's new() constructor, function, then hand out mutable or immutable references as necessary. New object instances should never be handed out.

Add convenience functions for creating attached Bรฉzier curves.

PdfPageObjects already contains convenience functions for creating lines, rectangles, circles, and ellipses. Add an equivalent convenience function for creating a Beลบier curve.

Likewise, PdfPagePathObject already contains convenience functions for creating lines, rectangles, circles, and ellipses. Add an equivalent convenience function for creating a Bรฉzier curve.

Run in web worker

To run pdfium-render on the web, it's important to do the actual rendering in a worker. Otherwise, expensive operations block the UI. However, window is not accessible within workers.
Currently, running pdfium-render in a worker fails with

Uncaught (in promise) ReferenceError: Window is not defined
    at imports.wbg.__wbg_instanceof_Window_42f092928baaee84

Add FPDF_Set*Box() and FPDF_Get*Box() support for 0.5.2.

Added bindings for the various FPDF_Set*Box() and FPDF_Get*Box() functions. Exposed functionality as new PageBoundaries collection, available via PdfPage::boundaries() function. Reworked WASM implementation so that a separate javascript wrapper binding the Pdfium WASM module to pdfium-render is no longer necessary; instead, pdfium-render binds to Pdfium directly using js_sys::Reflect(). Reworked memory management functions; as part of this, fixed #5. Updated documentation. Pushed version 0.5.2 to crates.io.

Relax unnecessarily restrictive lifetime bounds in PdfPageObjectPath constructors.

While working on https://gitlab.duetto.dev/apps/rescore/-/issues/30, encountered a difficulty when creating detached PdfPageObjectPath objects in a function called inside a for loop. The problem was due to an overly restrictive lifetime bound on the PdfDocument reference passed to the PdfPageObjectPath::new() function; the signature calls for &'a PdfDocument<'a>, but in practice only &PdfDocument<'a> is actually required. There are similar restrictions on the PdfPageObjectPath::new_line(), PdfPageObject::new_bezier(), PdfPageObject::new_rect(), and other constructors. Relax these to avoid imposing unresolvable lifetime constraints on callers.

Add support for setting and retrieving page object transforms for more accurate text placement.

using the sample pdf #17 I got the desired output, however using other pdfs, the text is not placed correctly even without any change in the text formatting, just extracting the text deleting the original, and placing the same text will result in a wrongly placed text. I'm thinking that there are some other objects' properties that may have been lost and must be preserved to get the desired output.

Complete implementation of PdfiumRenderWasmState::copy_file_access_to_pdfium().

File access functions in Pdfium use the FPDF_FILEACCESS struct which contains a pointer to a callback function that Pdfium repeatedly calls to load (or save) blocks of data from (or to) a file. That function pointer points to a location in pdfium-render's local WASM memory heap, but Pdfium needs a pointer to a function in its own WASM memory heap. Simply copying the function to Pdfium's WASM heap is not sufficient, since the function will no longer have access to any data it expects to find in our local WASM heap.

Add path page object support.

Building on the addition of text page object support in 0.7.0, add support for the next major page object type: path objects.

Update Readme

Hi,

Update the repository name from "paulo-coutinho" to "paulocoutinhox".

Thanks.

Error when compiling on Windows

running these two programs seems to give a compile error on windows

use pdfium_render::prelude::*;

fn main()   {
    let pdfium = Pdfium::new(
        Pdfium::bind_to_library(Pdfium::pdfium_platform_library_name_at_path("./"))
            .or_else(|_| Pdfium::bind_to_system_library()).unwrap(),
    );

    // Create a new document containing a single page with the desired sample text.

    let document = pdfium.create_new_pdf().unwrap();

    let mut pages = document.pages();

    let mut page = pages.create_page_at_start(PdfPagePaperSize::a4()).unwrap();

    // Desired sample text:

    let sample_text = vec!(
            "TITLE HERE",
            "",
            "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum",
            "has been the industry's standard dummy text ever since the 1500s, when an unknown",
            "printer took a galley of type and scrambled it to make a type specimen book. It has",
            "survived not only five centuries, but also the leap into electronic typesetting, remaining",
            "essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets",
            "containing Lorem Ipsum passages, and more recently with desktop publishing software like",
            "Aldus PageMaker including versions of Lorem Ipsum.",
        );

    // Add the sample text to the page. We create a separate text object
    // for each line in the sample text.

    let regular_font = PdfFont::helvetica(&document);

    let bold_font = PdfFont::helvetica_bold(&document);

    let font_size = PdfPoints::new(12.0);

    let line_spacing = font_size * 1.5;

    let line_left = PdfPoints::new(50.0);

    let mut line_top = PdfPoints::new(700.0);

    for (index, line) in sample_text.iter().enumerate() {
        let font = {
            // Make the first line bold, all other lines regular.

            if index == 0 {
                &bold_font
            } else {
                &regular_font
            }
        };

        page.objects_mut()
            .create_text_object(line_left, line_top, line, font, font_size).unwrap();

        line_top -= line_spacing;
    }

    document.save_to_file("before.pdf").unwrap();
    
}
// this just a part of the program I included only the part where the error seems to occur
 let mut bold_word = PdfPageTextObject::new(
                                &document,
                                child_object.bold.clone(),
                                &object_txt.font(),
                                object_txt.font_size(),
                            )
                            .unwrap();
/* line 67 */         bold_part.translate(word_left, line_top).unwrap();
                            word_left += bold_part.width().unwrap();
//the error:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: PdfiumLibraryInternalError(Unknown)', src\place.rs:67:70  

since create_text_object() use translate() method in its definition I'm assuming that both errors are in fact the same.
both programs compile fine on WSL
It is worth mentioning that opening a file, removing text objects from it and saving the edited version worked fine. probably because we didn't need to use translate() method.

Can't get static compilation to work

I've tried building pdfium locally to get a libpdfium.a. I then instruct cargo to link with a build.rs like this:

fn main() {
    println!("cargo:rustc-link-search=native=./");
    println!("cargo:rustc-link-lib=static=pdfium");
}

And it does find my library. All good so far.

However I still get all these undefined reference errors when building. Here's a snippet of it (it filled more than my terminal could handle):

          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `bool v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::Register>::RecursivelyEmitMoveChainTargets<unsigned int>(unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::Register>::GapMoveTargets&)':
          ./../../v8/src/maglev/maglev-code-generator.cc:(.text+0x56f): undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::PopTargets(v8::internal::XMMRegister)':
          ./../../buildtools/third_party/libc++/trunk/include/array:218: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `bool v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::RecursivelyEmitMoveChainTargets<v8::internal::XMMRegister>(v8::internal::XMMRegister, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets&)':
          ./../../v8/src/maglev/maglev-code-generator.cc:(.text+0x4e9): undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::EmitMovesFromSource(v8::internal::XMMRegister, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets const&)':
          ./../../buildtools/third_party/libc++/trunk/include/array:218: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&>(std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&>(std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&>(std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&>(std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, std::Cr::__hash_map_iterator<std::Cr::__hash_iterator<std::Cr::__hash_node<std::Cr::__hash_value_type<unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets>, void*>*> > const&, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/new:(.text+0x471): undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(maglev-code-generator.o): in function `bool v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::RecursivelyEmitMoveChainTargets<unsigned int>(unsigned int, v8::internal::maglev::(anonymous namespace)::ParallelMoveResolver<v8::internal::XMMRegister>::GapMoveTargets&)':
          ./../../v8/src/maglev/maglev-code-generator.cc:(.text+0x57a): undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `v8::internal::SharedTurboAssemblerBase<v8::internal::TurboAssembler>::F64x2ConvertLowI32x4U(v8::internal::XMMRegister, v8::internal::XMMRegister, v8::internal::Register)':
          ./../../buildtools/third_party/libc++/trunk/include/__string/char_traits.h:236: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `v8::internal::SharedTurboAssemblerBase<v8::internal::TurboAssembler>::I32x4TruncSatF64x2SZero(v8::internal::XMMRegister, v8::internal::XMMRegister, v8::internal::XMMRegister, v8::internal::Register)':
          ./../../buildtools/third_party/libc++/trunk/include/__string/char_traits.h:236: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `v8::internal::SharedTurboAssemblerBase<v8::internal::TurboAssembler>::I32x4TruncSatF64x2UZero(v8::internal::XMMRegister, v8::internal::XMMRegister, v8::internal::XMMRegister, v8::internal::Register)':
          ./../../buildtools/third_party/libc++/trunk/include/__string/char_traits.h:236: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o):./../../buildtools/third_party/libc++/trunk/include/__string/char_traits.h:236: more undefined references to `std::Cr::__libcpp_verbose_abort(char const*, ...)' follow
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<int, v8::internal::compiler::CallDescriptor::Flag>(int, v8::internal::compiler::CallDescriptor::Flag, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<int, v8::internal::compiler::CallDescriptor::Flag>(int, v8::internal::compiler::CallDescriptor::Flag, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<int, v8::internal::compiler::CallDescriptor::Flag>(int, v8::internal::compiler::CallDescriptor::Flag, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::CallDescriptor::Flag&>(v8::internal::compiler::CallDescriptor::Flag&)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::CallDescriptor::Flag&>(v8::internal::compiler::CallDescriptor::Flag&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::CallDescriptor::Flag&>(v8::internal::compiler::CallDescriptor::Flag&)':
          ./../../v8/src/base/logging.h:141: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::operator<<(int)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::CallDescriptor::Flag&>(v8::internal::compiler::CallDescriptor::Flag&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::CallDescriptor::Flag&>(v8::internal::compiler::CallDescriptor::Flag&)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode>(v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode>(v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode>(v8::internal::compiler::MemoryAccessMode, v8::internal::compiler::MemoryAccessMode, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::MemoryAccessMode&>(v8::internal::compiler::MemoryAccessMode&)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::MemoryAccessMode&>(v8::internal::compiler::MemoryAccessMode&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::MemoryAccessMode&>(v8::internal::compiler::MemoryAccessMode&)':
          ./../../v8/src/base/logging.h:141: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::operator<<(int)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::MemoryAccessMode&>(v8::internal::compiler::MemoryAccessMode&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::MemoryAccessMode&>(v8::internal::compiler::MemoryAccessMode&)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::XMMRegister const&, v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&, v8::internal::XMMRegister const&, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::XMMRegister const&, v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&, v8::internal::XMMRegister const&, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::XMMRegister const&, v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&, v8::internal::XMMRegister const&, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::XMMRegister const&>(v8::internal::XMMRegister const&)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth>(v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth>(v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth>(v8::internal::compiler::AtomicWidth, v8::internal::compiler::AtomicWidth, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition>(v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition>(v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition>(v8::internal::compiler::FlagsCondition, v8::internal::compiler::FlagsCondition, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsCondition&>(v8::internal::compiler::FlagsCondition&)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsCondition&>(v8::internal::compiler::FlagsCondition&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(code-generator-x64.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsCondition&>(v8::internal::compiler::FlagsCondition&)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(unwinding-info-writer-x64.o): in function `v8::internal::compiler::UnwindingInfoWriter::BeginInstructionBlock(int, v8::internal::compiler::InstructionBlock const*)':
          ./../../buildtools/third_party/libc++/trunk/include/vector:1457: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(unwinding-info-writer-x64.o): in function `v8::internal::compiler::UnwindingInfoWriter::EndInstructionBlock(v8::internal::compiler::InstructionBlock const*)':
          ./../../v8/src/zone/zone.h:(.text+0x3a6): undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `v8::internal::compiler::InstructionScheduler::StressSchedulerQueue::PopBestCandidate(int)':
          ./../../buildtools/third_party/libc++/trunk/include/list:1708: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode>(v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode>(v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode, char const*)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >* v8::base::MakeCheckOpString<v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode>(v8::internal::compiler::FlagsMode, v8::internal::compiler::FlagsMode, char const*)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsMode&>(v8::internal::compiler::FlagsMode&)':
          ./../../buildtools/third_party/libc++/trunk/include/ios:709: undefined reference to `std::Cr::ios_base::init(void*)'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsMode&>(v8::internal::compiler::FlagsMode&)':
          ./../../buildtools/third_party/libc++/trunk/include/sstream:230: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:231: undefined reference to `vtable for std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:766: undefined reference to `std::Cr::basic_stringbuf<char, std::Cr::char_traits<char>, std::Cr::allocator<char> >::str() const'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:864: undefined reference to `std::Cr::basic_streambuf<char, std::Cr::char_traits<char> >::~basic_streambuf()'
          /usr/bin/ld: ./../../buildtools/third_party/libc++/trunk/include/sstream:866: undefined reference to `std::Cr::basic_ostream<char, std::Cr::char_traits<char> >::~basic_ostream()'
          /usr/bin/ld: .//libpdfium.a(instruction-scheduler.o): in function `std::Cr::basic_string<char, std::Cr::char_traits<char>, std::Cr::allocator<char> > v8::base::detail::PrintToString<v8::internal::compiler::FlagsMode&>(v8::internal::compiler::FlagsMode&)':
          ./../../v8/src/base/logging.h:54: undefined reference to `std::Cr::basic_ios<char, std::Cr::char_traits<char> >::~basic_ios()'
          /usr/bin/ld: .//libpdfium.a(memory-lowering.o): in function `v8::internal::compiler::MemoryLowering::AllocationGroup* v8::internal::Zone::New<v8::internal::compiler::MemoryLowering::AllocationGroup, v8::internal::compiler::Node*&, v8::internal::AllocationType&, v8::internal::compiler::Node*&, v8::internal::Zone*>(v8::internal::compiler::Node*&, v8::internal::AllocationType&, v8::internal::compiler::Node*&, v8::internal::Zone*&&)':
          ./../../buildtools/third_party/libc++/trunk/include/__tree:294: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(memory-lowering.o): in function `v8::internal::compiler::MemoryLowering::AllocationGroup* v8::internal::Zone::New<v8::internal::compiler::MemoryLowering::AllocationGroup, v8::internal::compiler::Node*&, v8::internal::AllocationType&, v8::internal::Zone*>(v8::internal::compiler::Node*&, v8::internal::AllocationType&, v8::internal::Zone*&&)':
          ./../../buildtools/third_party/libc++/trunk/include/__tree:294: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(cfx_xmldocument.o): in function `std::Cr::vector<std::Cr::unique_ptr<CFX_XMLNode, std::Cr::default_delete<CFX_XMLNode> >, std::Cr::allocator<std::Cr::unique_ptr<CFX_XMLNode, std::Cr::default_delete<CFX_XMLNode> > > >::back[abi:v16000]()':
          ./../../buildtools/third_party/libc++/trunk/include/vector:563: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(cfx_xmldocument.o): in function `void std::Cr::advance[abi:v16000]<std::Cr::move_iterator<std::Cr::__wrap_iter<std::Cr::unique_ptr<CFX_XMLNode, std::Cr::default_delete<CFX_XMLNode> >*> >, long, long, void>(std::Cr::move_iterator<std::Cr::__wrap_iter<std::Cr::unique_ptr<CFX_XMLNode, std::Cr::default_delete<CFX_XMLNode> >*> >&, long)':
          ./../../buildtools/third_party/libc++/trunk/include/__iterator/advance.h:64: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(cfx_xmlelement.o): in function `std::Cr::__tree_node_base<void*>* std::Cr::__tree_leaf[abi:v16000]<std::Cr::__tree_node_base<void*>*>(std::Cr::__tree_node_base<void*>*)':
          ./../../buildtools/third_party/libc++/trunk/include/__tree:223: undefined reference to `std::Cr::__libcpp_verbose_abort(char const*, ...)'
          /usr/bin/ld: .//libpdfium.a(cfx_xmlparser.o):./../../buildtools/third_party/libc++/trunk/include/__iterator/advance.h:64: more undefined references to `std::Cr::__libcpp_verbose_abort(char const*, ...)' follow
          collect2: error: ld returned 1 exit status
          
  = help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

error: could not compile `internal` due to previous error

Any ideas how I might fix this? Any help would be greatly appreciated.

Statically linking pdfium

To make my application more portable, I'd like to statically link PDFium. Could this be added to this crate?

Pdfium crashes during content regeneration after transferring page object memory ownership from one page to another.

Pdfium does not include page resizing functionality - a page's size is fixed at creation time - but in theory it should be possible to mimic by creating a new page at the desired new size, transferring all page objects from the old page to the new page, then deleting the old page. The new PdfPages::resize_page_at_index() implements this recipe.

Pdfium segfaults while regenerating content streams on the new page. gdb backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78741b6 in CPDF_Stream::TakeData(std::__1::unique_ptr<unsigned char, FxFreeDeleter>, unsigned long) () from ./libpdfium.so
(gdb) bt
#0  0x00007ffff78741b6 in CPDF_Stream::TakeData(std::__1::unique_ptr<unsigned char, FxFreeDeleter>, unsigned long) () from ./libpdfium.so
#1  0x00007ffff787478f in CPDF_Stream::SetDataAndRemoveFilter(pdfium::span<unsigned char const>) () from ./libpdfium.so
#2  0x00007ffff78748ed in CPDF_Stream::SetDataFromStringstreamAndRemoveFilter(std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> >*) () from ./libpdfium.so
#3  0x00007ffff7a02c7b in CPDF_PageContentGenerator::UpdateContentStreams(std::__1::map<int, std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> >, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> > > > >&&) ()
   from ./libpdfium.so
#4  0x00007ffff7a02b28 in CPDF_PageContentGenerator::GenerateContent() () from ./libpdfium.so
#5  0x00007ffff790c83d in FPDFPage_GenerateContent () from ./libpdfium.so
#6  0x000055555557d804 in pdfium_render::native::{impl#1}::FPDFPage_GenerateContent (self=0x555555707bc0, page=0x5555557e5fe0)
    at /home/alastair/.decrypt/Documents/Programming/Duet/src/rescore/shared/src/pdfium/src/native.rs:3542
#7  0x00005555555e2ae3 in pdfium_render::page::PdfPage::regenerate_content_immut (self=0x7fffffffd1e0) at src/page.rs:679
#8  0x00005555555e2a57 in pdfium_render::page::PdfPage::regenerate_content (self=0x7fffffffd1e0) at src/page.rs:670
#9  0x0000555555609e03 in pdfium_render::pages::PdfPages::resize_page_at_index (self=0x7fffffffdd20, size=..., index=0) at src/pages.rs:182
#10 0x000055555558500a in create::main () at examples/create.rs:99
(gdb) bt
#0  0x00007ffff78741b6 in CPDF_Stream::TakeData(std::__1::unique_ptr<unsigned char, FxFreeDeleter>, unsigned long) () from ./libpdfium.so
#1  0x00007ffff787478f in CPDF_Stream::SetDataAndRemoveFilter(pdfium::span<unsigned char const>) () from ./libpdfium.so
#2  0x00007ffff78748ed in CPDF_Stream::SetDataFromStringstreamAndRemoveFilter(std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> >*) () from ./libpdfium.so
#3  0x00007ffff7a02c7b in CPDF_PageContentGenerator::UpdateContentStreams(std::__1::map<int, std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> >, std::__1::less<int>, std::__1::allocator<std::__1::pair<int const, std::__1::basic_ostringstream<char, std::__1::char_traits<char>, FxPartitionAllocAllocator<char, &pdfium::internal::StringAllocOrDie> > > > >&&) ()
   from ./libpdfium.so
#4  0x00007ffff7a02b28 in CPDF_PageContentGenerator::GenerateContent() () from ./libpdfium.so
#5  0x00007ffff790c83d in FPDFPage_GenerateContent () from ./libpdfium.so
#6  0x000055555557d804 in pdfium_render::native::{impl#1}::FPDFPage_GenerateContent (self=0x555555707bc0, page=0x5555557e5fe0)
    at /home/alastair/.decrypt/Documents/Programming/Duet/src/rescore/shared/src/pdfium/src/native.rs:3542
#7  0x00005555555e2ae3 in pdfium_render::page::PdfPage::regenerate_content_immut (self=0x7fffffffd1e0) at src/page.rs:679
#8  0x00005555555e2a57 in pdfium_render::page::PdfPage::regenerate_content (self=0x7fffffffd1e0) at src/page.rs:670
#9  0x0000555555609e03 in pdfium_render::pages::PdfPages::resize_page_at_index (self=0x7fffffffdd20, size=..., index=0) at src/pages.rs:182
#10 0x000055555558500a in create::main () at examples/create.rs:99

Relevant Pdfium source file: https://pdfium.googlesource.com/pdfium/+/refs/heads/main/core/fpdfapi/parser/cpdf_stream.cpp

It's got to be a page object memory ownership problem, but without debugging symbols in the Pdfium build it's likely to be very difficult to track down.

Copying page objects (rather than transferring them) doesn't work either - Pdfium regenerates page content correctly, then crashes during saving. gdb backtrace:

corrupted double-linked list

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
Downloading 0.00 MB source file /usr/src/debug/glibc/nptl/pthread_kill.c
44            return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;                                                                
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007ffff7c8e3d3 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
#2  0x00007ffff7c3e838 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff7c28535 in __GI_abort () at abort.c:79
#4  0x00007ffff7c8245e in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7dc083e "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#5  0x00007ffff7c980cc in malloc_printerr (str=str@entry=0x7ffff7dbe300 "corrupted double-linked list") at malloc.c:5664
#6  0x00007ffff7c98bf4 in unlink_chunk (p=p@entry=0x5555557ef600, av=0x7ffff7dfebc0 <main_arena>) at malloc.c:1635
#7  0x00007ffff7c98d85 in malloc_consolidate (av=av@entry=0x7ffff7dfebc0 <main_arena>) at malloc.c:4780
#8  0x00007ffff7c9ae9f in _int_malloc (av=av@entry=0x7ffff7dfebc0 <main_arena>, bytes=6032) at malloc.c:3965
#9  0x00007ffff7c9c47a in __GI___libc_malloc (bytes=<optimized out>) at malloc.c:3321
#10 0x00007ffff7a4a0d7 in Cr_z_deflateInit2_ () from ./libpdfium.so
#11 0x00007ffff7a49f74 in Cr_z_deflateInit_ () from ./libpdfium.so
#12 0x00007ffff7a493ac in Cr_z_compress () from ./libpdfium.so
#13 0x00007ffff78a1abd in fxcodec::FlateModule::Encode(pdfium::span<unsigned char const>, std::__1::unique_ptr<unsigned char, FxFreeDeleter>*, unsigned int*) () from ./libpdfium.so
#14 0x00007ffff7879df8 in FlateEncode(pdfium::span<unsigned char const>, std::__1::unique_ptr<unsigned char, FxFreeDeleter>*, unsigned int*) ()
   from ./libpdfium.so
#15 0x00007ffff7865748 in CPDF_FlateEncoder::CPDF_FlateEncoder(CPDF_Stream const*, bool) () from ./libpdfium.so
#16 0x00007ffff7874bfc in CPDF_Stream::WriteTo(IFX_ArchiveStream*, CPDF_Encryptor const*) const () from ./libpdfium.so
#17 0x00007ffff79ffc51 in CPDF_Creator::WriteIndirectObj(unsigned int, CPDF_Object const*) () from ./libpdfium.so
#18 0x00007ffff79fffd0 in CPDF_Creator::WriteNewObjs() () from ./libpdfium.so
#19 0x00007ffff7a00c2a in CPDF_Creator::WriteDoc_Stage2() () from ./libpdfium.so
#20 0x00007ffff7a021ea in CPDF_Creator::Create(unsigned int) () from ./libpdfium.so
#21 0x00007ffff7918743 in (anonymous namespace)::DoDocSave(fpdf_document_t__*, FPDF_FILEWRITE_*, unsigned long, absl::optional<int>) ()
   from ./libpdfium.so
#22 0x00007ffff7918791 in FPDF_SaveWithVersion () from ./libpdfium.so
#23 0x000055555557b57c in pdfium_render::native::{impl#1}::FPDF_SaveWithVersion (self=0x555555705bc0, document=0x555555707ee0, 
    pFileWrite=0x7fffffffd628, flags=0, fileVersion=17)
    at /home/alastair/.decrypt/Documents/Programming/Duet/src/rescore/shared/src/pdfium/src/native.rs:3217
#24 0x0000555555584bd7 in pdfium_render::document::PdfDocument::save_to_writer<std::fs::File> (self=0x7fffffffd828, writer=...)
    at /home/alastair/.decrypt/Documents/Programming/Duet/src/rescore/shared/src/pdfium/src/document.rs:244
#25 0x00005555555838d5 in create::main () at examples/create.rs:107

I'm baffled by this second crash because it shouldn't be any different from creating the page objects individually by hand, and that approach obviously works fine.

method cannot be called on `DynamicImage` due to unsatisfied trait bounds

Hi

I'm newbie in rust )

I want to use this lib in mac os app and handle next error during run.

error[E0599]: the method `width` exists for enum `DynamicImage`, but its trait bounds were not satisfied
   --> /Users/.../cargo/git/checkouts/pdfium-render-c0a9ea3e3be0834d/a27b6f9/src/page_objects.rs:435:33
    |
435 |         let image_width = image.width();
    |                                 ^^^^^ method cannot be called on `DynamicImage` due to unsatisfied trait bounds
    |
   ::: /Users/.../.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.23.14/./src/dynimage.rs:43:1
    |
43  | pub enum DynamicImage {
    | ---------------------
    | |
    | doesn't satisfy `DynamicImage: PdfPageObjectCommon`
    | doesn't satisfy `DynamicImage: PdfPageObjectPrivate<'_>`
    |
note: trait bound `DynamicImage: PdfPageObjectPrivate<'_>` was not satisfied
   --> /Users/.../.cargo/git/checkouts/pdfium-render-c0a9ea3e3be0834d/a27b6f9/src/page_object.rs:801:8
    |
799 | impl<'a, T> PdfPageObjectCommon<'a> for T
    |             -----------------------     -
800 | where
801 |     T: PdfPageObjectPrivate<'a>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
4   | use image::GenericImageView;
    |

FPDF_FORMFILLINFO struct does not correctly pass from Rust to Javascript when compiling to WASM.

Calling Pdfium's FPDF_InitFormFillEnvironment() function requires us to pass a pointer to an FPDF_FORMFILLINFO struct. This struct mostly consists of pointers to callback functions used during user interaction with the form field widgets defined in the form; since we have no need of that functionality in pdfium-render, these pointers are all NULL.

When compiling to WASM, however, the struct is not correctly copied across from pdfium-render's WASM heap memory to Pdfium's WASM heap memory. Since we never use the struct anyway there is no reason for this bug to block the release of 0.5.0, but it would obviously be good to understand what is causing the problem and fix it.

Integrate form rendering contribution from pull request #3.

Merge pull request, tidy up code contribution, add FFI bindings for all FPDF_* modules (currently only fpdfview.h is used to generate FFI bindings - there are multiple modules exposed by Pdfium that should be included in addition to fpdfview.h), publish to crates.io as version 0.5.0.

Add text objects editing functionality

The easiest way IMO to edit a text object in a pdf file is if we can directly edit the raw object

BT /F13 12 Tf 288 720 Td (ABC) Tj ET
As a side effect we can easily edit many other properties of the text object, however I don't know how easy it is to implement this or if it's even possible. especially that I don't exactly understand how are document level objects and cross references tables and other stuff that I may not know about relate to the content of the text object

Cannot iterate over objects in a page while holding a mutable reference to that page.

Trying to apply this approach I mentioned in issue #17 :

  • Iterate through every text object in every page in the original document. extracting the text and formatting and position
  • Apply the changes, resulting in new Child Objects
  • iterate through every object, remove it from the document and place the new child objects
  • the first Child Object will be placed in the same position as the original object and the remaining Child Objects will be placed
    according to the bounds of the previous Child Object

I can't seem to find a way to iterate over a mutable reference of a page, I'm trying to delete the original text objects, and insert the new child objects.

pages.iter().for_each(|page|{          
        page.objects_mut().iter().for_each(|object|{       //cannot borrow page as mutable 
            if let Some(object_text) = object.as_text_object() {
                page.objects_mut().delete_object(object);           //cannot borrow page as mutable 
            }
        })
    })

Can you please provide an example?

Add FPDFAnnot_*() and FPDFPage_*Annot*() bindings for 0.5.6.

Added bindings for FPDFAnnot_*() and FPDFPage_Annot() functions. Added PdfPageAnnotations collection, PdfPageAnnotation enum, and related sub-type structs to high-level interface. Added prelude. Bumped crate version to 0.5.6. Published to crates.io.

Page object fill and stroke mode are specific to Path objects.

Follow-on from #25. PdfPageObject defines the PdfPageObject::fill_mode(), PdfPageObject::is_stroked(), and PdfPageObject::set_fill_and_stroke_mode() functions for all page objects. However, for any object that is not a Path object, these functions will return errors.

Since they are specific to Path objects, these functions should be moved into PdfPagePathObject.

Support higher performance bitmap retrieval when compiling to WASM.

Hey! Great crate, had a blast playing around with it!
I tried to beat PDF.js for rendering a page to a canvas, but I can't seem to get the performance any better than PDF.js.

It seems like it always creates a new buffer when calling the get_bitmap_* functions. Would it be possible to introduce a variant which takes a mutable reference to a buffer and renders to that? I am not sure how much performance is left on the table here, but it's probably not nothing.

Add embedded thumbnail support to PdfPage.

Embedded thumbnails can be provided for each page in a document at document creation time. While largely a legacy feature - modern PDF document generators rarely embed page thumbnails - Pdfium does still provide function support for this, so for completeness we should expose the functionality in the high level interface.

WASM build can crash with "RuntimeError Index out of bounds" when converting UTF-16LE text to UTF8

Follow-on from #10. The examples/objects sample, when compiled to WASM and run in the browser, will crash with a RuntimeError Index out of bounds during text conversion. Strangely, this appears to be happening when attempting to return a value from utils::get_string_from_pdfium_utf16le_bytes(), which may suggest an out-of-memory problem with the stack frame sizing in the default WASM compile settings.

Add bindings and functions to access segments of page path objects, font glyphs, and clip paths.

PDFIUM allows access to Path's points to extract vector data
Base API are:

FPDFPathObj_CountPoints
FPDFPathObj_GetPointType
FPDFPathObj_GetPointX
FPDFPathObj_GetPointY

Would be very nice to have access to this in pdfium-render, in an API that can look like this:

for i in 0..path.points_count() {
    let type = path.get_point_type(i);
    match type {
        PdfPagePathObject::POINT_TYPE_MOVETO => {
            let x = path.get_point_x(i, 0);
            let y = path.get_point_y(i, 0);
        },
        PdfPagePathObject::POINT_TYPE_LINETO => {
            let x = path.get_point_x(i, 0);
            let y = path.get_point_y(i, 0);
        },
        PdfPagePathObject::POINT_TYPE_BEZIERTO => {
            let x1 = path.get_point_x(i, 0);
            let y1 = path.get_point_y(i, 0);
            let x2 = path.get_point_x(i, 1);
            let y2 = path.get_point_y(i, 1);
            let x3 = path.get_point_x(i, 2);
            let y3 = path.get_point_y(i, 2);
        },
        ...
    }
}

Or even better:

for point in path.points() {
    match point {
        PdfPagePathObjectPoint::MoveTo(x, y) => {},
        PdfPagePathObjectPoint::LineTo(x, y) => {},
        PdfPagePathObjectPoint::BezierTo(x1, y1, x2, y2, x3, y3) => {},
        ...
    }
}

Complete FPDFAnnot_*() binding WASM implementations for 0.5.8.

Completed all FPDFAnnot_*() bindings left incomplete during 0.5.6. Corrected a potential memory leak where the copy_struct_from_pdfium() function freed the target buffer in Pdfium's WASM module after copying it, but the function was not guaranteed to be called if the call to the Pdfium FPDF_* function indicated a failure value; in that case, a previously allocated buffer would not be freed. Bumped crate version number in Cargo.toml to 0.5.8. Published to crates.io.

Extract bounding box per word?

Hello, this is maybe more a pdfium question than pdfium-render question, but I hope you don't mind, and can help me anyway.

I am interesting in using pdfium-render essentially to replace pdftotext -bbox foobar.pdf which outputs a bbox per word, like such:

<word xMin="301.703800" yMin="104.483700" xMax="309.697000" yMax="115.283700">is</word>
<word xMin="313.046200" yMin="104.483700" xMax="318.374200" yMax="115.283700">a</word>
<word xMin="321.603400" yMin="104.483700" xMax="365.509000" yMax="115.283700">universal</word>
<word xMin="368.858200" yMin="104.483700" xMax="384.821800" yMax="115.283700">file</word>
<word xMin="388.291000" yMin="104.483700" xMax="420.229000" yMax="115.283700">format</word>

However, if I run some code such as:

for object in page.objects().iter() {
    if let Some(text) = object.as_text_object() {
        let bounds = object.bounds();
        //...

I tend to get the bounds for a number of words, perhaps a line, or a paragraph, not quite sure yet.

Can you guide me how to extract the bounds on a per-word basis?

Thanks in advance!

Add support for FPDFPage_GetRotation() and FPDFPage_SetRotation().

Added native and WASM bindings. Exposed via PdfPage::rotation() and PdfPage::set_rotation() (the latter requires mut self; there is currently no way to actually get a mutable reference to any pdfium-render object). Bumped crate version to 0.5.1. Updated README.md. Pushed to crates.io.

Closing a font handle can segfault Pdfium.

The PdfFont destructor calls FPDFFont_Close() on its font handle when it's dropped. This is done for every FPDF_FONT handle wrapped by an PdfFont object, irrespective of whether we created the font ourselves, or retrieved an existing font from a document.

Calling FPDFFont_Close() on fonts we did not load ourselves is unnecessary, and can segfault Pdfium. FPDFFont_Close() only needs to be called on fonts we load ourselves via FPDFText_LoadFont() or FPDFText_LoadStandardFont().

Retrieve comments and metadata from page annotations.

Hi there! Great lib and I was able to use it to read the PDF!

I was hoping to work with notes, such as highlight. I can get the rect object but couldn't find the Api (perhaps FPDFText_GetBoundedText? I'm not sure as I'm new to Pdfium as well. ) to use the rect of a highlight area to get the highlighted texts.

I was also wondering if it's possible to get the comment text that I type in the pop-up box as well.

Thank you!

Add image page object support.

Fleshed out image object functions in PdfPageImageObject.

The FPDFBitmap_GetBuffer() function is problematic. It returns a pointer to a mutable buffer of pixel data. Mutating that buffer changes the image linked to an image object. When compiling to WASM, the buffer lives in a separate WASM module, so the buffer returned by the WasmPdfiumBindings::FPDFBitmap_GetBuffer() is necessarily a copy (since it must reside in pdfium-render's WASM module, not Pdfium's). Mutating this buffer does nothing since Pdfium never sees it, and there is no way for pdfium-render to know when the caller has finished mutating data, so there is no reliable way for pdfium-render to copy any changes made to the buffer back across to Pdfium's WASM module.

Adjusted definition of FPDFBitmap_GetBuffer() so that it returns *const c_void rather than *mut c_void when compiling to WASM, in order to make the problem more obvious to the caller. (Obviously the caller can recast the pointer to *mut if they really want to, but this forces them to do so.) Added doc comments to the binding to explain the problem. Added new FPDFBitmap_SetBuffer() function that makes it easy for a caller to provide an updated pixel data buffer for a bitmap in a way that works for all target platforms including WASM.

Allow reuse of PdfBitmap when rendering pages

get_bitmap_with_config is quite slow on WASM. For a 2000x2000 bitmap, it takes ~11ms on my machine.
Most of that time is spent in create_empty_bitmap_handle. I will explore what optimizations can be done to improve this, especially on WASM.

After #32, which made the actual rendering process much faster, here is the crude flamegraph I generated.
Unlike the graphs in #32, this test is more realistic, rendering a real page with a lot of content:
image

"TOTAL" is the whole rendering process, starting with getting a specific page from a document, and ending with drawing the bitmap to a canvas.
image

`get_processed_image` gives reversed byte order

So I tried the following:

    let document = pdfium.load_pdf_from_file(&args.file, None)?;

    for (page_n, page) in document.pages().iter().enumerate() {
        for (object_n, object) in page.objects().iter().enumerate() {
            match &object {
                PdfPageObject::Text(_) => println!("Got Text object"),
                PdfPageObject::Path(_) => println!("Got Path object"),
                PdfPageObject::Image(image_obj) => {
                    println!("Got Image object");
                    let image = image_obj.get_processed_image(&document)?;
                    image.save(format!("{page_n:0>3}_{object_n:0>3}.jpeg"))?;
                }
                PdfPageObject::Shading(_) => println!("Got Shading object"),
                PdfPageObject::FormFragment(_) => println!("Got FormFragment object"),
                PdfPageObject::Unsupported(_) => println!("Got Unsupported object"),
            }
        }
    }

This worked on the first image of a PDF I tried it on, after which I got an error Error: Pdfium(PdfiumLibraryInternalError(Unknown)). But the important point is that the image that did manage to get extracted had the colours all wrong - a mostly red image turned blue. I'm guessing this is due to #9 and that this doesn't use the set_reverse_byte_order flag?

lifetime problems with self-referential struct

Hi, first off thanks for this library. It's really nice to be able to use such a good pdf renderer like pdfium in rust.
I'm integrating pdfium into my digital pen note taking application, which needs to re-render the pdf potentially every frame (when scaling, rotating or translating the page).

I have major issues with the API that is provided by pdfium-render. There are lifetimes everywhere (which in itself might be justified) but the most function signatures don't have explicit lifetimes and as a consequence all lifetimes are the same, which is overly restrictive. This is probably rather easy to solve.

Furthermore the PdfDocument requires a bytes slice when loading from bytes. This means the document can't own the bytes and I have to store them separately from the document. This results in a self referential struct that contains bot the document and the bytes.
It's not a solution to re-parse the document every time from the bytes as this is too slow. Do you have a solution for this problem?

I would be willing to do some contributions to this project as I heavily rely on it and need it for my own project.

Edit: After giving this all some more thought and taking a look at some functions in pdfium-render, I now think that these restrictions are from the C++ pdfium library. That's just how it is designed, right? It just happens to not align very well with the way the borrow checker would like you to write rust code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.