diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 12467ba..93826aa 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -47,7 +47,7 @@ jobs: if: matrix.os == 'windows-2019' uses: microsoft/setup-msbuild@v1.3.1 - run: cargo test --features serde - timeout-minutes: 20 + timeout-minutes: 30 if: matrix.os == 'windows-2019' env: LIBCLANG_PATH: "C:\\Program Files\\LLVM\\bin" @@ -95,7 +95,7 @@ jobs: - uses: dtolnay/rust-toolchain@nightly with: components: rust-src - - run: sudo apt-get -y install libfontconfig1-dev llvm + - run: sudo apt-get -y install libfontconfig1-dev llvm libc++abi-dev clang - name: cargo test --features serde run: | cargo test -Zbuild-std --target x86_64-unknown-linux-gnu --features serde diff --git a/mupdf-sys/build.rs b/mupdf-sys/build.rs index 0b6af26..558cb75 100644 --- a/mupdf-sys/build.rs +++ b/mupdf-sys/build.rs @@ -43,14 +43,18 @@ fn cp_r(dir: &Path, dest: &Path, excluding_dir_names: &'static [&'static str]) { } } -const CPU_FLAGS: &[(&str, &str, &str, Option<&str>)] = &[ +#[allow(dead_code)] +const DEFAULT_CPU_FLAGS: &[(&str, &str, &str, Option<&str>)] = &[ ("sse4.1", "-msse4.1", "HAVE_SSE4_1", Some("ARCH_HAS_SSE")), ("avx", "-mavx", "HAVE_AVX", None), ("avx2", "-mavx2", "HAVE_AVX2", None), ("fma", "-mfma", "HAVE_FMA", None), - ("neon", "-mfpu=neon", "HAVE_NEON", Some("ARCH_HAS_NEON")), ]; +#[allow(dead_code)] +const ARM_CPU_FLAGS: &[(&str, &str, &str, Option<&str>)] = + &[("neon", "-mfpu=neon", "HAVE_NEON", Some("ARCH_HAS_NEON"))]; + #[cfg(not(target_env = "msvc"))] fn build_libmupdf() { use std::process::Command; @@ -99,8 +103,8 @@ fn build_libmupdf() { "libs".to_owned(), format!("build={}", profile), format!("OUT={}", &build_dir_str), - #[cfg(not(feature = "tesseract"))] - "USE_TESSERACT=no".to_owned(), + #[cfg(feature = "tesseract")] + "USE_TESSERACT=yes".to_owned(), #[cfg(not(feature = "libarchive"))] "USE_LIBARCHIVE=no".to_owned(), #[cfg(not(feature = "zxingcpp"))] @@ -110,11 +114,22 @@ fn build_libmupdf() { "HAVE_X11=no".to_owned(), "HAVE_GLUT=no".to_owned(), "HAVE_CURL=no".to_owned(), + // The parameter doesn't seem to have been implemented properly. + // - There's an error message about libmupdf.a.in not being found. + // - This will cause tests to fail under MYS2. + // "USE_ARGUMENT_FILE=yes".to_owned(), "verbose=yes".to_owned(), ]; - for (feature, flag, make_flag, define) in CPU_FLAGS { - let contains = target_features.contains(feature); + let mut cpu_flags = DEFAULT_CPU_FLAGS.to_vec(); + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); + + if target_arch == "arm" { + cpu_flags.extend(ARM_CPU_FLAGS); + } + + for (feature, flag, make_flag, define) in cpu_flags { + let contains = target_features.contains(&feature); if contains { build.flag_if_supported(flag); @@ -513,6 +528,20 @@ fn main() { println!("cargo:rerun-if-changed=wrapper.h"); println!("cargo:rerun-if-changed=wrapper.c"); + if let Ok(ref target_os) = env::var("CARGO_CFG_TARGET_OS") { + if target_os == "windows" { + #[cfg(target_env = "msvc")] + println!("cargo:rustc-link-lib=msvcrt"); + + #[cfg(not(target_env = "msvc"))] + println!("cargo:rustc-link-lib=stdc++"); + } else if target_os == "macos" { + println!("cargo:rustc-link-lib=c++"); + } else { + println!("cargo:rustc-link-lib=stdc++"); + } + } + build_libmupdf(); let mut build = cc::Build::new(); diff --git a/mupdf-sys/wrapper.c b/mupdf-sys/wrapper.c index 428b484..e7f9c70 100644 --- a/mupdf-sys/wrapper.c +++ b/mupdf-sys/wrapper.c @@ -3227,6 +3227,20 @@ fz_document_writer *mupdf_new_document_writer(fz_context *ctx, const char *filen return writer; } +fz_document_writer *mupdf_new_pdfocr_writer(fz_context *ctx, const char *path, const char *options, mupdf_error_t **errptr) +{ + fz_document_writer *writer = NULL; + fz_try(ctx) + { + writer = fz_new_pdfocr_writer(ctx, path, options); + } + fz_catch(ctx) + { + mupdf_save_error(ctx, errptr); + } + return writer; +} + fz_device *mupdf_document_writer_begin_page(fz_context *ctx, fz_document_writer *writer, fz_rect mediabox, mupdf_error_t **errptr) { fz_device *device = NULL; diff --git a/src/document_writer.rs b/src/document_writer.rs index 6869af3..5594416 100644 --- a/src/document_writer.rs +++ b/src/document_writer.rs @@ -3,7 +3,7 @@ use std::ptr; use mupdf_sys::*; -use crate::{context, Device, Error, Rect}; +use crate::{context, Device, Error, FilePath, Rect}; #[derive(Debug)] pub struct DocumentWriter { @@ -11,8 +11,12 @@ pub struct DocumentWriter { } impl DocumentWriter { - pub fn new(filename: &str, format: &str, options: &str) -> Result { - let c_filename = CString::new(filename)?; + pub fn new + ?Sized>( + filename: &P, + format: &str, + options: &str, + ) -> Result { + let c_filename = CString::new(filename.as_ref().as_bytes())?; let c_format = CString::new(format)?; let c_options = CString::new(options)?; unsafe { @@ -26,6 +30,21 @@ impl DocumentWriter { .map(|inner| Self { inner }) } + #[cfg(feature = "tesseract")] + pub fn with_ocr + ?Sized>(path: &P, options: &str) -> Result { + let c_path = CString::new(path.as_ref().as_bytes())?; + let c_options = CString::new(options)?; + + unsafe { + ffi_try!(mupdf_new_pdfocr_writer( + context(), + c_path.as_ptr(), + c_options.as_ptr() + )) + } + .map(|inner| Self { inner }) + } + pub fn begin_page(&mut self, media_box: Rect) -> Result { unsafe { ffi_try!(mupdf_document_writer_begin_page(