Compare commits
4 Commits
75754935be
...
5a66936222
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a66936222 | ||
|
|
3fad0a8312 | ||
|
|
81c62481c8 | ||
|
|
03353f9796 |
6
flake.lock
generated
6
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1761574448,
|
"lastModified": 1771495088,
|
||||||
"narHash": "sha256-zCRT8xJbC5rYPghC/AVyHh7cPPyyNxx/siyrQhg3u6s=",
|
"narHash": "sha256-1M4NAJMJDgdR/IegOhBQbxnJ9Dhj9VSM+JT2yuxiedI=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "497f8871b05933590ae58e4b48172320c59f108f",
|
"rev": "8c1d8f4fa63318fdc8658ca1f28a58b30bdc25cc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
devShells = eachSystem ({ pkgs, ownPkgs, ... }: {
|
devShells = eachSystem ({ pkgs, ownPkgs, ... }: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
inputsFrom = [ownPkgs.default];
|
inputsFrom = [ownPkgs.default];
|
||||||
packages = [pkgs.rust-analyzer pkgs.clippy pkgs.rustfmt];
|
packages = [pkgs.rust-analyzer pkgs.clippy pkgs.rustfmt pkgs.gdb];
|
||||||
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
# From: https://github.com/NixOS/nixpkgs/blob/1fab95f5190d087e66a3502481e34e15d62090aa/pkgs/applications/networking/browsers/firefox/common.nix#L247-L253
|
# From: https://github.com/NixOS/nixpkgs/blob/1fab95f5190d087e66a3502481e34e15d62090aa/pkgs/applications/networking/browsers/firefox/common.nix#L247-L253
|
||||||
|
|||||||
264
src/lib.rs
264
src/lib.rs
@@ -1,15 +1,17 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
ffi::{CStr, OsStr, c_void},
|
ffi::{CStr, CString, OsStr, c_void},
|
||||||
fs, iter,
|
fs,
|
||||||
mem::MaybeUninit,
|
|
||||||
os::unix::ffi::OsStrExt,
|
os::unix::ffi::OsStrExt,
|
||||||
path::Path,
|
path::Path,
|
||||||
|
ptr::{self, NonNull},
|
||||||
slice,
|
slice,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ::typst::{
|
use ::typst::{
|
||||||
|
Document,
|
||||||
layout::{Abs, FrameItem, Page, Point, Rect},
|
layout::{Abs, FrameItem, Page, Point, Rect},
|
||||||
|
model::{Destination, Numbering},
|
||||||
text::{Glyph, TextItem},
|
text::{Glyph, TextItem},
|
||||||
};
|
};
|
||||||
use cairo::{Format, ImageSurface};
|
use cairo::{Format, ImageSurface};
|
||||||
@@ -17,11 +19,21 @@ use cairo::{Format, ImageSurface};
|
|||||||
use crate::{
|
use crate::{
|
||||||
typst::FrameItemIterator,
|
typst::FrameItemIterator,
|
||||||
zathura::{
|
zathura::{
|
||||||
ZathuraResult, cairo_t, girara_list_append, girara_list_new_with_free, girara_list_t,
|
GiraraList, ZathuraResult, cairo_t, girara_list_t, zathura_document_get_data,
|
||||||
zathura_document_get_data, zathura_document_get_path, zathura_document_s,
|
zathura_document_get_path, zathura_document_information_entry_list_new,
|
||||||
zathura_document_set_data, zathura_document_set_number_of_pages, zathura_page_get_document,
|
zathura_document_information_entry_new, zathura_document_information_entry_t,
|
||||||
zathura_page_get_index, zathura_page_set_data, zathura_page_set_height,
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_AUTHOR,
|
||||||
zathura_page_set_width, zathura_page_t, zathura_rectangle_s,
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_CREATION_DATE,
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_KEYWORDS,
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_PRODUCER,
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_TITLE, zathura_document_s,
|
||||||
|
zathura_document_set_data, zathura_document_set_number_of_pages,
|
||||||
|
zathura_link_destination_type_e_ZATHURA_LINK_DESTINATION_UNKNOWN,
|
||||||
|
zathura_link_destination_type_e_ZATHURA_LINK_DESTINATION_XYZ, zathura_link_free,
|
||||||
|
zathura_link_new, zathura_link_target_s, zathura_link_type_e_ZATHURA_LINK_GOTO_DEST,
|
||||||
|
zathura_link_type_e_ZATHURA_LINK_GOTO_REMOTE, zathura_link_type_e_ZATHURA_LINK_URI,
|
||||||
|
zathura_page_get_document, zathura_page_get_index, zathura_page_set_data,
|
||||||
|
zathura_page_set_height, zathura_page_set_width, zathura_page_t, zathura_rectangle_s,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,22 +54,22 @@ pub static zathura_plugin_6_7: zathura::zathura_plugin_definition_s =
|
|||||||
functions: zathura::zathura_plugin_functions_s {
|
functions: zathura::zathura_plugin_functions_s {
|
||||||
document_open: Some(document_open),
|
document_open: Some(document_open),
|
||||||
document_free: Some(document_free),
|
document_free: Some(document_free),
|
||||||
document_index_generate: None,
|
document_index_generate: None, // TODO?
|
||||||
document_save_as: Some(document_save_as),
|
document_save_as: Some(document_save_as),
|
||||||
document_attachments_get: None,
|
document_attachments_get: None,
|
||||||
document_attachment_save: None,
|
document_attachment_save: None,
|
||||||
document_get_information: None,
|
document_get_information: Some(document_get_information),
|
||||||
page_init: Some(page_init),
|
page_init: Some(page_init),
|
||||||
page_clear: Some(page_clear),
|
page_clear: Some(page_clear),
|
||||||
page_search_text: None,
|
page_search_text: None, // TODO?
|
||||||
page_links_get: None,
|
page_links_get: Some(page_links_get),
|
||||||
page_form_fields_get: None,
|
page_form_fields_get: None,
|
||||||
page_images_get: None,
|
page_images_get: None, // TODO?
|
||||||
page_image_get_cairo: None,
|
page_image_get_cairo: None,
|
||||||
page_get_text: Some(page_get_text),
|
page_get_text: Some(page_get_text),
|
||||||
page_get_selection: Some(page_get_selection),
|
page_get_selection: Some(page_get_selection),
|
||||||
page_render_cairo: Some(page_render_cairo),
|
page_render_cairo: Some(page_render_cairo),
|
||||||
page_get_label: None,
|
page_get_label: Some(page_get_label),
|
||||||
page_get_signatures: None,
|
page_get_signatures: None,
|
||||||
},
|
},
|
||||||
mime_types_size: 1,
|
mime_types_size: 1,
|
||||||
@@ -90,6 +102,71 @@ unsafe extern "C" fn document_free(_: *mut zathura_document_s, data: *mut c_void
|
|||||||
ZathuraResult::OK
|
ZathuraResult::OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn document_get_information(
|
||||||
|
_: *mut zathura_document_s,
|
||||||
|
doc: *mut c_void,
|
||||||
|
res: *mut ZathuraResult,
|
||||||
|
) -> *mut girara_list_t {
|
||||||
|
let res = if let Some(mut r) = NonNull::new(res) {
|
||||||
|
unsafe {
|
||||||
|
r.write(ZathuraResult::Unknown);
|
||||||
|
r.as_mut()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
&mut ZathuraResult::OK
|
||||||
|
};
|
||||||
|
|
||||||
|
let doc = unsafe { &mut *(doc as *mut TypstDocument) };
|
||||||
|
let i = &doc.doc.info;
|
||||||
|
let mut lst = unsafe {
|
||||||
|
GiraraList::<zathura_document_information_entry_t>::from_raw(
|
||||||
|
zathura_document_information_entry_list_new(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
[
|
||||||
|
(
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_TITLE,
|
||||||
|
i.title.clone().unwrap_or_default().to_string(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_AUTHOR,
|
||||||
|
i.author.join(", "),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_KEYWORDS,
|
||||||
|
i.keywords.join(", "),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_CREATION_DATE,
|
||||||
|
i.date.unwrap_or_default().map_or(String::new(), |d| {
|
||||||
|
d.display(Default::default())
|
||||||
|
.expect("Defaults do the right thing")
|
||||||
|
.to_string()
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
zathura_document_information_type_e_ZATHURA_DOCUMENT_INFORMATION_PRODUCER,
|
||||||
|
"Typst (via zathura-plugin-typst)".to_owned(),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(_, st)| !st.is_empty())
|
||||||
|
.map(|(ty, st)| {
|
||||||
|
unsafe extern "C" {
|
||||||
|
safe fn calloc(n: usize, s: usize) -> *mut c_void;
|
||||||
|
}
|
||||||
|
let st_m = calloc(st.len() + 1, 1);
|
||||||
|
unsafe { slice::from_raw_parts_mut(st_m as *mut u8, st.len()) }
|
||||||
|
.copy_from_slice(st.as_bytes());
|
||||||
|
(ty, st_m as *const i8)
|
||||||
|
})
|
||||||
|
.for_each(|(ty, st)| {
|
||||||
|
unsafe { lst.append_allocated(zathura_document_information_entry_new(ty, st)) };
|
||||||
|
});
|
||||||
|
*res = ZathuraResult::OK;
|
||||||
|
lst.into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn document_save_as(
|
unsafe extern "C" fn document_save_as(
|
||||||
_: *mut zathura_document_s,
|
_: *mut zathura_document_s,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
@@ -232,7 +309,6 @@ fn selected_glyphs(
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.filter_map(move |(point, glyph)| {
|
.filter_map(move |(point, glyph)| {
|
||||||
dbg!(&item.text[glyph.range()]);
|
|
||||||
let bbox = item
|
let bbox = item
|
||||||
.font
|
.font
|
||||||
.ttf()
|
.ttf()
|
||||||
@@ -260,10 +336,13 @@ unsafe extern "C" fn page_get_text(
|
|||||||
rect: zathura_rectangle_s,
|
rect: zathura_rectangle_s,
|
||||||
res: *mut ZathuraResult,
|
res: *mut ZathuraResult,
|
||||||
) -> *mut i8 {
|
) -> *mut i8 {
|
||||||
let res = if res.is_null() {
|
let res = if let Some(mut r) = NonNull::new(res) {
|
||||||
&mut ZathuraResult::OK
|
unsafe {
|
||||||
|
r.write(ZathuraResult::Unknown);
|
||||||
|
r.as_mut()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsafe { &mut *(res as *mut MaybeUninit<ZathuraResult>) }.write(ZathuraResult::Unknown)
|
&mut ZathuraResult::OK
|
||||||
};
|
};
|
||||||
let typst_page: &Page = unsafe { &*(data as *mut _) };
|
let typst_page: &Page = unsafe { &*(data as *mut _) };
|
||||||
|
|
||||||
@@ -299,10 +378,13 @@ unsafe extern "C" fn page_get_selection(
|
|||||||
rect: zathura_rectangle_s,
|
rect: zathura_rectangle_s,
|
||||||
res: *mut ZathuraResult,
|
res: *mut ZathuraResult,
|
||||||
) -> *mut girara_list_t {
|
) -> *mut girara_list_t {
|
||||||
let res = if res.is_null() {
|
let res = if let Some(mut r) = NonNull::new(res) {
|
||||||
&mut ZathuraResult::OK
|
unsafe {
|
||||||
|
r.write(ZathuraResult::Unknown);
|
||||||
|
r.as_mut()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsafe { &mut *(res as *mut MaybeUninit<ZathuraResult>) }.write(ZathuraResult::Unknown)
|
&mut ZathuraResult::OK
|
||||||
};
|
};
|
||||||
let typst_page: &Page = unsafe { &*(data as *mut _) };
|
let typst_page: &Page = unsafe { &*(data as *mut _) };
|
||||||
|
|
||||||
@@ -320,31 +402,133 @@ unsafe extern "C" fn page_get_selection(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe extern "C" fn drop_rect(data: *mut c_void) {
|
*res = ZathuraResult::OK;
|
||||||
drop(unsafe { Box::from_raw(data as *mut zathura_rectangle_s) });
|
rects
|
||||||
|
.map(zathura_rectangle_s::from)
|
||||||
|
.collect::<GiraraList<zathura_rectangle_s>>()
|
||||||
|
.into_raw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn page_links_get(
|
||||||
|
zpage: *mut zathura_page_t,
|
||||||
|
page: *mut c_void,
|
||||||
|
res: *mut ZathuraResult,
|
||||||
|
) -> *mut girara_list_t {
|
||||||
|
let res = if let Some(mut r) = NonNull::new(res) {
|
||||||
|
unsafe {
|
||||||
|
r.write(ZathuraResult::Unknown);
|
||||||
|
r.as_mut()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
&mut ZathuraResult::OK
|
||||||
|
};
|
||||||
|
let doc = unsafe {
|
||||||
|
&mut (*(zathura_document_get_data(zathura_page_get_document(zpage)) as *mut TypstDocument))
|
||||||
|
};
|
||||||
|
|
||||||
|
let page: &Page = unsafe { &*(page as *const _) };
|
||||||
|
|
||||||
|
let links = FrameItemIterator::new(&page.frame)
|
||||||
|
.filter_map(|(point, item)| {
|
||||||
|
if let FrameItem::Link(dst, size) = item {
|
||||||
|
Some((Rect::from_pos_size(point, *size), dst))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|(rect, dst)| {
|
||||||
|
let (ty, target) = match dst {
|
||||||
|
Destination::Url(url) => (
|
||||||
|
if url.starts_with("file://") {
|
||||||
|
zathura_link_type_e_ZATHURA_LINK_GOTO_REMOTE
|
||||||
|
} else {
|
||||||
|
zathura_link_type_e_ZATHURA_LINK_URI
|
||||||
|
},
|
||||||
|
zathura_link_target_s {
|
||||||
|
destination_type:
|
||||||
|
zathura_link_destination_type_e_ZATHURA_LINK_DESTINATION_UNKNOWN,
|
||||||
|
value: doc
|
||||||
|
.cstring_cache
|
||||||
|
.entry(url.to_string())
|
||||||
|
.or_insert_with(|| {
|
||||||
|
CString::new(url.as_bytes()).expect("URL shouldn't contain NUL")
|
||||||
|
})
|
||||||
|
.as_ptr() as *mut i8,
|
||||||
|
page_number: 0,
|
||||||
|
left: -1.,
|
||||||
|
right: -1.,
|
||||||
|
top: -1.,
|
||||||
|
bottom: -1.,
|
||||||
|
zoom: 0.,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Destination::Position(position) => (
|
||||||
|
zathura_link_type_e_ZATHURA_LINK_GOTO_DEST,
|
||||||
|
zathura_link_target_s {
|
||||||
|
destination_type:
|
||||||
|
zathura_link_destination_type_e_ZATHURA_LINK_DESTINATION_XYZ,
|
||||||
|
value: ptr::null_mut(),
|
||||||
|
page_number: position.page.get() as u32 - 1,
|
||||||
|
left: position.point.x.to_pt(),
|
||||||
|
right: -1.,
|
||||||
|
top: position.point.y.to_pt(),
|
||||||
|
bottom: -1.,
|
||||||
|
zoom: 0.,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Destination::Location(location) => {
|
||||||
|
let position = doc.doc.introspector().position(*location);
|
||||||
|
(
|
||||||
|
zathura_link_type_e_ZATHURA_LINK_GOTO_DEST,
|
||||||
|
zathura_link_target_s {
|
||||||
|
destination_type:
|
||||||
|
zathura_link_destination_type_e_ZATHURA_LINK_DESTINATION_XYZ,
|
||||||
|
value: ptr::null_mut(),
|
||||||
|
page_number: position.page.get() as u32 - 1,
|
||||||
|
left: position.point.x.to_pt(),
|
||||||
|
right: -1.,
|
||||||
|
top: position.point.y.to_pt(),
|
||||||
|
bottom: -1.,
|
||||||
|
zoom: 0.,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe { zathura_link_new(ty, rect.into(), target) }
|
||||||
|
});
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let list = girara_list_new_with_free(Some(drop_rect));
|
let mut links_ = GiraraList::new_with_free(zathura_link_free);
|
||||||
|
links_.extend_allocated(links);
|
||||||
for rect in rects {
|
|
||||||
girara_list_append(
|
|
||||||
list,
|
|
||||||
Box::into_raw(Box::new(zathura_rectangle_s {
|
|
||||||
x1: rect.min.x.to_pt(),
|
|
||||||
y1: rect.min.y.to_pt(),
|
|
||||||
x2: rect.max.x.to_pt(),
|
|
||||||
y2: rect.max.y.to_pt(),
|
|
||||||
})) as *mut _,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
*res = ZathuraResult::OK;
|
*res = ZathuraResult::OK;
|
||||||
list
|
links_.into_raw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn page_get_label(
|
||||||
|
zpage: *mut zathura_page_t,
|
||||||
|
page: *mut c_void,
|
||||||
|
out: *mut *mut i8,
|
||||||
|
) -> ZathuraResult {
|
||||||
|
let doc = unsafe {
|
||||||
|
&mut *(zathura_document_get_data(zathura_page_get_document(zpage)) as *mut TypstDocument)
|
||||||
|
};
|
||||||
|
let page = unsafe { &*(page as *mut Page) };
|
||||||
|
let numbering = match page.numbering.clone() {
|
||||||
|
Some(Numbering::Pattern(numbering)) => numbering,
|
||||||
|
_ => "1".parse().expect("1 is a valid numbering style"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let label = numbering.apply(&[page.number]);
|
||||||
|
let label = doc
|
||||||
|
.cstring_cache
|
||||||
|
.entry(label.to_string())
|
||||||
|
.or_insert_with_key(|k| CString::new(k.to_owned()).expect("It's a string"))
|
||||||
|
.as_ptr();
|
||||||
|
|
||||||
|
unsafe { out.write(label as _) };
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: render warnings
|
// TODO: render warnings
|
||||||
// TODO: PDF as attachment
|
|
||||||
// TODO: link/... handling
|
|
||||||
// TODO: better caching
|
// TODO: better caching
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap}, hash::Hash, io::{self, ErrorKind}, iter, path::{Path, PathBuf}, slice, sync::{LazyLock, Mutex}
|
collections::{hash_map::Entry, HashMap}, ffi::CString, hash::Hash, io::{self, ErrorKind}, iter, path::{Path, PathBuf}, slice, sync::{LazyLock, Mutex}
|
||||||
};
|
};
|
||||||
|
|
||||||
use codespan_reporting::{
|
use codespan_reporting::{
|
||||||
@@ -131,6 +131,7 @@ impl World {
|
|||||||
pub struct TypstDocument {
|
pub struct TypstDocument {
|
||||||
pub doc: typst::layout::PagedDocument,
|
pub doc: typst::layout::PagedDocument,
|
||||||
pub warnings: Vec<SourceDiagnostic>,
|
pub warnings: Vec<SourceDiagnostic>,
|
||||||
|
pub cstring_cache: HashMap<String, CString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::result_large_err)]
|
#[allow(clippy::result_large_err)]
|
||||||
@@ -146,6 +147,7 @@ fn compile(path: &Path) -> Result<TypstDocument, (Option<World>, Vec<SourceDiagn
|
|||||||
Ok(doc) => Ok(TypstDocument {
|
Ok(doc) => Ok(TypstDocument {
|
||||||
doc,
|
doc,
|
||||||
warnings: warnings.to_vec(),
|
warnings: warnings.to_vec(),
|
||||||
|
cstring_cache: Default::default(),
|
||||||
}),
|
}),
|
||||||
Err(mut errors) => {
|
Err(mut errors) => {
|
||||||
errors.extend(warnings);
|
errors.extend(warnings);
|
||||||
@@ -277,6 +279,7 @@ fn diagnostics(world: &World, errors: impl IntoIterator<Item = SourceDiagnostic>
|
|||||||
TypstDocument {
|
TypstDocument {
|
||||||
doc: output.expect("Should be valid syntax"),
|
doc: output.expect("Should be valid syntax"),
|
||||||
warnings: vec![],
|
warnings: vec![],
|
||||||
|
cstring_cache: Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
use std::{ffi::c_void, marker::PhantomData, mem::ManuallyDrop};
|
||||||
|
|
||||||
pub use cairo::ffi::*;
|
pub use cairo::ffi::*;
|
||||||
use typst::layout::{Abs, Point, Rect};
|
use typst::layout::{Abs, Point, Rect};
|
||||||
|
|
||||||
@@ -8,6 +10,7 @@ unsafe impl Sync for zathura_plugin_definition_s {}
|
|||||||
|
|
||||||
pub type zathura_plugin_error_e = ZathuraResult;
|
pub type zathura_plugin_error_e = ZathuraResult;
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum ZathuraResult {
|
pub enum ZathuraResult {
|
||||||
/// No error occurred
|
/// No error occurred
|
||||||
OK = 0,
|
OK = 0,
|
||||||
@@ -45,3 +48,84 @@ impl From<zathura_rectangle_s> for Rect {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<Rect> for zathura_rectangle_s {
|
||||||
|
fn from(rect: Rect) -> Self {
|
||||||
|
zathura_rectangle_s {
|
||||||
|
x1: rect.min.x.to_pt(),
|
||||||
|
y1: rect.min.y.to_pt(),
|
||||||
|
x2: rect.max.x.to_pt(),
|
||||||
|
y2: rect.max.y.to_pt(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GiraraList<T> {
|
||||||
|
list: *mut girara_list_t,
|
||||||
|
data: PhantomData<Box<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> GiraraList<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
unsafe extern "C" fn free<T>(t: *mut c_void) {
|
||||||
|
drop(unsafe { Box::from_raw(t as *mut T) });
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
list: unsafe { girara_list_new_with_free(Some(free::<T>)) },
|
||||||
|
data: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn new_with_free(free: unsafe extern "C" fn(*mut T)) -> Self {
|
||||||
|
Self {
|
||||||
|
list: unsafe { girara_list_new_with_free(Some(std::mem::transmute(free))) },
|
||||||
|
data: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn from_raw(list: *mut girara_list_t) -> Self {
|
||||||
|
Self { list, data: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_raw(self) -> *mut girara_list_t {
|
||||||
|
let s = ManuallyDrop::new(self);
|
||||||
|
s.list
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, t: T) {
|
||||||
|
unsafe { self.append_allocated(Box::into_raw(Box::new(t)) as _) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn append_allocated(&mut self, t: *mut T) {
|
||||||
|
unsafe { girara_list_append(self.list, t as _) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn extend_allocated(&mut self, iter: impl IntoIterator<Item = *mut T>) {
|
||||||
|
for i in iter {
|
||||||
|
unsafe { self.append_allocated(i) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Extend<T> for GiraraList<T> {
|
||||||
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||||
|
for i in iter {
|
||||||
|
self.append(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FromIterator<T> for GiraraList<T> {
|
||||||
|
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||||
|
let mut list = Self::new();
|
||||||
|
list.extend(iter);
|
||||||
|
list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Drop for GiraraList<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
girara_list_free(self.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user