wip
This commit is contained in:
parent
f9a24f4c48
commit
103f986bc0
2 changed files with 236 additions and 64 deletions
140
src/main.rs
140
src/main.rs
|
|
@ -2,12 +2,12 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::quad_tree::QuadTree;
|
use crate::quad_tree::QuadTree;
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::IndexSet;
|
||||||
use mupdf_sys::{FZ_STEXT_BOLD, fz_matrix};
|
use mupdf_sys::{FZ_STEXT_BOLD, fz_matrix};
|
||||||
use non_nan_float::NonNaNF32;
|
use non_nan_float::NonNaNF32;
|
||||||
use std::{
|
use std::{
|
||||||
backtrace::Backtrace,
|
backtrace::Backtrace,
|
||||||
borrow::{Borrow, Cow},
|
borrow::Cow,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
|
|
@ -681,7 +681,7 @@ impl ParsedTextLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn write_xml_lines(
|
fn write_xml_lines(
|
||||||
lines: impl IntoIterator<Item: Borrow<ParsedTextLine>>,
|
lines: impl IntoIterator<Item: std::borrow::Borrow<ParsedTextLine>>,
|
||||||
parent: &mut xml_tree::Element,
|
parent: &mut xml_tree::Element,
|
||||||
trailing_nl: bool,
|
trailing_nl: bool,
|
||||||
preceding_nl: bool,
|
preceding_nl: bool,
|
||||||
|
|
@ -691,7 +691,7 @@ impl ParsedTextLine {
|
||||||
}
|
}
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for line in lines {
|
for line in lines {
|
||||||
let line = line.borrow();
|
let line = std::borrow::Borrow::borrow(&line);
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1182,8 +1182,8 @@ impl<'a> ElementBodyBuilder<'a> {
|
||||||
}
|
}
|
||||||
self.shrink_stack(new_len);
|
self.shrink_stack(new_len);
|
||||||
}
|
}
|
||||||
fn write_text(&mut self, text: impl Borrow<str>) {
|
fn write_text(&mut self, text: impl std::borrow::Borrow<str>) {
|
||||||
let text = text.borrow();
|
let text = std::borrow::Borrow::borrow(&text);
|
||||||
let insert_point = self.insert_point();
|
let insert_point = self.insert_point();
|
||||||
if let Some(child) = insert_point.children.last_mut() {
|
if let Some(child) = insert_point.children.last_mut() {
|
||||||
child.tail += text;
|
child.tail += text;
|
||||||
|
|
@ -1328,14 +1328,14 @@ impl fmt::Display for InsnBitFields {
|
||||||
|
|
||||||
impl InsnBitFields {
|
impl InsnBitFields {
|
||||||
fn write_xml_fields(
|
fn write_xml_fields(
|
||||||
fields: impl IntoIterator<Item: Borrow<InsnBitField>>,
|
fields: impl IntoIterator<Item: std::borrow::Borrow<InsnBitField>>,
|
||||||
parent: &mut xml_tree::Element,
|
parent: &mut xml_tree::Element,
|
||||||
) {
|
) {
|
||||||
let fields_elm = parent.sub_element("fields".into(), []);
|
let fields_elm = parent.sub_element("fields".into(), []);
|
||||||
fields_elm.text = "\n".into();
|
fields_elm.text = "\n".into();
|
||||||
fields_elm.tail = "\n".into();
|
fields_elm.tail = "\n".into();
|
||||||
for field in fields {
|
for field in fields {
|
||||||
field.borrow().write_xml(fields_elm);
|
std::borrow::Borrow::borrow(&field).write_xml(fields_elm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn write_xml(&self, parent: &mut xml_tree::Element) {
|
fn write_xml(&self, parent: &mut xml_tree::Element) {
|
||||||
|
|
@ -3170,7 +3170,9 @@ impl<'ctx> Parser<'ctx> {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct MyDevice {
|
struct MyDevice {
|
||||||
page_num: u32,
|
page_num: u32,
|
||||||
qt: BTreeMap<TextSection, QuadTree<PageItem>>,
|
qt: Rc<RefCell<BTreeMap<TextSection, QuadTree<PageItem>>>>,
|
||||||
|
unprocessed_chars:
|
||||||
|
Rc<RefCell<BTreeMap<TextSection, Rc<RefCell<BTreeMap<Font, IndexSet<Char>>>>>>>,
|
||||||
unprocessed_non_text: Rc<RefCell<IndexSet<LineOrRect>>>,
|
unprocessed_non_text: Rc<RefCell<IndexSet<LineOrRect>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3179,10 +3181,11 @@ impl MyDevice {
|
||||||
Self {
|
Self {
|
||||||
page_num,
|
page_num,
|
||||||
qt: Default::default(),
|
qt: Default::default(),
|
||||||
|
unprocessed_chars: Default::default(),
|
||||||
unprocessed_non_text: Default::default(),
|
unprocessed_non_text: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn path(&mut self, path: &mupdf_ffi::Path<'_>, cmt: fz_matrix) {
|
fn path(&self, path: &mupdf_ffi::Path<'_>, cmt: fz_matrix) {
|
||||||
enum Walker {
|
enum Walker {
|
||||||
Empty,
|
Empty,
|
||||||
Moved { x: f32, y: f32 },
|
Moved { x: f32, y: f32 },
|
||||||
|
|
@ -3198,8 +3201,8 @@ impl MyDevice {
|
||||||
p1_y: NonNaNF32::new(p1_y)?,
|
p1_y: NonNaNF32::new(p1_y)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
impl mupdf::PathWalker for Walker {
|
impl<'ctx> mupdf_ffi::PathWalker<'ctx> for Walker {
|
||||||
fn move_to(&mut self, x: f32, y: f32) {
|
fn move_to(&mut self, _ctx: mupdf_ffi::ContextRef<'ctx>, x: f32, y: f32) {
|
||||||
*self = match *self {
|
*self = match *self {
|
||||||
Walker::Empty | Walker::Moved { .. } => Walker::Moved { x, y },
|
Walker::Empty | Walker::Moved { .. } => Walker::Moved { x, y },
|
||||||
Walker::Line(_) | Walker::Rect { .. } | Walker::NotRecognized => {
|
Walker::Line(_) | Walker::Rect { .. } | Walker::NotRecognized => {
|
||||||
|
|
@ -3207,7 +3210,7 @@ impl MyDevice {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn line_to(&mut self, x: f32, y: f32) {
|
fn line_to(&mut self, _ctx: mupdf_ffi::ContextRef<'ctx>, x: f32, y: f32) {
|
||||||
*self = match *self {
|
*self = match *self {
|
||||||
Walker::Empty => Walker::NotRecognized,
|
Walker::Empty => Walker::NotRecognized,
|
||||||
Walker::Moved { x: p0_x, y: p0_y } => new_line(p0_x, p0_y, x, y)
|
Walker::Moved { x: p0_x, y: p0_y } => new_line(p0_x, p0_y, x, y)
|
||||||
|
|
@ -3218,11 +3221,27 @@ impl MyDevice {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn curve_to(&mut self, _cx1: f32, _cy1: f32, _cx2: f32, _cy2: f32, _ex: f32, _ey: f32) {
|
fn curve_to(
|
||||||
|
&mut self,
|
||||||
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
|
_cx1: f32,
|
||||||
|
_cy1: f32,
|
||||||
|
_cx2: f32,
|
||||||
|
_cy2: f32,
|
||||||
|
_ex: f32,
|
||||||
|
_ey: f32,
|
||||||
|
) {
|
||||||
*self = Walker::NotRecognized;
|
*self = Walker::NotRecognized;
|
||||||
}
|
}
|
||||||
fn close(&mut self) {}
|
fn close_path(&mut self, _ctx: mupdf_ffi::ContextRef<'ctx>) {}
|
||||||
fn rect(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
|
fn rect_to(
|
||||||
|
&mut self,
|
||||||
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
|
x1: f32,
|
||||||
|
y1: f32,
|
||||||
|
x2: f32,
|
||||||
|
y2: f32,
|
||||||
|
) {
|
||||||
*self = match *self {
|
*self = match *self {
|
||||||
Walker::Empty => Walker::Rect { x1, y1, x2, y2 },
|
Walker::Empty => Walker::Rect { x1, y1, x2, y2 },
|
||||||
Walker::Moved { .. }
|
Walker::Moved { .. }
|
||||||
|
|
@ -3233,9 +3252,7 @@ impl MyDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut walker = Walker::Empty;
|
let mut walker = Walker::Empty;
|
||||||
let Ok(()) = path.walk(&mut walker) else {
|
path.walk(&mut walker);
|
||||||
return;
|
|
||||||
};
|
|
||||||
let component = match walker {
|
let component = match walker {
|
||||||
Walker::Empty | Walker::Moved { .. } | Walker::NotRecognized => return,
|
Walker::Empty | Walker::Moved { .. } | Walker::NotRecognized => return,
|
||||||
Walker::Line(Line {
|
Walker::Line(Line {
|
||||||
|
|
@ -3244,26 +3261,20 @@ impl MyDevice {
|
||||||
p1_x,
|
p1_x,
|
||||||
p1_y,
|
p1_y,
|
||||||
}) => {
|
}) => {
|
||||||
let mupdf::Point { x: p0_x, y: p0_y } = mupdf::Point {
|
let mupdf_sys::fz_point { x: p0_x, y: p0_y } =
|
||||||
x: p0_x.get(),
|
mupdf_ffi::transform_point_xy(p0_x.get(), p0_y.get(), cmt);
|
||||||
y: p0_y.get(),
|
let mupdf_sys::fz_point { x: p1_x, y: p1_y } =
|
||||||
}
|
mupdf_ffi::transform_point_xy(p1_x.get(), p1_y.get(), cmt);
|
||||||
.transform(&cmt);
|
|
||||||
let mupdf::Point { x: p1_x, y: p1_y } = mupdf::Point {
|
|
||||||
x: p1_x.get(),
|
|
||||||
y: p1_y.get(),
|
|
||||||
}
|
|
||||||
.transform(&cmt);
|
|
||||||
let Some(line) = new_line(p0_x, p0_y, p1_x, p1_y) else {
|
let Some(line) = new_line(p0_x, p0_y, p1_x, p1_y) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
LineOrRect::Line(line)
|
LineOrRect::Line(line)
|
||||||
}
|
}
|
||||||
Walker::Rect { x1, y1, x2, y2 } => {
|
Walker::Rect { x1, y1, x2, y2 } => {
|
||||||
let p1 = mupdf::Point { x: x1, y: y1 }.transform(&cmt);
|
let p1 = mupdf_ffi::transform_point_xy(x1, y1, cmt);
|
||||||
let p2 = mupdf::Point { x: x2, y: y1 }.transform(&cmt);
|
let p2 = mupdf_ffi::transform_point_xy(x2, y1, cmt);
|
||||||
let p3 = mupdf::Point { x: x2, y: y2 }.transform(&cmt);
|
let p3 = mupdf_ffi::transform_point_xy(x2, y2, cmt);
|
||||||
let p4 = mupdf::Point { x: x1, y: y2 }.transform(&cmt);
|
let p4 = mupdf_ffi::transform_point_xy(x1, y2, cmt);
|
||||||
let min_x = NonNaNF32::new(p1.x.min(p2.x).min(p3.x).min(p4.x));
|
let min_x = NonNaNF32::new(p1.x.min(p2.x).min(p3.x).min(p4.x));
|
||||||
let max_x = NonNaNF32::new(p1.x.max(p2.x).max(p3.x).max(p4.x));
|
let max_x = NonNaNF32::new(p1.x.max(p2.x).max(p3.x).max(p4.x));
|
||||||
let min_y = NonNaNF32::new(p1.y.min(p2.y).min(p3.y).min(p4.y));
|
let min_y = NonNaNF32::new(p1.y.min(p2.y).min(p3.y).min(p4.y));
|
||||||
|
|
@ -3306,25 +3317,25 @@ impl MyDevice {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn text(&mut self, text: &mupdf_ffi::Text<'_>, cmt: fz_matrix) {
|
fn text(&self, text: &mupdf_ffi::Text<'_>, cmt: fz_matrix) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> mupdf_ffi::DeviceCallbacks<'ctx> for MyDevice {
|
impl<'ctx> mupdf_ffi::DeviceCallbacks<'ctx> for MyDevice {
|
||||||
fn fill_path(
|
fn fill_path(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
path: &mupdf_ffi::Path<'ctx>,
|
path: &mupdf_ffi::Path<'ctx>,
|
||||||
even_odd: bool,
|
_even_odd: bool,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
) {
|
) {
|
||||||
self.path(path, cmt);
|
self.path(path, cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stroke_path(
|
fn stroke_path(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
path: &mupdf_ffi::Path<'ctx>,
|
path: &mupdf_ffi::Path<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
) {
|
) {
|
||||||
|
|
@ -3332,29 +3343,29 @@ impl<'ctx> mupdf_ffi::DeviceCallbacks<'ctx> for MyDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip_path(
|
fn clip_path(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
path: &mupdf_ffi::Path<'ctx>,
|
path: &mupdf_ffi::Path<'ctx>,
|
||||||
even_odd: bool,
|
_even_odd: bool,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
scissor: mupdf_sys::fz_rect,
|
_scissor: mupdf_sys::fz_rect,
|
||||||
) {
|
) {
|
||||||
self.path(path, cmt);
|
self.path(path, cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip_stroke_path(
|
fn clip_stroke_path(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
path: &mupdf_ffi::Path<'ctx>,
|
path: &mupdf_ffi::Path<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
scissor: mupdf_sys::fz_rect,
|
_scissor: mupdf_sys::fz_rect,
|
||||||
) {
|
) {
|
||||||
self.path(path, cmt);
|
self.path(path, cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_text(
|
fn fill_text(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
text: &mupdf_ffi::Text<'ctx>,
|
text: &mupdf_ffi::Text<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
) {
|
) {
|
||||||
|
|
@ -3362,8 +3373,8 @@ impl<'ctx> mupdf_ffi::DeviceCallbacks<'ctx> for MyDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stroke_text(
|
fn stroke_text(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
text: &mupdf_ffi::Text<'ctx>,
|
text: &mupdf_ffi::Text<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
) {
|
) {
|
||||||
|
|
@ -3371,28 +3382,28 @@ impl<'ctx> mupdf_ffi::DeviceCallbacks<'ctx> for MyDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip_text(
|
fn clip_text(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
text: &mupdf_ffi::Text<'ctx>,
|
text: &mupdf_ffi::Text<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
scissor: mupdf_sys::fz_rect,
|
_scissor: mupdf_sys::fz_rect,
|
||||||
) {
|
) {
|
||||||
self.text(text, cmt);
|
self.text(text, cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip_stroke_text(
|
fn clip_stroke_text(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
text: &mupdf_ffi::Text<'ctx>,
|
text: &mupdf_ffi::Text<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
scissor: mupdf_sys::fz_rect,
|
_scissor: mupdf_sys::fz_rect,
|
||||||
) {
|
) {
|
||||||
self.text(text, cmt);
|
self.text(text, cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_text(
|
fn ignore_text(
|
||||||
&mut self,
|
&self,
|
||||||
ctx: mupdf_ffi::ContextRef<'ctx>,
|
_ctx: mupdf_ffi::ContextRef<'ctx>,
|
||||||
text: &mupdf_ffi::Text<'ctx>,
|
text: &mupdf_ffi::Text<'ctx>,
|
||||||
cmt: fz_matrix,
|
cmt: fz_matrix,
|
||||||
) {
|
) {
|
||||||
|
|
@ -3477,20 +3488,25 @@ impl Page {
|
||||||
let device = MyDevice::new(page_num);
|
let device = MyDevice::new(page_num);
|
||||||
page.run(
|
page.run(
|
||||||
&mupdf_ffi::Device::new(page.ctx(), Box::new(device))?,
|
&mupdf_ffi::Device::new(page.ctx(), Box::new(device))?,
|
||||||
&mupdf::Matrix::IDENTITY,
|
fz_matrix {
|
||||||
|
a: 1.0,
|
||||||
|
b: 0.0,
|
||||||
|
c: 0.0,
|
||||||
|
d: 1.0,
|
||||||
|
e: 0.0,
|
||||||
|
f: 0.0,
|
||||||
|
},
|
||||||
)?;
|
)?;
|
||||||
let MyDevice {
|
let MyDevice {
|
||||||
page_num,
|
page_num,
|
||||||
qt,
|
qt,
|
||||||
|
unprocessed_chars,
|
||||||
unprocessed_non_text,
|
unprocessed_non_text,
|
||||||
} = device;
|
} = device;
|
||||||
let mut qt = Rc::try_unwrap(qt)
|
let mut qt = Rc::try_unwrap(qt)
|
||||||
.ok()
|
.ok()
|
||||||
.expect("already dropped all other references")
|
.expect("already dropped all other references")
|
||||||
.into_inner();
|
.into_inner();
|
||||||
let unprocessed_chars: Rc<
|
|
||||||
RefCell<BTreeMap<TextSection, Rc<RefCell<BTreeMap<Font, IndexSet<Char>>>>>>,
|
|
||||||
> = Rc::default();
|
|
||||||
// we convert to xml and parse that becuase the mupdf rust crate doesn't include all the API surface we need.
|
// we convert to xml and parse that becuase the mupdf rust crate doesn't include all the API surface we need.
|
||||||
let json = page.stext_page_as_json_from_page(1.0)?;
|
let json = page.stext_page_as_json_from_page(1.0)?;
|
||||||
todo!("{json}");
|
todo!("{json}");
|
||||||
|
|
|
||||||
160
src/mupdf_ffi.rs
160
src/mupdf_ffi.rs
|
|
@ -4,13 +4,14 @@
|
||||||
use mupdf_sys::{
|
use mupdf_sys::{
|
||||||
fz_clone_context, fz_color_params, fz_colorspace, fz_context, fz_device, fz_document,
|
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_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_rect, fz_stroke_state, fz_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_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,
|
mupdf_new_base_context, mupdf_new_derived_device, mupdf_open_document, mupdf_run_page,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
ffi::{CStr, CString, c_int},
|
ffi::{CStr, CString, c_int, c_void},
|
||||||
fmt,
|
fmt,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
|
|
@ -542,11 +543,158 @@ struct DeviceStruct<T> {
|
||||||
value: Box<T>,
|
value: Box<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait PathWalker<'ctx> {
|
||||||
|
fn move_to(&mut self, ctx: ContextRef<'ctx>, x: f32, y: f32);
|
||||||
|
fn line_to(&mut self, ctx: ContextRef<'ctx>, x: f32, y: f32);
|
||||||
|
fn curve_to(
|
||||||
|
&mut self,
|
||||||
|
ctx: ContextRef<'ctx>,
|
||||||
|
x1: f32,
|
||||||
|
y1: f32,
|
||||||
|
x2: f32,
|
||||||
|
y2: f32,
|
||||||
|
x3: f32,
|
||||||
|
y3: f32,
|
||||||
|
);
|
||||||
|
fn close_path(&mut self, ctx: ContextRef<'ctx>);
|
||||||
|
fn rect_to(&mut self, ctx: ContextRef<'ctx>, x1: f32, y1: f32, x2: f32, y2: f32) {
|
||||||
|
self.move_to(ctx, x1, y1);
|
||||||
|
self.move_to(ctx, x2, y1);
|
||||||
|
self.move_to(ctx, x2, y2);
|
||||||
|
self.move_to(ctx, x1, y2);
|
||||||
|
self.close_path(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx, T: ?Sized + PathWalker<'ctx>> PathWalker<'ctx> for &'_ mut T {
|
||||||
|
fn move_to(&mut self, ctx: ContextRef<'ctx>, x: f32, y: f32) {
|
||||||
|
T::move_to(self, ctx, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_to(&mut self, ctx: ContextRef<'ctx>, x: f32, y: f32) {
|
||||||
|
T::line_to(self, ctx, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn curve_to(
|
||||||
|
&mut self,
|
||||||
|
ctx: ContextRef<'ctx>,
|
||||||
|
x1: f32,
|
||||||
|
y1: f32,
|
||||||
|
x2: f32,
|
||||||
|
y2: f32,
|
||||||
|
x3: f32,
|
||||||
|
y3: f32,
|
||||||
|
) {
|
||||||
|
T::curve_to(self, ctx, x1, y1, x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_path(&mut self, ctx: ContextRef<'ctx>) {
|
||||||
|
T::close_path(self, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_to(&mut self, ctx: ContextRef<'ctx>, x1: f32, y1: f32, x2: f32, y2: f32) {
|
||||||
|
T::rect_to(self, ctx, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Path<'ctx> {
|
pub(crate) struct Path<'ctx> {
|
||||||
ptr: *mut fz_path,
|
ptr: *mut fz_path,
|
||||||
ctx: ContextRef<'ctx>,
|
ctx: ContextRef<'ctx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ctx> Path<'ctx> {
|
||||||
|
pub(crate) fn walk<W: PathWalker<'ctx>>(&self, mut walker: W) {
|
||||||
|
unsafe {
|
||||||
|
fz_walk_path(
|
||||||
|
self.ctx.0.as_ptr(),
|
||||||
|
self.ptr,
|
||||||
|
const {
|
||||||
|
&fz_path_walker {
|
||||||
|
moveto: Some(Self::move_to_fn::<W>),
|
||||||
|
lineto: Some(Self::line_to_fn::<W>),
|
||||||
|
curveto: Some(Self::curve_to_fn::<W>),
|
||||||
|
closepath: Some(Self::close_path_fn::<W>),
|
||||||
|
quadto: None,
|
||||||
|
curvetov: None,
|
||||||
|
curvetoy: None,
|
||||||
|
rectto: Some(Self::rect_to_fn::<W>),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(&raw mut walker).cast(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn move_to_fn<W: PathWalker<'ctx>>(
|
||||||
|
ctx: *mut fz_context,
|
||||||
|
arg: *mut c_void,
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
) {
|
||||||
|
let Some(ctx) = NonNull::new(ctx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ctx = ContextRef(ctx, PhantomData);
|
||||||
|
let this = unsafe { &mut *arg.cast::<W>() };
|
||||||
|
this.move_to(ctx, x, y);
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn line_to_fn<W: PathWalker<'ctx>>(
|
||||||
|
ctx: *mut fz_context,
|
||||||
|
arg: *mut c_void,
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
) {
|
||||||
|
let Some(ctx) = NonNull::new(ctx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ctx = ContextRef(ctx, PhantomData);
|
||||||
|
let this = unsafe { &mut *arg.cast::<W>() };
|
||||||
|
this.line_to(ctx, x, y);
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn curve_to_fn<W: PathWalker<'ctx>>(
|
||||||
|
ctx: *mut fz_context,
|
||||||
|
arg: *mut c_void,
|
||||||
|
x1: f32,
|
||||||
|
y1: f32,
|
||||||
|
x2: f32,
|
||||||
|
y2: f32,
|
||||||
|
x3: f32,
|
||||||
|
y3: f32,
|
||||||
|
) {
|
||||||
|
let Some(ctx) = NonNull::new(ctx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ctx = ContextRef(ctx, PhantomData);
|
||||||
|
let this = unsafe { &mut *arg.cast::<W>() };
|
||||||
|
this.curve_to(ctx, x1, y1, x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn close_path_fn<W: PathWalker<'ctx>>(
|
||||||
|
ctx: *mut fz_context,
|
||||||
|
arg: *mut c_void,
|
||||||
|
) {
|
||||||
|
let Some(ctx) = NonNull::new(ctx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ctx = ContextRef(ctx, PhantomData);
|
||||||
|
let this = unsafe { &mut *arg.cast::<W>() };
|
||||||
|
this.close_path(ctx);
|
||||||
|
}
|
||||||
|
unsafe extern "C" fn rect_to_fn<W: PathWalker<'ctx>>(
|
||||||
|
ctx: *mut fz_context,
|
||||||
|
arg: *mut c_void,
|
||||||
|
x1: f32,
|
||||||
|
y1: f32,
|
||||||
|
x2: f32,
|
||||||
|
y2: f32,
|
||||||
|
) {
|
||||||
|
let Some(ctx) = NonNull::new(ctx) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ctx = ContextRef(ctx, PhantomData);
|
||||||
|
let this = unsafe { &mut *arg.cast::<W>() };
|
||||||
|
this.rect_to(ctx, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'ctx> Drop for Path<'ctx> {
|
impl<'ctx> Drop for Path<'ctx> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -567,3 +715,11 @@ impl<'ctx> Drop for Text<'ctx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn transform_point(point: fz_point, m: fz_matrix) -> fz_point {
|
||||||
|
unsafe { fz_transform_point(point, m) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn transform_point_xy(x: f32, y: f32, m: fz_matrix) -> fz_point {
|
||||||
|
unsafe { fz_transform_point_xy(x, y, m) }
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue