wip
This commit is contained in:
parent
103f986bc0
commit
a677cd8a33
2 changed files with 169 additions and 85 deletions
166
src/mupdf_ffi.rs
166
src/mupdf_ffi.rs
|
|
@ -4,14 +4,15 @@
|
|||
use mupdf_sys::{
|
||||
fz_clone_context, fz_color_params, fz_colorspace, fz_context, fz_device, fz_document,
|
||||
fz_drop_context, fz_drop_device, fz_drop_document, fz_drop_page, fz_drop_path, fz_drop_text,
|
||||
fz_error_type_FZ_ERROR_GENERIC, fz_matrix, fz_page, fz_path, fz_path_walker, fz_point, fz_rect,
|
||||
fz_stroke_state, fz_text, fz_transform_point, fz_transform_point_xy, fz_walk_path,
|
||||
mupdf_document_page_count, mupdf_drop_error, mupdf_error_t, mupdf_load_page,
|
||||
mupdf_new_base_context, mupdf_new_derived_device, mupdf_open_document, mupdf_run_page,
|
||||
fz_error_type_FZ_ERROR_GENERIC, fz_font, fz_matrix, fz_page, fz_path, fz_path_walker, fz_point,
|
||||
fz_rect, fz_stroke_state, fz_text, fz_text_item, fz_text_span, fz_transform_point,
|
||||
fz_transform_point_xy, fz_walk_path, mupdf_document_page_count, mupdf_drop_error,
|
||||
mupdf_error_t, mupdf_load_page, mupdf_new_base_context, mupdf_new_derived_device,
|
||||
mupdf_open_document, mupdf_run_page,
|
||||
};
|
||||
use std::{
|
||||
cell::Cell,
|
||||
ffi::{CStr, CString, c_int, c_void},
|
||||
ffi::{CStr, c_int, c_void},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
mem::ManuallyDrop,
|
||||
|
|
@ -20,16 +21,16 @@ use std::{
|
|||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MuPdfError {
|
||||
pub(crate) struct MuPdfError {
|
||||
type_: c_int,
|
||||
message: CString,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl MuPdfError {
|
||||
fn new_generic(message: impl ToString) -> Self {
|
||||
Self {
|
||||
type_: fz_error_type_FZ_ERROR_GENERIC as _,
|
||||
message: message.try_into().expect("nul byte in message"),
|
||||
message: message.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,15 +58,17 @@ impl Drop for OwnedMuPdfError {
|
|||
}
|
||||
|
||||
unsafe fn mupdf_try<R>(f: impl FnOnce(&mut *mut mupdf_error_t) -> R) -> Result<R, MuPdfError> {
|
||||
let mut err = <*mut mupdf_error_t>::null_mut();
|
||||
let mut err = ptr::null_mut();
|
||||
let retval = f(&mut err);
|
||||
let Some(err) = NonNull::new(err).map(OwnedMuPdfError) else {
|
||||
return Ok(retval);
|
||||
};
|
||||
unsafe {
|
||||
Err(MuPdfError {
|
||||
type_: (*err.0).type_,
|
||||
message: CString::from(CStr::from_ptr((*err.0).message)),
|
||||
type_: (*err.0.as_ptr()).type_,
|
||||
message: CStr::from_ptr((*err.0.as_ptr()).message)
|
||||
.to_string_lossy()
|
||||
.into_owned(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -254,10 +257,6 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
};
|
||||
(&raw mut (*dev_ptr).value).write(value);
|
||||
let fz_device {
|
||||
refs,
|
||||
hints,
|
||||
flags,
|
||||
close_device,
|
||||
drop_device,
|
||||
fill_path,
|
||||
stroke_path,
|
||||
|
|
@ -268,29 +267,7 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
clip_text,
|
||||
clip_stroke_text,
|
||||
ignore_text,
|
||||
fill_shade,
|
||||
fill_image,
|
||||
fill_image_mask,
|
||||
clip_image_mask,
|
||||
pop_clip,
|
||||
begin_mask,
|
||||
end_mask,
|
||||
begin_group,
|
||||
end_group,
|
||||
begin_tile,
|
||||
end_tile,
|
||||
render_flags,
|
||||
set_default_colorspaces,
|
||||
begin_layer,
|
||||
end_layer,
|
||||
begin_structure,
|
||||
end_structure,
|
||||
begin_metatext,
|
||||
end_metatext,
|
||||
d1_rect,
|
||||
container_len,
|
||||
container_cap,
|
||||
container,
|
||||
..
|
||||
} = &mut (*dev_ptr).base;
|
||||
*drop_device = Some(Self::drop_device_fn);
|
||||
*fill_path = Some(Self::fill_path_fn);
|
||||
|
|
@ -306,7 +283,7 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
}
|
||||
}
|
||||
pub(crate) fn get(&self) -> &T {
|
||||
unsafe { &(*self.ptr.cast::<DeviceStruct<T>>()).value }
|
||||
unsafe { &(*self.dev.cast::<DeviceStruct<T>>()).value }
|
||||
}
|
||||
unsafe extern "C" fn drop_device_fn(_ctx: *mut fz_context, dev: *mut fz_device) {
|
||||
unsafe {
|
||||
|
|
@ -319,10 +296,10 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
path: *const fz_path,
|
||||
even_odd: c_int,
|
||||
cmt: fz_matrix,
|
||||
color_space: *mut fz_colorspace,
|
||||
color: *const f32,
|
||||
alpha: f32,
|
||||
color_params: fz_color_params,
|
||||
_color_space: *mut fz_colorspace,
|
||||
_color: *const f32,
|
||||
_alpha: f32,
|
||||
_color_params: fz_color_params,
|
||||
) {
|
||||
let Some(ctx) = NonNull::new(ctx) else {
|
||||
return;
|
||||
|
|
@ -343,12 +320,12 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
ctx: *mut fz_context,
|
||||
dev: *mut fz_device,
|
||||
path: *const fz_path,
|
||||
stroke_state: *const fz_stroke_state,
|
||||
_stroke_state: *const fz_stroke_state,
|
||||
cmt: fz_matrix,
|
||||
color_space: *mut fz_colorspace,
|
||||
color: *const f32,
|
||||
alpha: f32,
|
||||
color_params: fz_color_params,
|
||||
_color_space: *mut fz_colorspace,
|
||||
_color: *const f32,
|
||||
_alpha: f32,
|
||||
_color_params: fz_color_params,
|
||||
) {
|
||||
let Some(ctx) = NonNull::new(ctx) else {
|
||||
return;
|
||||
|
|
@ -392,7 +369,7 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
ctx: *mut fz_context,
|
||||
dev: *mut fz_device,
|
||||
path: *const fz_path,
|
||||
stroke_state: *const fz_stroke_state,
|
||||
_stroke_state: *const fz_stroke_state,
|
||||
cmt: fz_matrix,
|
||||
scissor: fz_rect,
|
||||
) {
|
||||
|
|
@ -416,10 +393,10 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
dev: *mut fz_device,
|
||||
text: *const fz_text,
|
||||
cmt: fz_matrix,
|
||||
color_space: *mut fz_colorspace,
|
||||
color: *const f32,
|
||||
alpha: f32,
|
||||
color_params: fz_color_params,
|
||||
_color_space: *mut fz_colorspace,
|
||||
_color: *const f32,
|
||||
_alpha: f32,
|
||||
_color_params: fz_color_params,
|
||||
) {
|
||||
let Some(ctx) = NonNull::new(ctx) else {
|
||||
return;
|
||||
|
|
@ -439,12 +416,12 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
ctx: *mut fz_context,
|
||||
dev: *mut fz_device,
|
||||
text: *const fz_text,
|
||||
stroke_state: *const fz_stroke_state,
|
||||
_stroke_state: *const fz_stroke_state,
|
||||
cmt: fz_matrix,
|
||||
color_space: *mut fz_colorspace,
|
||||
color: *const f32,
|
||||
alpha: f32,
|
||||
color_params: fz_color_params,
|
||||
_color_space: *mut fz_colorspace,
|
||||
_color: *const f32,
|
||||
_alpha: f32,
|
||||
_color_params: fz_color_params,
|
||||
) {
|
||||
let Some(ctx) = NonNull::new(ctx) else {
|
||||
return;
|
||||
|
|
@ -486,7 +463,7 @@ impl<'ctx, T: DeviceCallbacks<'ctx>> Device<'ctx, T> {
|
|||
ctx: *mut fz_context,
|
||||
dev: *mut fz_device,
|
||||
text: *const fz_text,
|
||||
stroke_state: *const fz_stroke_state,
|
||||
_stroke_state: *const fz_stroke_state,
|
||||
cmt: fz_matrix,
|
||||
scissor: fz_rect,
|
||||
) {
|
||||
|
|
@ -716,6 +693,77 @@ impl<'ctx> Drop for Text<'ctx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx> Text<'ctx> {
|
||||
pub(crate) fn spans<'a>(&'a self) -> TextSpanIter<'a, 'ctx> {
|
||||
TextSpanIter {
|
||||
ptr: unsafe { NonNull::new((*self.ptr).head) },
|
||||
ctx: self.ctx,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TextSpanIter<'a, 'ctx> {
|
||||
ptr: Option<NonNull<fz_text_span>>,
|
||||
ctx: ContextRef<'ctx>,
|
||||
_phantom: PhantomData<&'a Text<'ctx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> Iterator for TextSpanIter<'a, 'ctx> {
|
||||
type Item = TextSpanRef<'a, 'ctx>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let ptr = self.ptr?;
|
||||
self.ptr = NonNull::new(unsafe { ptr.as_ref().next });
|
||||
Some(TextSpanRef {
|
||||
ptr: unsafe { &*ptr.as_ptr() },
|
||||
ctx: self.ctx,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct TextSpanRef<'a, 'ctx> {
|
||||
ptr: &'a fz_text_span,
|
||||
ctx: ContextRef<'ctx>,
|
||||
_phantom: PhantomData<&'a Text<'ctx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> TextSpanRef<'a, 'ctx> {
|
||||
pub(crate) fn get(self) -> &'a fz_text_span {
|
||||
self.ptr
|
||||
}
|
||||
pub(crate) fn font(self) -> FontRef<'a, 'ctx> {
|
||||
FontRef {
|
||||
ptr: unsafe { &*self.ptr.font },
|
||||
ctx: self.ctx,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub(crate) fn items(self) -> &'a [fz_text_item] {
|
||||
let len = self.ptr.len as usize;
|
||||
if len == 0 {
|
||||
return &[];
|
||||
}
|
||||
unsafe { std::slice::from_raw_parts(self.ptr.items, len) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct FontRef<'a, 'ctx> {
|
||||
ptr: &'a fz_font,
|
||||
ctx: ContextRef<'ctx>,
|
||||
_phantom: PhantomData<&'a Text<'ctx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> FontRef<'a, 'ctx> {
|
||||
pub(crate) fn get(self) -> &'a fz_font {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn transform_point(point: fz_point, m: fz_matrix) -> fz_point {
|
||||
unsafe { fz_transform_point(point, m) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue