Skip to content

Commit

Permalink
Progressing #168
Browse files Browse the repository at this point in the history
  • Loading branch information
Alastair Carey committed Dec 17, 2024
1 parent 99bd797 commit b35e3c6
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 46 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pdfium-render"
version = "0.8.27"
version = "0.8.28"
edition = "2018"
rust-version = "1.61"
publish = true
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ will be removed in release 0.9.0.

## Version history

* 0.8.27: adds new `axum_once_cell` example; 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`); 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.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>.
* 0.8.24: introduces crate feature flags for selecting Pdfium API versions to use in `PdfiumLibraryBindings`; reworked `build.rs` to output bindings for multiple sets of Pdfium header files; reworks bindings implementations to differentiate between API versions that include the `FPDFFont_*` and `FPDFText_GetTextObject()` functions added in 0.8.23, and API versions that do not; reinstates `FPDFText_GetTextRenderMode()` function removed in 0.8.23 behind feature flags; adds WASM bindings utility function `copy_string_to_pdfium()` to correctly copy the string data of an `FPDF_WIDESTRING` to Pdfium's WASM memory module, instead of just the pointer location; adds `PdfiumLibraryBindings::version()` function for reporting the currently configured API version; internally reorganizes source code layout to make the code structure clearer.
Expand Down
2 changes: 1 addition & 1 deletion examples/copy_objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn main() -> Result<(), PdfiumError> {
.map(|bounds| {
// Only select objects on the bottom half of the page.

bounds.top < source_page.height() / 2.0
bounds.top() < source_page.height() / 2.0
})
.unwrap_or(false)
})?;
Expand Down
2 changes: 1 addition & 1 deletion examples/create_annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn main() -> Result<(), PdfiumError> {
link_annotation.set_height(PdfPoints::new(50.0))?;
link_annotation
.attachment_points_mut()
.create_attachment_point_at_end(PdfQuadPoints::from_rect(PdfRect::new_from_values(
.create_attachment_point_at_end(PdfQuadPoints::from_rect(&PdfRect::new_from_values(
100.0, 100.0, 150.0, 150.0,
)))?;

Expand Down
3 changes: 1 addition & 2 deletions src/pdf/document/page/annotation/attachment_points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::bindgen::FPDF_ANNOTATION;
use crate::bindings::PdfiumLibraryBindings;
use crate::error::{PdfiumError, PdfiumInternalError};
use crate::pdf::quad_points::PdfQuadPoints;
use crate::pdf::rect::PdfRect;
use std::ops::{Range, RangeInclusive};

/// The zero-based index of a single attachment point inside its containing
Expand Down Expand Up @@ -82,7 +81,7 @@ impl<'a> PdfPageAnnotationAttachmentPoints<'a> {
return Err(PdfiumError::PageAnnotationAttachmentPointIndexOutOfBounds);
}

let mut result = PdfQuadPoints::from_rect(PdfRect::ZERO).as_pdfium();
let mut result = PdfQuadPoints::ZERO.as_pdfium();

if self
.bindings
Expand Down
24 changes: 12 additions & 12 deletions src/pdf/document/page/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,24 +414,24 @@ impl<'a> PdfPageAnnotations<'a> {

let bounds = object.bounds()?;

annotation.set_position(bounds.left, bounds.bottom)?;
annotation.set_position(bounds.left(), bounds.bottom())?;
annotation.set_stroke_color(color)?;

const SQUIGGLY_HEIGHT: f32 = 12.0;

let annotation_top = bounds.bottom.value - 5.0;
let annotation_top = bounds.bottom().value - 5.0;
let annotation_bottom = annotation_top - SQUIGGLY_HEIGHT;

annotation
.attachment_points_mut()
.create_attachment_point_at_end(PdfQuadPoints::new_from_values(
bounds.left.value,
bounds.left().value,
annotation_bottom,
bounds.right.value,
bounds.right().value,
annotation_bottom,
bounds.right.value,
bounds.right().value,
annotation_top,
bounds.left.value,
bounds.left().value,
annotation_top,
))?;

Expand Down Expand Up @@ -467,11 +467,11 @@ impl<'a> PdfPageAnnotations<'a> {

let bounds = object.bounds()?;

annotation.set_position(bounds.left, bounds.bottom)?;
annotation.set_position(bounds.left(), bounds.bottom())?;
annotation.set_stroke_color(color)?;
annotation
.attachment_points_mut()
.create_attachment_point_at_end(PdfQuadPoints::from_rect(bounds))?;
.create_attachment_point_at_end(bounds)?;

if let Some(contents) = contents {
annotation.set_width(bounds.width())?;
Expand Down Expand Up @@ -505,11 +505,11 @@ impl<'a> PdfPageAnnotations<'a> {

let bounds = object.bounds()?;

annotation.set_position(bounds.left, bounds.bottom)?;
annotation.set_position(bounds.left(), bounds.bottom())?;
annotation.set_stroke_color(color)?;
annotation
.attachment_points_mut()
.create_attachment_point_at_end(PdfQuadPoints::from_rect(bounds))?;
.create_attachment_point_at_end(bounds)?;

if let Some(contents) = contents {
annotation.set_width(bounds.width())?;
Expand Down Expand Up @@ -543,11 +543,11 @@ impl<'a> PdfPageAnnotations<'a> {

let bounds = object.bounds()?;

annotation.set_position(bounds.left, bounds.bottom)?;
annotation.set_position(bounds.left(), bounds.bottom())?;
annotation.set_stroke_color(color)?;
annotation
.attachment_points_mut()
.create_attachment_point_at_end(PdfQuadPoints::from_rect(bounds))?;
.create_attachment_point_at_end(bounds)?;

if let Some(contents) = contents {
annotation.set_width(bounds.width())?;
Expand Down
21 changes: 16 additions & 5 deletions src/pdf/document/page/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::pdf::document::page::objects::PdfPageObjects;
use crate::pdf::document::PdfDocument;
use crate::pdf::matrix::{PdfMatrix, PdfMatrixValue};
use crate::pdf::points::PdfPoints;
use crate::pdf::quad_points::PdfQuadPoints;
use crate::pdf::rect::PdfRect;
use crate::{create_transform_getters, create_transform_setters};
use std::convert::TryInto;
Expand Down Expand Up @@ -547,13 +548,13 @@ pub trait PdfPageObjectCommon<'a> {
/// Returns `true` if this [PdfPageObject] contains transparency.
fn has_transparency(&self) -> bool;

/// Returns the bounding box of this [PdfPageObject].
/// Returns the bounding box of this [PdfPageObject] as a quadrilateral.
///
/// For text objects, the bottom of the bounding box is set to the font baseline. Any characters
/// in the text object that have glyph shapes that descends below the font baseline will extend
/// beneath the bottom of this bounding box. To measure the distance of the maximum descent of
/// any glyphs, use the [PdfPageTextObject::descent()] function.
fn bounds(&self) -> Result<PdfRect, PdfiumError>;
fn bounds(&self) -> Result<PdfQuadPoints, PdfiumError>;

/// Returns the width of this [PdfPageObject].
#[inline]
Expand All @@ -571,7 +572,7 @@ pub trait PdfPageObjectCommon<'a> {
#[inline]
fn is_inside_rect(&self, rect: &PdfRect) -> bool {
self.bounds()
.map(|bounds| bounds.is_inside(rect))
.map(|bounds| bounds.to_rect().is_inside(rect))
.unwrap_or(false)
}

Expand All @@ -580,7 +581,7 @@ pub trait PdfPageObjectCommon<'a> {
#[inline]
fn does_overlap_rect(&self, rect: &PdfRect) -> bool {
self.bounds()
.map(|bounds| bounds.does_overlap(rect))
.map(|bounds| bounds.to_rect().does_overlap(rect))
.unwrap_or(false)
}

Expand Down Expand Up @@ -765,7 +766,7 @@ where
}

#[inline]
fn bounds(&self) -> Result<PdfRect, PdfiumError> {
fn bounds(&self) -> Result<PdfQuadPoints, PdfiumError> {
self.bounds_impl()
}

Expand Down Expand Up @@ -1045,6 +1046,16 @@ impl<'a> PdfPageObjectPrivate<'a> for PdfPageObject<'a> {
self.unwrap_as_trait().get_object_handle()
}

#[inline]
fn get_document_handle(&self) -> Option<FPDF_DOCUMENT> {
self.unwrap_as_trait().get_document_handle()
}

#[inline]
fn set_document_handle(&mut self, document: FPDF_DOCUMENT) {
self.unwrap_as_trait_mut().set_document_handle(document);
}

#[inline]
fn get_page_handle(&self) -> Option<FPDF_PAGE> {
self.unwrap_as_trait().get_page_handle()
Expand Down
20 changes: 10 additions & 10 deletions src/pdf/document/page/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

use crate::bindgen::FPDF_PAGEOBJECT;
use crate::error::PdfiumError;
use crate::pdf::document::PdfDocument;
use crate::pdf::document::fonts::PdfFontToken;
use crate::pdf::document::page::PdfPage;
use crate::pdf::document::page::object::{PdfPageObject, PdfPageObjectCommon};
use crate::pdf::document::page::object::group::PdfPageGroupObject;
use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
use crate::pdf::document::page::object::text::PdfPageTextObject;
use crate::pdf::document::page::object::{PdfPageObject, PdfPageObjectCommon};
use crate::pdf::document::page::objects::common::PdfPageObjectsCommon;
use crate::pdf::document::page::PdfPage;
use crate::pdf::document::PdfDocument;
use crate::pdf::font::PdfFont;
use crate::pdf::points::PdfPoints;
use itertools::Itertools;
Expand Down Expand Up @@ -291,7 +291,7 @@ impl<'a> PdfParagraph<'a> {
.map(|object| {
let object_bottom = object
.bounds()
.map(|bounds| bounds.bottom)
.map(|bounds| bounds.bottom())
.unwrap_or(PdfPoints::ZERO);

match objects_bottom {
Expand All @@ -305,7 +305,7 @@ impl<'a> PdfParagraph<'a> {

let object_top = object
.bounds()
.map(|bounds| bounds.top)
.map(|bounds| bounds.top())
.unwrap_or(PdfPoints::ZERO);

match objects_top {
Expand All @@ -324,7 +324,7 @@ impl<'a> PdfParagraph<'a> {

let object_left = object
.bounds()
.map(|bounds| bounds.left)
.map(|bounds| bounds.left())
.unwrap_or(PdfPoints::ZERO);

match objects_left {
Expand All @@ -338,7 +338,7 @@ impl<'a> PdfParagraph<'a> {

let object_right = object
.bounds()
.map(|bounds| bounds.right)
.map(|bounds| bounds.right())
.unwrap_or(PdfPoints::ZERO);

match objects_right {
Expand Down Expand Up @@ -472,7 +472,7 @@ impl<'a> PdfParagraph<'a> {

let separator = if let Ok(bounds) = object.bounds() {
if let Some(last_object_right) = last_object_right {
if last_object_right > bounds.left {
if last_object_right > bounds.left() {
// The last and current objects are touching.
// Assume they're part of the same word, despite being
// in separate objects.
Expand Down Expand Up @@ -507,7 +507,7 @@ impl<'a> PdfParagraph<'a> {
println!(
"last_object_right = {:?}, this object left = {:?}",
last_object_right,
object.bounds().unwrap().left,
object.bounds().unwrap().left(),
);
} else {
// The styles of the two text objects are different, so they can't be merged.
Expand Down Expand Up @@ -887,4 +887,4 @@ mod tests {

Ok(())
}
}
}
6 changes: 3 additions & 3 deletions src/pdf/document/page/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,11 @@ impl<'a> PdfPageText<'a> {
let text_page = new_page.text()?;
let tolerance_x = bounds.width() / 2.0;
let tolerance_y = bounds.height() / 2.0;
let center_height = bounds.bottom + tolerance_y;
let center_height = bounds.bottom() + tolerance_y;

let start_index = Self::get_char_index_near_point(
*text_page.handle(),
bounds.left,
bounds.left(),
tolerance_x,
center_height,
tolerance_y,
Expand All @@ -193,7 +193,7 @@ impl<'a> PdfPageText<'a> {

let end_index = Self::get_char_index_near_point(
*text_page.handle(),
bounds.right,
bounds.right(),
tolerance_x,
center_height,
tolerance_y,
Expand Down
6 changes: 6 additions & 0 deletions src/pdf/points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ impl PdfPoints {
pub fn to_mm(&self) -> f32 {
self.to_cm() * 10.0
}

/// Creates a new [PdfPoints] object with the absolute value of this [PdfPoints] object.
#[inline]
pub fn abs(&self) -> PdfPoints {
PdfPoints::new(self.value.abs())
}
}

impl Add<PdfPoints> for PdfPoints {
Expand Down
Loading

0 comments on commit b35e3c6

Please sign in to comment.