#![allow(clippy::unnecessary_cast)]
#[rustfmt::skip] #[macro_use] pub mod error;
pub mod bitmap;
pub mod buffer;
pub mod color;
pub mod color_params;
pub mod colorspace;
pub mod context;
pub mod cookie;
pub mod destination;
pub mod device;
pub mod display_list;
pub mod document;
pub mod document_writer;
pub mod file_path;
pub mod font;
pub mod glyph;
pub mod image;
pub mod link;
pub mod matrix;
pub mod outline;
pub mod output;
pub mod page;
pub mod path;
pub mod pdf;
pub mod pixmap;
pub mod point;
pub mod quad;
pub mod rect;
pub mod separations;
pub mod shade;
pub mod size;
pub mod stroke_state;
#[cfg(all(feature = "system-fonts", not(target_arch = "wasm32")))]
pub mod system_font;
pub mod text;
pub mod text_page;
pub mod array;
use array::FzArray;
pub use bitmap::Bitmap;
pub use buffer::Buffer;
pub use color_params::{ColorParams, RenderingIntent};
pub use colorspace::Colorspace;
pub(crate) use context::context;
pub use context::Context;
pub use cookie::Cookie;
pub use destination::{Destination, DestinationKind};
pub use device::{BlendMode, Device, Function, NativeDevice};
pub use display_list::DisplayList;
pub use document::{Document, MetadataName};
pub use document_writer::DocumentWriter;
pub(crate) use error::ffi_error;
pub use error::Error;
pub use file_path::FilePath;
pub use font::{CjkFontOrdering, Font, SimpleFontEncoding, WriteMode};
pub use glyph::Glyph;
pub use image::Image;
pub use link::Link;
pub use matrix::Matrix;
pub use outline::Outline;
pub use page::Page;
pub use path::{Path, PathWalker};
pub use pixmap::{ImageFormat, Pixmap};
pub use point::Point;
pub use quad::Quad;
pub use rect::{IRect, Rect};
pub use separations::Separations;
pub use shade::Shade;
pub use size::Size;
pub use stroke_state::{LineCap, LineJoin, StrokeState};
pub use text::{Text, TextItem, TextSpan};
pub use text_page::{TextBlock, TextChar, TextLine, TextPage, TextPageFlags};
use core::{marker::PhantomData, ptr::NonNull};
use zerocopy::{FromBytes, IntoBytes};
pub(crate) trait Sealed {}
#[allow(private_bounds)]
pub trait FFIAnalogue: IntoBytes + FromBytes + Sized + Sealed {
type FFIType: IntoBytes + FromBytes + Sized;
fn _assert_size_eq() {
let _assert = AssertSizeEquals::<Self, Self::FFIType>::new();
}
}
trait FFIWrapper {
type FFIType;
fn as_ref(&self) -> &Self::FFIType;
fn as_ptr(&self) -> *const Self::FFIType;
fn as_mut_ptr(&mut self) -> *mut Self::FFIType;
}
macro_rules! unsafe_impl_ffi_wrapper {
($struct:ident, $ffi_type:ident, $ffi_drop_fn:ident) => {
impl $crate::FFIWrapper for $struct {
type FFIType = $ffi_type;
fn as_ref(&self) -> &Self::FFIType {
unsafe { self.inner.as_ref() }
}
fn as_ptr(&self) -> *const Self::FFIType {
self.inner.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut Self::FFIType {
unsafe { self.inner.as_mut() }
}
}
impl Drop for $struct {
fn drop(&mut self) {
let ptr = <Self as $crate::FFIWrapper>::as_ptr(&*self).cast_mut();
unsafe { $ffi_drop_fn($crate::context(), ptr) }
}
}
};
}
macro_rules! impl_ffi_traits {
($struct:ident, $ffi_type:ident) => {
impl $crate::Sealed for $struct {}
impl $crate::FFIAnalogue for $struct {
type FFIType = $ffi_type;
}
impl From<$ffi_type> for $struct {
fn from(val: $ffi_type) -> $struct {
::zerocopy::transmute!(val)
}
}
impl From<$struct> for $ffi_type {
fn from(val: $struct) -> $ffi_type {
::zerocopy::transmute!(val)
}
}
};
}
pub(crate) use impl_ffi_traits;
pub(crate) use unsafe_impl_ffi_wrapper;
unsafe fn rust_vec_from_ffi_ptr<R: FFIAnalogue>(
ptr: *mut R::FFIType,
len: i32,
) -> Result<FzArray<R>, Error> {
let Some(ptr) = NonNull::new(ptr) else {
return Err(Error::UnexpectedNullPtr);
};
let rust_ty_ptr = ptr.cast::<R>();
let mut arr = unsafe { FzArray::from_parts(rust_ty_ptr, 0) };
let len = usize::try_from(len)?;
unsafe { arr.set_len(len) };
Ok(arr)
}
fn rust_slice_to_ffi_ptr<R: FFIAnalogue>(vec: &[R]) -> Result<(*const R::FFIType, i32), Error> {
let len = i32::try_from(vec.len())?;
let ptr = vec.as_ptr() as *mut R::FFIType;
if ptr.is_null() {
return Err(Error::UnexpectedNullPtr);
}
Ok((ptr, len))
}
struct AssertSizeEquals<A, B> {
_phantom: PhantomData<(A, B)>,
}
impl<A, B> AssertSizeEquals<A, B> {
const _SIZE_OK: () = const { assert!(size_of::<A>() == size_of::<B>()) };
const fn new() -> Self {
Self {
_phantom: PhantomData,
}
}
}
macro_rules! from_enum {
(
$c_type_from:ty => $c_type_to:ty,
$(#[$($attr:tt)*])*
pub enum $name:ident {
$(
$(#[$($field_attr:tt)*])*
$field:ident = $value:tt,
)*
}
) => {
$(#[$($attr)*])*
pub enum $name {
$(
$(#[$($field_attr)*])*
$field = $value as isize,
)*
}
impl TryFrom<$c_type_from> for $name {
type Error = $crate::error::Error;
#[allow(non_upper_case_globals)]
fn try_from(value: $c_type_from) -> Result<Self, Self::Error> {
match value as _ {
$($value => Ok(Self::$field),)*
_ => Err(Self::Error::UnknownEnumVariant)
}
}
}
const _: () = {
$(
assert!((<$c_type_to>::MAX as i64) >= ($value as i64));
)*
};
impl From<$name> for $c_type_to {
fn from(value: $name) -> Self {
value as $c_type_to
}
}
};
}
pub(crate) use from_enum;