use core::slice;
use std::{convert::TryInto, marker::PhantomData};
use ttf2mesh_sys as sys;
use crate::{
output::{DataIterator, Value},
Error,
};
pub type Mesh3d = ttf2mesh_sys::ttf_mesh3d;
pub type Mesh2d = ttf2mesh_sys::ttf_mesh;
type Vert2d = sys::ttf_mesh__bindgen_ty_1;
type Face2d = sys::ttf_mesh__bindgen_ty_2;
type Vert3d = sys::ttf_mesh3d__bindgen_ty_1;
type Face3d = sys::ttf_mesh3d__bindgen_ty_2;
type Normal = sys::ttf_mesh3d__bindgen_ty_3;
#[allow(unused_imports)]
use crate::Glyph;
pub struct Mesh<'a, T: InnerMesh<'a>> {
inner: *mut T,
_phantom: &'a PhantomData<T>,
}
pub trait InnerMesh<'a> {
type VertStruct: Value<'a>;
type FaceStruct: Value<'a>;
type NormalStruct: Value<'a>;
fn vertices_len(&self) -> usize;
fn faces_len(&self) -> usize;
fn normals_len(&self) -> usize;
fn vert_ptr(&self) -> *mut Self::VertStruct;
fn face_ptr(&self) -> *mut Self::FaceStruct;
fn normals_ptr(&self) -> Option<*mut Self::NormalStruct>;
unsafe fn free(&mut self);
}
impl<'a> InnerMesh<'a> for Mesh2d {
type VertStruct = Vert2d;
type FaceStruct = Face2d;
type NormalStruct = Normal;
fn vert_ptr(&self) -> *mut Self::VertStruct {
self.vert
}
fn vertices_len(&self) -> usize {
self.nvert.try_into().unwrap()
}
fn face_ptr(&self) -> *mut Self::FaceStruct {
self.faces
}
fn faces_len(&self) -> usize {
self.nfaces.try_into().unwrap()
}
fn normals_ptr(&self) -> Option<*mut Self::NormalStruct> {
None
}
fn normals_len(&self) -> usize {
0
}
unsafe fn free(&mut self) {
sys::ttf_free_mesh(&mut *self)
}
}
impl<'a> InnerMesh<'a> for Mesh3d {
type VertStruct = Vert3d;
type FaceStruct = Face3d;
type NormalStruct = Normal;
fn vert_ptr(&self) -> *mut Self::VertStruct {
self.vert
}
fn vertices_len(&self) -> usize {
self.nvert.try_into().unwrap()
}
fn face_ptr(&self) -> *mut Self::FaceStruct {
self.faces
}
fn faces_len(&self) -> usize {
self.nfaces.try_into().unwrap()
}
fn normals_ptr(&self) -> Option<*mut Self::NormalStruct> {
Some(self.normals)
}
fn normals_len(&self) -> usize {
self.nvert.try_into().unwrap()
}
unsafe fn free(&mut self) {
sys::ttf_free_mesh3d(&mut *self)
}
}
impl<'a, T: InnerMesh<'a>> Mesh<'a, T> {
pub(crate) fn from_raw(mesh: *mut T) -> Result<Self, Error> {
Ok(Mesh {
inner: mesh,
_phantom: &PhantomData,
})
}
pub fn iter_vertices(&'a self) -> DataIterator<'a, <T as InnerMesh>::VertStruct> {
let vertices =
unsafe { slice::from_raw_parts((&*self.inner).vert_ptr(), self.vertices_len()) };
DataIterator::new(vertices)
}
pub fn iter_faces<'b>(&'a self) -> DataIterator<'a, <T as InnerMesh>::FaceStruct> {
let faces = unsafe { slice::from_raw_parts((&*self.inner).face_ptr(), self.faces_len()) };
DataIterator::new(faces)
}
pub fn iter_normals<'b>(&'a self) -> Option<DataIterator<'a, <T as InnerMesh>::NormalStruct>> {
let ptr = match unsafe { &*self.inner }.normals_ptr() {
Some(ptr) => ptr,
None => return None,
};
let normals = unsafe { slice::from_raw_parts(ptr, self.normals_len()) };
Some(DataIterator::new(normals))
}
pub fn vertices_len(&self) -> usize {
unsafe { &*self.inner }.vertices_len()
}
pub fn faces_len(&self) -> usize {
unsafe { &*self.inner }.faces_len()
}
pub fn normals_len(&self) -> usize {
unsafe { &*self.inner }.normals_len()
}
}
impl<'a, T: InnerMesh<'a>> Drop for Mesh<'a, T> {
fn drop(&mut self) {
unsafe { (&mut *self.inner).free() }
}
}