Skip to content

Commit

Permalink
Resolves #168
Browse files Browse the repository at this point in the history
  • Loading branch information
Alastair Carey committed Dec 31, 2024
1 parent e711eb7 commit 924d001
Show file tree
Hide file tree
Showing 58 changed files with 1,733 additions and 1,328 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ examples/test*.png

# Do not check Visual Studio Code-specific files into source control

*.code-workspace
*.code-workspace
.history/
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ Short, commented examples that demonstrate all the major Pdfium document handlin
_Note: upcoming release 0.9.0 will remove all deprecated items. For a complete list of deprecated
items, see <https://github.com/ajrcarey/pdfium-render/issues/36>._

Release 0.8.28 fixes a bug in page object handling where it was possible to apply a change to a page object - a transformation, for example - that might not be captured during automatic content regeneration of the containing page.

Release 0.8.27 adds a new `axum_once_cell` example demonstrating how to use Pdfium safely across asynchronous tasks with Axum, thanks to an excellent contribution from <https://github.com/danwritecode>, and fixes two bugs related to memory safety in the WASM bindings implementation, thanks to an excellent contribution from <https://github.com/samsieber>. The first bug affected certain UTF-16 string handling operations; the second bug could result in data corruption when working with raw bitmap pixel buffers.

Release 0.8.26 relaxes the minimum supported Rust version to 1.61 based on user feedback, increments the `pdfium_latest` feature to `pdfium_6721` to match new Pdfium release 6721 at <https://github.com/bblanchon/pdfium-binaries>, adds new crate features `image_025`, `image_024`, and `image_023` to allow explicitly pinning the version of `image` that should be used by `pdfium-render`, sets `image` to `image_025`, and adjusts bookmark traversal so that bookmarks are returned in a more natural order, thanks to an excellent contribution from <https://github.com/mlaiosa>.

Release 0.8.25 establishes a minimum supported Rust version of 1.60 for `pdfium-render`, increments the `pdfium_latest` feature to `pdfium_6666` to match new Pdfium release 6666 at <https://github.com/bblanchon/pdfium-binaries>, adds new crate features `pdfium_use_skia`, `pdfium_use_win32`, `pdfium_enable_xfa`, and `pdfium_enable_v8` to make available certain Pdfium functions that require Pdfium to be built with specific compile-time flags, and adds bindings for all remaining `FPDF_*` functions in the Pdfium API to `PdfiumLibraryBindings`, an important milestone leading up to release 0.9.0.

Release 0.8.24 fixes a bug in certain string handling operations in the WASM bindings implementation, and introduces the ability to control the version of the Pdfium API used by `pdfium-render`. By default `pdfium-render` uses the latest released version of the Pdfium API, potentially requiring you to upgrade your Pdfium library if the latest release contains breaking changes. This can be inconvenient! To explicitly use an older API version, select one of the crate's Pdfium version feature flags when taking `pdfium-render` as a dependency in your project's `Cargo.toml`. See the "Crate features" section below for more information.

## Binding to Pdfium

`pdfium-render` does not include Pdfium itself. You have several options:
Expand Down Expand Up @@ -300,6 +300,7 @@ will be removed in release 0.9.0.

## Version history

* 0.8.28: adds new `PdfSignature::modification_detection_permission()` function; adds `PdfQuadPoints::transform()` and additional utility functions to reach parity with `PdfRect`; changes return type of `PdfPageObject::bounds()` from `PdfRect` to `PdfQuadPoints`; deprecates direct `PdfRect` field access in favour of accessor functions; fixes a bug in content regeneration that could drop trailing transformations to page objects. Deprecated items will be removed in release 0.9.0.
* 0.8.27: adds new `examples/axum_once_cell.rs` example, thanks to an excellent contribution from <https://github.com/danwritecode>; fixes a WASM-specific bug in string termination detection when copying `FPDF_WIDESTRING` buffers to Pdfium's WASM address space; deprecates the memory-unsafe WASM implementation of `FPDFBitmap_GetBuffer` in favour of `FPDFBitmap_GetBuffer_as_vec` and `FPDFBitmap_GetBuffer_as_array` (renamed from `FPDFBitmap_GetArray`), thanks to an excellent contribution from <https://github.com/samsieber>; establishes upper bound on `wasm-bindgen` dependency to avoid a build failure during Github workflow automated build that was introduced in `wasm-bindgen-macros` versions 0.2.96 and later, as described at <https://github.com/ajrcarey/pdfium-render/issues/177>; completes expansion of all `FPDF_*` doc comments in `PdfiumLibraryBindings` trait. Deprecated items will be removed in release 0.9.0.
* 0.8.26: relaxes version constraint on `chrono` dependency based on user feedback, relaxing the minimum supported Rust version to 1.61; increments the `pdfium_latest` feature to `pdfium_6721` to match new Pdfium release 6721 at <https://github.com/bblanchon/pdfium-binaries>; synchronises `pdfium_future` feature against current Google mainline; adds new crate features `image_025`, `image_024`, and `image_023` to allow explicitly pinning the version of `image` that should be used by `pdfium-render`, sets `image` to `image_025`; adjusts bookmark traversal so that bookmarks are returned in a more natural order, thanks to an excellent contribution from <https://github.com/mlaiosa>.
* 0.8.25: adds bindings for all outstanding Pdfium API functions, including `FPDFAnnot_GetFormAdditionalActionJavaScript()`, `FPDFBitmap_Create()`, `FPDFAnnot_GetFormFieldAlternateName()`, `FPDFAnnot_GetFileAttachment()`, `FPDFAnnot_AddFileAttachment()`, `FPDFAvail_Create()`, `FPDFAvail_Destroy()`, `FPDFAvail_IsDocAvail()`, `FPDFAvail_GetDocument()`, `FPDFAvail_GetFirstPageNum()`, `FPDFAvail_IsPageAvail()`, `FPDFAvail_IsFormAvail()`, `FPDFAvail_IsLinearized()`, `FPDFAnnot_GetFontColor()`, `FPDFPageObj_TransformF()`, `FPDFPageObj_GetMarkedContentID()`, `FPDF_StructElement_GetActualText()`, `FPDF_StructElement_GetObjType()`, `FPDF_StructElement_GetChildMarkedContentID()`, `FPDF_StructElement_GetAttributeAtIndex()`, `FPDF_StructElement_Attr_GetName()`, `FPDF_StructElement_Attr_GetValue()`, `FPDF_StructElement_Attr_GetType()`, `FPDF_StructElement_Attr_GetBooleanValue()`, `FPDF_StructElement_Attr_GetNumberValue()`, `FPDF_StructElement_Attr_GetStringValue()`, `FPDF_StructElement_Attr_GetBlobValue()`, `FPDF_StructElement_Attr_GetChildAtIndex()`, `FPDF_StructElement_GetMarkedContentIdCount()`, `FPDF_StructElement_GetMarkedContentIdAtIndex()`, `FPDF_ARGB()`, `FPDF_GetBValue()`, `FPDF_GetGValue()`, `FPDF_GetRValue()`, `FPDF_MovePages()`, `FPDFImageObj_GetImagePixelSize()`, `FPDFPageObj_GetRotatedBounds()`, `FPDFText_LoadCidType2Font()`, `FPDFTextObj_GetRenderedBitmap()`, `FPDF_FFLDrawSkia()`, `FPDF_NewXObjectFromPage()`, `FPDF_CloseXObject()`, `FPDF_NewFormObjectFromXObject()`, `FPDF_CopyViewerPreferences()`, `FPDF_RenderPageBitmapWithColorScheme_Start()`, `FPDF_RenderPageBitmap_Start()`, `FPDF_RenderPage_Continue()`, `FPDF_RenderPage_Close()`, `FPDF_GetDefaultTTFMap()`, `FPDF_GetDefaultTTFMapCount()`, `FPDF_GetDefaultTTFMapEntry()`, `FPDF_AddInstalledFont()`, `FPDFText_IsGenerated()`, `FPDFText_IsHyphen()`, `FPDFText_HasUnicodeMapError()`, `FPDF_InitLibraryWithConfig()`, `FPDF_SetSandBoxPolicy()`, `FPDF_SetPrintMode()`, `FPDF_DocumentHasValidCrossReferenceTable()`, `FPDF_GetTrailerEnds()`, `FPDF_GetDocUserPermissions()`, `FPDF_GetPageWidth()` `FPDF_GetPageHeight()` `FPDF_GetPageSizeByIndex()` `FPDF_RenderPageSkia()`, `FPDF_CountNamedDests()`, `FPDF_GetNamedDestByName()`, `FPDF_GetNamedDest()`, `FPDF_GetXFAPacketCount()`, `FPDF_GetXFAPacketName()`, `FPDF_GetXFAPacketContent()`, `FPDF_GetRecommendedV8Flags()`, `FPDF_GetArrayBufferAllocatorSharedInstance()`, `FPDF_BStr_Init()`, `FPDF_BStr_Set()`, `FPDF_BStr_Clear()`, `FPDF_SetPrintMode()`, and `FPDF_RenderPage()`; adds `pfdium_use_skia`,`pdfium_use_win32`, `pdfium_enable_xfa`, and `pdfium_enable_v8` crate feature flags; adjusts dependency versions in `Cargo.toml` to meet a minimum supported Rust version (MSRV) of Rust 1.60; establishes upper bound on `bindgen` dependency to avoid a build failure when compiling to WASM that was introduced in `bindgen` versions 0.70.0 and later, as described at <https://github.com/ajrcarey/pdfium-render/issues/156>.
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
name = "pdfium-render-wasm-example"
version = "1.0.0"
edition = "2018"
authors = ["Alastair Carey <alastair@duetto.dev>"]
authors = ["Alastair Carey <alastair@alastaircarey.com>"]
publish = true

[lib]
Expand Down
16 changes: 8 additions & 8 deletions examples/chars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ fn main() -> Result<(), PdfiumError> {
println!(
"{}: ({}, {}) - ({}, {})",
word,
start.left.value,
start.bottom.value,
char.loose_bounds()?.left.value, // The word ends at the space's leading (left) edge
char.loose_bounds()?.top.value
start.left().value,
start.bottom().value,
char.loose_bounds()?.left().value, // The word ends at the space's leading (left) edge
char.loose_bounds()?.top().value
);

// Prepare for the next word.
Expand All @@ -73,10 +73,10 @@ fn main() -> Result<(), PdfiumError> {
println!(
"{}: ({}, {}) - ({}, {})",
word,
start.left.value,
start.bottom.value,
char.loose_bounds()?.right.value,
char.loose_bounds()?.top.value
start.left().value,
start.bottom().value,
char.loose_bounds()?.right().value,
char.loose_bounds()?.top().value
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/descenders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn main() -> Result<(), PdfiumError> {
"Character {}: \"{}\" descends {} points below the baseline",
index,
char.unicode_string().unwrap(),
object.get_vertical_translation().value - char.tight_bounds()?.bottom.value
object.get_vertical_translation().value - char.tight_bounds()?.bottom().value
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions examples/export_clip_crop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ fn main() -> Result<(), PdfiumError> {
let config = PdfRenderConfig::new().set_target_width(2000);

let (clip_left, clip_top) =
page.points_to_pixels(bounds.left, bounds.top, &config)?;
page.points_to_pixels(bounds.left(), bounds.top(), &config)?;

let (clip_right, clip_bottom) =
page.points_to_pixels(bounds.right, bounds.bottom, &config)?;
page.points_to_pixels(bounds.right(), bounds.bottom(), &config)?;

// Render the portion of the page within the clipping rectangle...

Expand Down
8 changes: 4 additions & 4 deletions examples/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ pub fn main() -> Result<(), PdfiumError> {
"Page {} has defined {:#?} box ({}, {}) - ({}, {})",
index,
boundary.box_type,
boundary.bounds.left.value,
boundary.bounds.top.value,
boundary.bounds.right.value,
boundary.bounds.bottom.value,
boundary.bounds.left().value,
boundary.bounds.top().value,
boundary.bounds.right().value,
boundary.bounds.bottom().value,
);
}

Expand Down
8 changes: 4 additions & 4 deletions examples/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ pub async fn log_page_metrics_to_console(url: String) {
"Page {} has defined {:#?} box ({}, {}) - ({}, {})",
page_index,
boundary.box_type,
boundary.bounds.left.value,
boundary.bounds.top.value,
boundary.bounds.right.value,
boundary.bounds.bottom.value,
boundary.bounds.left().value,
boundary.bounds.top().value,
boundary.bounds.right().value,
boundary.bounds.bottom().value,
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub trait PdfiumLibraryBindings {
/// Returns Pdfium's internal `FPDF_PAGEOBJECT` handle for the given [PdfPageObject].
#[inline]
fn get_handle_from_object(&self, object: &PdfPageObject) -> FPDF_PAGEOBJECT {
object.get_object_handle()
object.object_handle()
}

/// Returns the API version of the Pdfium FPDF_* API currently in use.
Expand Down
7 changes: 4 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ pub enum PdfiumError {
UnknownActionType,
UnknownAppearanceMode,
PageObjectIndexOutOfBounds,
PageObjectNotAttachedToPage,
PageObjectAlreadyAttachedToDifferentPage,
PageAnnotationIndexOutOfBounds,
PageObjectNotAttachedToAnnotation,
OwnershipNotAttachedToDocument,
OwnershipNotAttachedToPage,
OwnershipAlreadyAttachedToDifferentPage,
OwnershipNotAttachedToAnnotation,
FormFieldOptionIndexOutOfBounds,
FormFieldAppearanceStreamUndefined,
PageFlattenFailure,
Expand Down
3 changes: 2 additions & 1 deletion src/pdf/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::pdf::action::remote_destination::PdfActionRemoteDestination;
use crate::pdf::action::unsupported::PdfActionUnsupported;
use crate::pdf::action::uri::PdfActionUri;

/// The type of action associated with a clickable link or document bookmark.
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub enum PdfActionType {
GoToDestinationInSameDocument = PDFACTION_GOTO as isize,
Expand Down Expand Up @@ -117,7 +118,7 @@ impl<'a> PdfAction<'a> {
/// Note that Pdfium does not support or recognize all PDF action types. For instance,
/// Pdfium does not currently support or recognize the interactive Javascript action type
/// supported by Adobe Acrobat or Foxit's commercial PDF SDK. In these cases,
/// Pdfium will return `PdfActionType::Unsupported`.
/// Pdfium will return [PdfActionType::Unsupported].
#[inline]
pub fn action_type(&self) -> PdfActionType {
match self {
Expand Down
36 changes: 17 additions & 19 deletions src/pdf/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::bindgen::{
};
use crate::bindings::PdfiumLibraryBindings;
use crate::error::{PdfiumError, PdfiumInternalError};
use crate::pdf::document::page::render_config::PdfRenderSettings;
use crate::pdf::document::page::render_config::PdfPageRenderSettings;
use crate::utils::pixels::{aligned_bgr_to_rgba, aligned_rgb_to_rgba, bgra_to_rgba};
use std::os::raw::c_int;

Expand Down Expand Up @@ -46,7 +46,7 @@ struct JsValue;
///
/// While Pdfium will accept pixel sizes in either dimension up to the limits of [i32],
/// in practice the maximum size of a bitmap image is limited to approximately 2,320,723,080 bytes
/// (a little over 2 Gb). You can use the [PdfBitmap::bytes_required_for_size()] function
/// (a little over 2 Gb). You can use the [PdfBitmap::bytes_required_for_size] function
/// to estimate the maximum size of a bitmap image for a given target pixel width and height.
pub type Pixels = i32;

Expand Down Expand Up @@ -194,9 +194,9 @@ impl<'a> PdfBitmap<'a> {
/// Lets this [PdfBitmap] know whether it was created from a rendering configuration
/// that instructed Pdfium to reverse the byte order of generated image data from its
/// default of BGR8 to RGB8. The setting of this flag determines the color channel
/// normalization strategy used by [PdfBitmap::as_rgba_bytes()].
/// normalization strategy used by [PdfBitmap::as_rgba_bytes].
#[inline]
pub(crate) fn set_byte_order_from_render_settings(&mut self, settings: &PdfRenderSettings) {
pub(crate) fn set_byte_order_from_render_settings(&mut self, settings: &PdfPageRenderSettings) {
self.was_byte_order_reversed_during_rendering = settings.is_reversed_byte_order_flag_set
}

Expand Down Expand Up @@ -239,10 +239,10 @@ impl<'a> PdfBitmap<'a> {

/// Returns an immutable reference to the bitmap buffer backing this [PdfBitmap].
///
/// Unlike [PdfBitmap::as_rgba_bytes()], this function does not attempt any color channel normalization.
/// To adjust color channels in your own code, use the [PdfiumLibraryBindings::bgr_to_rgba()],
/// [PdfiumLibraryBindings::bgra_to_rgba()], [PdfiumLibraryBindings::rgb_to_bgra()],
/// and [PdfiumLibraryBindings::rgba_to_bgra()] functions.
/// Unlike [PdfBitmap::as_rgba_bytes], this function does not attempt any color channel normalization.
/// To adjust color channels in your own code, use the [PdfiumLibraryBindings::bgr_to_rgba],
/// [PdfiumLibraryBindings::bgra_to_rgba], [PdfiumLibraryBindings::rgb_to_bgra],
/// and [PdfiumLibraryBindings::rgba_to_bgra] functions.
pub fn as_raw_bytes(&self) -> Vec<u8> {
self.bindings.FPDFBitmap_GetBuffer_as_vec(self.handle)
}
Expand Down Expand Up @@ -333,13 +333,13 @@ impl<'a> PdfBitmap<'a> {
/// this [PdfBitmap].
///
/// This function avoids a memory allocation and copy required by both
/// [PdfBitmap::as_rgba_bytes()] and [PdfBitmap::as_image_data()], making it preferable for
/// [PdfBitmap::as_rgba_bytes] and [PdfBitmap::as_image_data], making it preferable for
/// situations where performance is paramount.
///
/// Unlike [PdfBitmap::as_rgba_bytes()], this function does not attempt any color channel normalization.
/// To adjust color channels in your own code, use the [PdfiumLibraryBindings::bgr_to_rgba()],
/// [PdfiumLibraryBindings::bgra_to_rgba()], [PdfiumLibraryBindings::rgb_to_bgra()],
/// and [PdfiumLibraryBindings::rgba_to_bgra()] functions.
/// Unlike [PdfBitmap::as_rgba_bytes], this function does not attempt any color channel normalization.
/// To adjust color channels in your own code, use the [PdfiumLibraryBindings::bgr_to_rgba],
/// [PdfiumLibraryBindings::bgra_to_rgba], [PdfiumLibraryBindings::rgb_to_bgra],
/// and [PdfiumLibraryBindings::rgba_to_bgra] functions.
///
/// This function is only available when compiling to WASM.
#[cfg(any(doc, target_arch = "wasm32"))]
Expand All @@ -354,9 +354,9 @@ impl<'a> PdfBitmap<'a> {
///
/// `canvas.getContext('2d').putImageData(image_data);`
///
/// This function is slower than calling [PdfBitmap::as_array()] because it must perform
/// This function is slower than calling [PdfBitmap::as_array] because it must perform
/// an additional memory allocation in order to create the `ImageData` object. Consider calling
/// the [PdfBitmap::as_array()] function directly if performance is paramount.
/// the [PdfBitmap::as_array] function directly if performance is paramount.
///
/// This function is only available when compiling to WASM.
#[cfg(any(doc, target_arch = "wasm32"))]
Expand Down Expand Up @@ -396,16 +396,14 @@ mod tests {
use crate::utils::test::test_bind_to_pdfium;

#[test]
#[cfg(not(target_arch = "wasm32"))]
fn test_from_bytes() -> Result<(), PdfiumError> {
let pdfium = test_bind_to_pdfium();

let test_width = 2000;
let test_height = 4000;

let buffer_size_required = PdfBitmap::bytes_required_for_size(test_width, test_height);

let mut buffer = create_sized_buffer(buffer_size_required);
let mut buffer =
create_sized_buffer(PdfBitmap::bytes_required_for_size(test_width, test_height));

let buffer_ptr = buffer.as_ptr();

Expand Down
7 changes: 5 additions & 2 deletions src/pdf/color_space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::bindgen::{
};
use crate::error::PdfiumError;

/// The color space of any displayable object on a `PdfPage`.
#[cfg(doc)]
use crate::pdf::document::page::PdfPage;

/// The color space of any displayable object on a [PdfPage].
///
/// Colors can be described in any of a variety of color systems called _color spaces_.
/// Some color spaces are related to device color representation (e.g. grayscale, RGB, CMYK);
Expand Down Expand Up @@ -36,7 +39,7 @@ use crate::error::PdfiumError;
/// Non-RGB color spaces typically define a transform that enables color values in the color
/// space to be converted to an RGB approximation for on-screen display.
///
/// For more information on color spaces and their utilisation in PDF files, see Section 4.5
/// For more information on color spaces and their utilization in PDF files, see Section 4.5
/// of the PDF Reference Manual version 1.7, starting on page 235.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum PdfColorSpace {
Expand Down
Loading

0 comments on commit 924d001

Please sign in to comment.