Skip to content

Commit

Permalink
Patch pdfium wasm for esm compatibility, and add loader example and w…
Browse files Browse the repository at this point in the history
…orkaround to App.vue
  • Loading branch information
samsieber committed Feb 5, 2024
1 parent e718638 commit ff5ed61
Show file tree
Hide file tree
Showing 12 changed files with 1,115 additions and 38 deletions.
879 changes: 879 additions & 0 deletions my-crate/Cargo.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion my-crate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ edition = "2021"
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "^0"
pdfium-render = { version = "0.8.17", features = ["thread_safe"]}
image = "^0"
js-sys = "^0"
log = "^0"
wasm-bindgen = "^0"
wasm-bindgen-futures = "^0"
web-sys = { version = "^0", features = ["ImageData"] }
147 changes: 146 additions & 1 deletion my-crate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,149 @@ extern {
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
}

use pdfium_render::prelude::*;

use wasm_bindgen::prelude::*;


use web_sys::ImageData;

// See https://github.com/ajrcarey/pdfium-render/tree/master/examples for information
// on how to build and package this example alongside a WASM build of Pdfium, suitable
// for running in a browser.

/// Downloads the given url, opens it as a PDF document, then Logs the width and height of
/// each page in the document, along with other document metrics, to the Javascript console.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub async fn log_page_metrics_to_console(url: String) {
let pdfium = Pdfium::default();

let document = pdfium.load_pdf_from_fetch(url, None).await.unwrap();

// Output metadata and form information for the PDF file to the console.

log::info!("PDF file version: {:#?}", document.version());

log::info!("PDF metadata tags:");

document
.metadata()
.iter()
.enumerate()
.for_each(|(index, tag)| log::info!("{}: {:#?} = {}", index, tag.tag_type(), tag.value()));

let pages = document.pages();

match document.form() {
Some(form) => {
log::info!(
"PDF contains an embedded form of type {:#?}",
form.form_type()
);

for (key, value) in form.field_values(&pages).iter() {
log::info!("{:?} => {:?}", key, value);
}
}
None => log::info!("PDF does not contain an embedded form"),
};

// Report labels, boundaries, and metrics for each page to the console.

pages.iter().enumerate().for_each(|(page_index, page)| {
if let Some(label) = page.label() {
log::info!("Page {} has a label: {}", page_index, label);
}

log::info!(
"Page {} width: {}, height: {}",
page_index,
page.width().value,
page.height().value
);

for boundary in page.boundaries().iter() {
log::info!(
"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,
);
}

log::info!(
"Page {} has paper size {:#?}",
page_index,
page.paper_size()
);

for (link_index, link) in page.links().iter().enumerate() {
log::info!(
"Page {} link {} has action of type {:?}",
page_index,
link_index,
link.action().map(|action| action.action_type())
);

// For links that have URI actions, output the destination URI.

if let Some(action) = link.action() {
if let Some(uri_action) = action.as_uri_action() {
log::info!("Link URI destination: {:#?}", uri_action.uri())
}
}
}

let text = page.text().unwrap();

for (annotation_index, annotation) in page.annotations().iter().enumerate() {
log::info!(
"Page {} annotation {} has text: {:?}, bounds: {:?}",
page_index,
annotation_index,
text.for_annotation(&annotation),
annotation.bounds()
);
}
});
}

/// Downloads the given url, opens it as a PDF document, then returns the ImageData for
/// the given page index using the given bitmap dimensions.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub async fn get_image_data_for_page(
url: String,
index: PdfPageIndex,
width: Pixels,
height: Pixels,
) -> ImageData {
Pdfium::default()
.load_pdf_from_fetch(url, None)
.await
.unwrap()
.pages()
.get(index)
.unwrap()
.render_with_config(
&PdfRenderConfig::new()
.set_target_size(width, height)
.render_form_data(true)
.highlight_text_form_fields(PdfColor::YELLOW.with_alpha(128))
.highlight_checkbox_form_fields(PdfColor::BLUE.with_alpha(128)),
)
.unwrap()
.as_image_data()
.unwrap()
}

// Source files in examples/ directory are expected to always have a main() entry-point.
// Since we're compiling to WASM, we'll never actually use this.
#[allow(dead_code)]
fn main() {}
13 changes: 13 additions & 0 deletions pdfium/pkg/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "pdfium",
"collaborators": [
"Sam Sieber"
],
"version": "0.1.0",
"files": [
"pdfium.wasm",
"pdfium.js"
],
"types": "pdfium.d.ts",
"module": "pdfium.js"
}
3 changes: 3 additions & 0 deletions pdfium/pkg/pdfium.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module 'pdfium' {
export default function PDFiumModule(module_or_path?: any): Promise<any>;
}
10 changes: 3 additions & 7 deletions pdfium/pkg/pdfium.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var PDFiumModule = (() => {
export default (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
Expand Down Expand Up @@ -415,7 +415,7 @@ var PDFiumModule = (() => {
}
}
var wasmBinaryFile;
wasmBinaryFile = "pdfium.wasm";
wasmBinaryFile = "pdfium_bg.wasm";
if (!isDataURI(wasmBinaryFile)) {
wasmBinaryFile = locateFile(wasmBinaryFile)
}
Expand All @@ -433,7 +433,7 @@ var PDFiumModule = (() => {
function getBinaryPromise(binaryFile) {
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
if (typeof fetch == "function" && !isFileURI(binaryFile)) {
return fetch(new URL(binaryFile, import.meta.url), {
return fetch(binaryFile, {
credentials: "same-origin"
}).then(response => {
if (!response["ok"]) {
Expand Down Expand Up @@ -4820,7 +4820,3 @@ var PDFiumModule = (() => {
}
);
})();;
if (typeof exports === 'object' && typeof module === 'object')
module.exports = PDFiumModule;
else if (typeof define === 'function' && define['amd'])
define([], () => PDFiumModule);
36 changes: 36 additions & 0 deletions pdfium/pkg/pdfium.js.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
diff --git a/ui/pdfium/pkg/pdfium.js b/ui/pdfium/pkg/original.js
index 94f7926..d06d540 100644
--- a/ui/pdfium/pkg/pdfium.js
+++ b/ui/pdfium/pkg/original.js
@@ -1,4 +1,4 @@
-export default (() => {
+var PDFiumModule = (() => {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
@@ -415,7 +415,7 @@ export default (() => {
}
}
var wasmBinaryFile;
- wasmBinaryFile = "pdfium_bg.wasm";
+ wasmBinaryFile = "pdfium.wasm";
if (!isDataURI(wasmBinaryFile)) {
wasmBinaryFile = locateFile(wasmBinaryFile)
}
@@ -462,7 +462,7 @@ export default (() => {

function instantiateAsync(binary, binaryFile, imports, callback) {
if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") {
- return fetch(new URL(binaryFile, import.meta.url), {
+ return fetch(binaryFile, {
credentials: "same-origin"
}).then(response => {
var result = WebAssembly.instantiateStreaming(response, imports);
@@ -4820,3 +4820,7 @@ export default (() => {
}
);
})();;
+if (typeof exports === 'object' && typeof module === 'object')
+ module.exports = PDFiumModule;
+else if (typeof define === 'function' && define['amd'])
+ define([], () => PDFiumModule);
Binary file renamed pdfium/pkg/pdfium.wasm → pdfium/pkg/pdfium_bg.wasm
Binary file not shown.
28 changes: 25 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
<script setup lang="ts">
import { ref } from 'vue'
import init, { greet } from 'my-crate';
import {initialize_pdfium_render} from "my-crate";
import PDFiumModule from "pdfium";
// This throws the following errors:
// Aborted(`Module.asm` has been replaced by `wasmExports` (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name))
// pdfium-render::initialize_pdfium_render(): Unable to locate wasmTable
async function initWasm(){
let wasm = await init();
let pdfiumModule = await PDFiumModule()
let wasmModule = wasm;
initialize_pdfium_render(pdfiumModule, wasmModule, false);
greet("Test Issue")
}
async function hackyInit(){
let wasm = await init();
let pdfiumModule = await PDFiumModule()
let wasmModule = wasm;
(window as any).wasmTable = pdfiumModule.wasmExports.__indirect_function_table
initialize_pdfium_render(pdfiumModule, wasmModule, false);
greet("Test Issue")
}
Expand All @@ -16,9 +27,20 @@ async function initWasm(){
<div>
<div>
<pre>
// This logs the following errors:
// Aborted(`Module.asm` has been replaced by `wasmExports` (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name))
// pdfium-render::initialize_pdfium_render(): Unable to locate wasmTable
{{ initWasm }}
</pre>
<button @click="initWasm">Run initWasm</button>
</div>
<hr>
<div>
<pre>
// Manually attaching to the window prevents the errors
{{ hackyInit }}
</pre>
<button @click="hackyInit">Run hackyInit</button>
</div>
</div>
</template>
Expand Down
25 changes: 0 additions & 25 deletions src/wasm-loader.ts

This file was deleted.

1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"strictNullChecks": false,
"paths": {
"my-crate": ["./my-crate/pkg"],
"pdfium": ["./pdfium/pkg"],
"~/*": ["./src/*"]
}
},
Expand Down
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default defineConfig({
},
plugins: [
vue(),
wasmPack(['./my-crate']),
wasmPack(['./my-crate']),
wasmPack(['./pdfium']) ,
]
});

0 comments on commit ff5ed61

Please sign in to comment.