Initial Functional Plugin
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
/.direnv
|
||||||
|
*.mgc
|
||||||
3665
Cargo.lock
generated
Normal file
3665
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
Cargo.toml
Normal file
27
Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "zathura-typst-plugin"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
typst = "0.14.0"
|
||||||
|
typst-render = "0.14.0"
|
||||||
|
cairo-rs = "0.21.2"
|
||||||
|
typst-kit = { version = "0.14.0", features = ["embed-fonts", "vendor-openssl"] }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bindgen = "0.72.1"
|
||||||
|
pkg-config = "0.3.32"
|
||||||
|
system-deps = "7.0.6"
|
||||||
|
|
||||||
|
[package.metadata.system-deps]
|
||||||
|
zathura = "0.5.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = 'abort'
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = 'abort'
|
||||||
21
build.rs
Normal file
21
build.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
system_deps::Config::new().probe().unwrap();
|
||||||
|
|
||||||
|
let bindings = bindgen::Builder::default()
|
||||||
|
.header("wrapper.h")
|
||||||
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||||
|
.formatter(bindgen::Formatter::Prettyplease)
|
||||||
|
.allowlist_item("zathura_.*")
|
||||||
|
.blocklist_item("zathura_plugin_error_e")
|
||||||
|
.blocklist_item("^cairo_.*")
|
||||||
|
.generate()
|
||||||
|
.expect("Unable to generate bindings");
|
||||||
|
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
bindings.write_to_file(out_path.join("bindings.rs")).expect("Couldn't write bindings");
|
||||||
|
}
|
||||||
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1761574448,
|
||||||
|
"narHash": "sha256-zCRT8xJbC5rYPghC/AVyHh7cPPyyNxx/siyrQhg3u6s=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "497f8871b05933590ae58e4b48172320c59f108f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
68
flake.nix
Normal file
68
flake.nix
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }: let
|
||||||
|
inherit (nixpkgs) lib;
|
||||||
|
systems = ["x86_64-linux"];
|
||||||
|
eachSystem = f: lib.genAttrs systems (system: f {
|
||||||
|
inherit system;
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
ownPkgs = self.packages.${system};
|
||||||
|
});
|
||||||
|
in {
|
||||||
|
packages = eachSystem ({ pkgs, ... }: {
|
||||||
|
default = pkgs.rustPlatform.buildRustPackage (final: {
|
||||||
|
pname = "zathura-typst";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
cargoHash = lib.fakeHash;
|
||||||
|
|
||||||
|
buildInputs = [pkgs.zathuraPkgs.zathura_core pkgs.girara pkgs.cairo pkgs.pkg-config];
|
||||||
|
|
||||||
|
# From https://hoverbear.org/blog/rust-bindgen-in-nix/
|
||||||
|
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||||
|
preBuild = ''
|
||||||
|
# From: https://github.com/NixOS/nixpkgs/blob/1fab95f5190d087e66a3502481e34e15d62090aa/pkgs/applications/networking/browsers/firefox/common.nix#L247-L253
|
||||||
|
# Set C flags for Rust's bindgen program. Unlike ordinary C
|
||||||
|
# compilation, bindgen does not invoke $CC directly. Instead it
|
||||||
|
# uses LLVM's libclang. To make sure all necessary flags are
|
||||||
|
# included we need to look in a few places.
|
||||||
|
export BINDGEN_EXTRA_CLANG_ARGS="$(< ${pkgs.stdenv.cc}/nix-support/libc-crt1-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/libc-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/cc-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/libcxx-cxxflags) \
|
||||||
|
${lib.optionalString pkgs.stdenv.cc.isClang "-idirafter ${pkgs.stdenv.cc.cc}/lib/clang/${lib.getVersion pkgs.stdenv.cc.cc}/include"} \
|
||||||
|
${lib.optionalString pkgs.stdenv.cc.isGNU "-isystem ${pkgs.stdenv.cc.cc}/include/c++/${lib.getVersion pkgs.stdenv.cc.cc} -isystem ${pkgs.stdenv.cc.cc}/include/c++/${lib.getVersion pkgs.stdenv.cc.cc}/${pkgs.stdenv.hostPlatform.config}"} \
|
||||||
|
$(pkg-config --cflags zathura)
|
||||||
|
"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
devShells = eachSystem ({ pkgs, ownPkgs, ... }: {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
inputsFrom = [ownPkgs.default];
|
||||||
|
packages = [pkgs.rust-analyzer pkgs.clippy pkgs.rustfmt];
|
||||||
|
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||||
|
shellHook = ''
|
||||||
|
# From: https://github.com/NixOS/nixpkgs/blob/1fab95f5190d087e66a3502481e34e15d62090aa/pkgs/applications/networking/browsers/firefox/common.nix#L247-L253
|
||||||
|
# Set C flags for Rust's bindgen program. Unlike ordinary C
|
||||||
|
# compilation, bindgen does not invoke $CC directly. Instead it
|
||||||
|
# uses LLVM's libclang. To make sure all necessary flags are
|
||||||
|
# included we need to look in a few places.
|
||||||
|
export BINDGEN_EXTRA_CLANG_ARGS="$(< ${pkgs.stdenv.cc}/nix-support/libc-crt1-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/libc-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/cc-cflags) \
|
||||||
|
$(< ${pkgs.stdenv.cc}/nix-support/libcxx-cxxflags) \
|
||||||
|
${lib.optionalString pkgs.stdenv.cc.isClang "-idirafter ${pkgs.stdenv.cc.cc}/lib/clang/${lib.getVersion pkgs.stdenv.cc.cc}/include"} \
|
||||||
|
${lib.optionalString pkgs.stdenv.cc.isGNU "-isystem ${pkgs.stdenv.cc.cc}/include/c++/${lib.getVersion pkgs.stdenv.cc.cc} -isystem ${pkgs.stdenv.cc.cc}/include/c++/${lib.getVersion pkgs.stdenv.cc.cc}/${pkgs.stdenv.hostPlatform.config}"} \
|
||||||
|
$(pkg-config --cflags zathura)
|
||||||
|
"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
6
magic/typst.magic
Normal file
6
magic/typst.magic
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
0 string/cW /*\ doc:\ typst\ */ typst text document
|
||||||
|
!:ext typ
|
||||||
|
!:mime text/vnd.typst
|
||||||
|
0 string #import typst text document
|
||||||
|
!:ext typ
|
||||||
|
!:mime text/vnd.typst
|
||||||
167
src/lib.rs
Normal file
167
src/lib.rs
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
use std::{
|
||||||
|
ffi::{CStr, OsStr, c_void},
|
||||||
|
os::unix::ffi::OsStrExt,
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
use cairo::{Format, ImageSurface};
|
||||||
|
|
||||||
|
use crate::zathura::{
|
||||||
|
ZathuraResult, cairo_t, zathura_document_get_data, zathura_document_get_path,
|
||||||
|
zathura_document_s, zathura_document_set_data, zathura_document_set_number_of_pages,
|
||||||
|
zathura_page_get_document, zathura_page_get_index, zathura_page_set_height,
|
||||||
|
zathura_page_set_width, zathura_page_t,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod typst;
|
||||||
|
mod zathura;
|
||||||
|
use typst::TypstDocument;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub static zathura_plugin_6_7: zathura::zathura_plugin_definition_s =
|
||||||
|
zathura::zathura_plugin_definition_s {
|
||||||
|
name: c"zathura-typst".as_ptr(),
|
||||||
|
version: zathura::zathura_plugin_version_s {
|
||||||
|
major: 0,
|
||||||
|
minor: 1,
|
||||||
|
rev: 0,
|
||||||
|
},
|
||||||
|
functions: zathura::zathura_plugin_functions_s {
|
||||||
|
document_open: Some(document_open),
|
||||||
|
document_free: Some(document_free),
|
||||||
|
document_index_generate: None,
|
||||||
|
document_save_as: None,
|
||||||
|
document_attachments_get: None,
|
||||||
|
document_attachment_save: None,
|
||||||
|
document_get_information: None,
|
||||||
|
page_init: Some(page_init),
|
||||||
|
page_clear: Some(page_clear),
|
||||||
|
page_search_text: None,
|
||||||
|
page_links_get: None,
|
||||||
|
page_form_fields_get: None,
|
||||||
|
page_images_get: None,
|
||||||
|
page_image_get_cairo: None,
|
||||||
|
page_get_text: None,
|
||||||
|
page_get_selection: None,
|
||||||
|
page_render_cairo: Some(page_render_cairo),
|
||||||
|
page_get_label: None,
|
||||||
|
page_get_signatures: None,
|
||||||
|
},
|
||||||
|
mime_types_size: 1,
|
||||||
|
mime_types: {
|
||||||
|
static MIMETYPES: &[&u8] = &[c"text/vnd.typst".to_bytes_with_nul().first().unwrap()];
|
||||||
|
MIMETYPES.as_ptr() as *mut _
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe extern "C" fn document_open(doc: *mut zathura_document_s) -> ZathuraResult {
|
||||||
|
let path = unsafe {
|
||||||
|
Path::new(OsStr::from_bytes(
|
||||||
|
CStr::from_ptr(zathura_document_get_path(doc)).to_bytes(),
|
||||||
|
))
|
||||||
|
};
|
||||||
|
let Ok(document) = TypstDocument::load(path) else {
|
||||||
|
return ZathuraResult::InvalidArguments;
|
||||||
|
};
|
||||||
|
let document = Box::new(document);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
zathura_document_set_number_of_pages(doc, document.doc.pages.len() as _);
|
||||||
|
zathura_document_set_data(doc, Box::into_raw(document) as _);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn document_free(_: *mut zathura_document_s, data: *mut c_void) -> ZathuraResult {
|
||||||
|
if !data.is_null() {
|
||||||
|
drop(unsafe { Box::<TypstDocument>::from_raw(data as _) });
|
||||||
|
}
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn page_init(page: *mut zathura_page_t) -> ZathuraResult {
|
||||||
|
let pageno = unsafe { zathura_page_get_index(page) };
|
||||||
|
let doc = unsafe { zathura_page_get_document(page) };
|
||||||
|
let typst_doc = unsafe { &mut *(zathura_document_get_data(doc) as *mut TypstDocument) };
|
||||||
|
let typst_page = &mut typst_doc.doc.pages[pageno as usize];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
zathura_page_set_width(page, typst_page.frame.width().to_pt());
|
||||||
|
zathura_page_set_height(page, typst_page.frame.height().to_pt());
|
||||||
|
};
|
||||||
|
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn page_clear(_: *mut zathura_page_t, _: *mut c_void) -> ZathuraResult {
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn page_render_cairo(
|
||||||
|
page: *mut zathura_page_t,
|
||||||
|
_: *mut c_void,
|
||||||
|
cairo: *mut cairo_t,
|
||||||
|
_printing: bool,
|
||||||
|
) -> ZathuraResult {
|
||||||
|
let pageno = unsafe { zathura_page_get_index(page) };
|
||||||
|
let doc = unsafe { zathura_page_get_document(page) };
|
||||||
|
let typst_doc = unsafe { &mut *(zathura_document_get_data(doc) as *mut TypstDocument) };
|
||||||
|
let typst_page = &mut typst_doc.doc.pages[pageno as usize];
|
||||||
|
|
||||||
|
let context = unsafe { cairo::Context::from_raw_none(cairo) };
|
||||||
|
let surface = context.target();
|
||||||
|
if surface.status().is_err() {
|
||||||
|
return ZathuraResult::Unknown;
|
||||||
|
}
|
||||||
|
let Ok(surface) = ImageSurface::try_from(surface) else {
|
||||||
|
return ZathuraResult::InvalidArguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
let scale = {
|
||||||
|
let wscale = surface.width() as f32 / typst_page.frame.width().to_pt() as f32;
|
||||||
|
let vscale = surface.height() as f32 / typst_page.frame.height().to_pt() as f32;
|
||||||
|
if wscale < vscale { wscale } else { vscale } // min, but floats aren't Ord
|
||||||
|
};
|
||||||
|
|
||||||
|
let format = surface.format();
|
||||||
|
|
||||||
|
let pixels_rgba = typst_render::render(typst_page, scale).take();
|
||||||
|
|
||||||
|
let (pixels_rgba, _) = pixels_rgba.as_chunks::<4>(); // This will always be exact anyway
|
||||||
|
|
||||||
|
let buf = unsafe {
|
||||||
|
std::slice::from_raw_parts_mut(
|
||||||
|
cairo::ffi::cairo_image_surface_get_data(surface.to_raw_none()),
|
||||||
|
surface.stride() as usize * surface.height() as usize,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if !matches!(format, Format::ARgb32 | Format::Rgb24) {
|
||||||
|
return ZathuraResult::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels_rgba
|
||||||
|
.iter()
|
||||||
|
.zip(buf.chunks_exact_mut(4))
|
||||||
|
.for_each(|(&[r, g, b, a], dst)| {
|
||||||
|
dst.copy_from_slice(&u32::from_be_bytes([a, r, g, b]).to_ne_bytes());
|
||||||
|
});
|
||||||
|
|
||||||
|
surface.mark_dirty();
|
||||||
|
|
||||||
|
ZathuraResult::OK
|
||||||
|
}
|
||||||
|
// TODO: handle compile errors
|
||||||
|
// TODO: render warnings
|
||||||
|
// TODO: text/link/... handling
|
||||||
|
// TODO: nixify compilation of magicdb (file -Cm ~/.magic:/nix/store/vi7ya34k19nid2m0dmkljqip5572g0bi-file-5.45/share/misc/magic.mgc)
|
||||||
|
/*
|
||||||
|
0 string/cW /*\ doc:\ typst\ */ typst text document
|
||||||
|
!:ext typ
|
||||||
|
!:mime text/vnd.typst
|
||||||
|
0 string #import typst text document
|
||||||
|
!:ext typ
|
||||||
|
!:mime text/vnd.typst
|
||||||
|
*/
|
||||||
147
src/typst.rs
Normal file
147
src/typst.rs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
use std::{
|
||||||
|
collections::{HashMap, hash_map::Entry},
|
||||||
|
hash::Hash,
|
||||||
|
io::{self, ErrorKind},
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::{LazyLock, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use typst::{
|
||||||
|
Library, LibraryExt,
|
||||||
|
diag::{FileError, FileResult, SourceDiagnostic, Warned},
|
||||||
|
foundations::{Bytes, Datetime},
|
||||||
|
syntax::{FileId, Source, Span, VirtualPath},
|
||||||
|
text::{Font, FontBook},
|
||||||
|
utils::LazyHash,
|
||||||
|
};
|
||||||
|
use typst_kit::{
|
||||||
|
download::{Downloader, ProgressSink},
|
||||||
|
fonts::{FontSearcher, Fonts},
|
||||||
|
package::PackageStorage,
|
||||||
|
};
|
||||||
|
|
||||||
|
static PACKAGE_SOURCE: LazyLock<Mutex<PackageStorage>> = LazyLock::new(|| {
|
||||||
|
Mutex::new(PackageStorage::new(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Downloader::new("zathura-typst-plugin v0.1.0"),
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
static FONTS: LazyLock<Fonts> = LazyLock::new(|| FontSearcher::new().search());
|
||||||
|
|
||||||
|
struct World {
|
||||||
|
root: PathBuf,
|
||||||
|
main: FileId,
|
||||||
|
source_cache: Mutex<HashMap<FileId, Source>>,
|
||||||
|
file_cache: Mutex<HashMap<FileId, Bytes>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_or_insert_with_err<K: Hash + Eq, V, E>(
|
||||||
|
map: &mut HashMap<K, V>,
|
||||||
|
key: K,
|
||||||
|
f: impl FnOnce() -> Result<V, E>,
|
||||||
|
) -> Result<&mut V, E> {
|
||||||
|
match map.entry(key) {
|
||||||
|
Entry::Occupied(entry) => Ok(entry.into_mut()),
|
||||||
|
Entry::Vacant(entry) => Ok(entry.insert(f()?)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl typst::World for World {
|
||||||
|
fn library(&self) -> &LazyHash<Library> {
|
||||||
|
static LIBRARY: LazyLock<LazyHash<Library>> =
|
||||||
|
LazyLock::new(|| LazyHash::new(Library::default()));
|
||||||
|
&LIBRARY
|
||||||
|
}
|
||||||
|
|
||||||
|
fn book(&self) -> &LazyHash<FontBook> {
|
||||||
|
static BOOK: LazyLock<LazyHash<FontBook>> =
|
||||||
|
LazyLock::new(|| LazyHash::new(FONTS.book.clone()));
|
||||||
|
&BOOK
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(&self) -> FileId {
|
||||||
|
self.main
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self, id: FileId) -> FileResult<Source> {
|
||||||
|
map_or_insert_with_err(&mut self.source_cache.lock().unwrap(), id, || {
|
||||||
|
Ok(Source::new(id, self.file(id)?.to_str()?.to_string()))
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file(&self, id: FileId) -> FileResult<Bytes> {
|
||||||
|
map_or_insert_with_err(&mut self.file_cache.lock().unwrap(), id, || {
|
||||||
|
let root = if let Some(package) = id.package() {
|
||||||
|
&PACKAGE_SOURCE
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.prepare_package(package, &mut ProgressSink)?
|
||||||
|
} else {
|
||||||
|
&self.root
|
||||||
|
};
|
||||||
|
let path = id
|
||||||
|
.vpath()
|
||||||
|
.resolve(root)
|
||||||
|
.ok_or_else(|| FileError::AccessDenied)?;
|
||||||
|
Ok(Bytes::new(
|
||||||
|
std::fs::read(&path).map_err(|e| FileError::from_io(e, &path))?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn font(&self, index: usize) -> Option<Font> {
|
||||||
|
FONTS.fonts.get(index)?.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn today(&self, _offset: Option<i64>) -> Option<Datetime> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
fn new(file: &Path) -> Result<Self, io::Error> {
|
||||||
|
let root = file
|
||||||
|
.canonicalize()?
|
||||||
|
.parent()
|
||||||
|
.ok_or(ErrorKind::NotFound)?
|
||||||
|
.to_owned();
|
||||||
|
Ok(Self {
|
||||||
|
main: FileId::new(
|
||||||
|
None,
|
||||||
|
VirtualPath::within_root(file, &root)
|
||||||
|
.expect("Root should contain path by construction"),
|
||||||
|
),
|
||||||
|
root: root.to_path_buf(),
|
||||||
|
source_cache: Default::default(),
|
||||||
|
file_cache: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypstDocument {
|
||||||
|
pub doc: typst::layout::PagedDocument,
|
||||||
|
pub warnings: Vec<SourceDiagnostic>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypstDocument {
|
||||||
|
pub fn load(path: &Path) -> Result<Self, Vec<SourceDiagnostic>> {
|
||||||
|
let Warned { output, warnings } = typst::compile(
|
||||||
|
&World::new(path)
|
||||||
|
.map_err(|e| vec![SourceDiagnostic::error(Span::detached(), e.to_string())])?,
|
||||||
|
);
|
||||||
|
match output {
|
||||||
|
Ok(doc) => Ok(Self {
|
||||||
|
doc,
|
||||||
|
warnings: warnings.to_vec(),
|
||||||
|
}),
|
||||||
|
Err(mut errors) => {
|
||||||
|
errors.extend(warnings);
|
||||||
|
Err(errors.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/zathura.rs
Normal file
23
src/zathura.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#![allow(warnings)]
|
||||||
|
pub use cairo::ffi::*;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
|
|
||||||
|
unsafe impl Sync for zathura_plugin_definition_s {}
|
||||||
|
|
||||||
|
pub type zathura_plugin_error_e = ZathuraResult;
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum ZathuraResult {
|
||||||
|
/// No error occurred
|
||||||
|
OK = 0,
|
||||||
|
/// An unknown error occurred
|
||||||
|
Unknown = 1,
|
||||||
|
/// Out of memory
|
||||||
|
OutOfMemory = 2,
|
||||||
|
/// The called function has not been implemented
|
||||||
|
NotImplemented = 3,
|
||||||
|
/// Invalid arguments have been passed
|
||||||
|
InvalidArguments = 4,
|
||||||
|
/// The provided password is invalid
|
||||||
|
InvalidPassword = 5,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user