From a99595c708b19caf6b01bd4c9eba1516dbb95ec4 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 17:18:15 +0300 Subject: [PATCH 01/46] Example text --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b5d8c7..e6de8cc 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ Add to `Cargo.toml`: ttf2mesh-rs = "0.0.1" ## Examples -TODO + +See [examples](/examples) -folder and crate docs. ## Development From b57ea251829d2ef7c78f1d9d879cd466578515e5 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 17:44:20 +0300 Subject: [PATCH 02/46] More documentation --- Cargo.toml | 2 +- examples/ttf2mesh.rs | 4 ++-- src/lib.rs | 28 +++++++++++++++++++++++++++- src/mesh.rs | 19 ++++++++++++++----- src/{outputs.rs => output.rs} | 22 +++++++++++++++++++--- src/ttf.rs | 18 ++++++++++-------- 6 files changed, 73 insertions(+), 20 deletions(-) rename src/{outputs.rs => output.rs} (68%) diff --git a/Cargo.toml b/Cargo.toml index 88dea2d..2263cd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.3" +version = "0.0.4" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" diff --git a/examples/ttf2mesh.rs b/examples/ttf2mesh.rs index 3a51b4b..1a2c323 100644 --- a/examples/ttf2mesh.rs +++ b/examples/ttf2mesh.rs @@ -54,7 +54,7 @@ fn main() { "- vertices: [{}]", mesh.iter_vertices() .map(|v| { - let v = v.value(); + let v = v.val(); format!("({:.3}, {:.2})", v.0, v.1) }) .collect::>() @@ -65,7 +65,7 @@ fn main() { "- faces: [{}]", mesh.iter_faces() .map(|v| { - let v = v.value(); + let v = v.val(); format!("({}, {}, {})", v.0, v.1, v.2) }) .collect::>() diff --git a/src/lib.rs b/src/lib.rs index 196fb82..84ebf90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,29 @@ +//! # Overview +//! +//! A high-level Rust wrapper API for [fetisov's ttf2mesh](https://github.com/fetisov/ttf2mesh/) +//! library for generating a 2d/3d mesh (vertices, indices and normals [only for 3D]) +//! from TrueType (`.ttf`) glyphs. +//! +//! Usage: +//! ```rust +//! # use ttf2mesh::{TTFFile, Quality}; +//! # +//! let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); +//! +//! // export all glyphs as 2d meshes to a .obj file +//! ttf.export_to_obj("/dev/null", Quality::Low).unwrap(); +//! +//! // generate 2d mesh for a glyph +//! let mut glyph = ttf.glyph_from_char('€').unwrap(); +//! let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); +//! +//! // work with Mesh vertices, faces (indices). See Mesh documentation for more +//! assert_eq!(mesh.vertices_len(), 56); +//! assert_eq!(mesh.iter_vertices().next().unwrap().val(), (0.555, 0.656)); +//! +//! assert_eq!(mesh.faces_len(), 54); +//! assert_eq!(mesh.iter_faces().next().unwrap().val(), (53, 52, 5)); +//! ``` #![feature(test)] extern crate test; @@ -6,7 +32,7 @@ use std::{ffi::CString, os::unix::prelude::OsStrExt, path::Path}; mod error; mod glyph; mod mesh; -mod outputs; +pub mod output; mod quality; mod ttf; diff --git a/src/mesh.rs b/src/mesh.rs index 6f5a93f..f347bd9 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -4,10 +4,13 @@ use std::{convert::TryInto, marker::PhantomData}; use ttf2mesh_sys as sys; use crate::{ - outputs::{IteratorValue, MeshIterator}, + output::{IteratorValue, MeshIterator}, Error, }; +#[allow(unused_imports)] +use crate::Glyph; + /// A (2d or 3d) mesh that has been generated from a [`Glyph`] /// /// Usage: @@ -19,21 +22,21 @@ use crate::{ /// /// // vertices with for-loop /// for vertex in mesh_3d.iter_vertices() { -/// let values: (f32, f32, f32) = vertex.value(); +/// let values: (f32, f32, f32) = vertex.val(); /// // do something /// } /// /// // or copying to a new vector /// let vertices = mesh_3d.iter_vertices() -/// .map(|v| v.value()) +/// .map(|v| v.val()) /// .collect::>(); /// /// let faces = mesh_3d.iter_faces() -/// .map(|v| v.value()) +/// .map(|v| v.val()) /// .collect::>(); /// /// let normals = mesh_3d.iter_normals().unwrap() -/// .map(|v| v.value()) +/// .map(|v| v.val()) /// .collect::>(); /// ``` pub struct Mesh<'a, T: MeshPointer<'a>> { @@ -135,6 +138,8 @@ impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { } /// Get an iterator of mesh vertices + /// + /// Produces `(x: f32, y: f32, z: f32)` tuples for 3d mesh and `(x: f32, y: f32)` tuples for 2d mesh pub fn iter_vertices(&'a self) -> MeshIterator<'a, ::VertStruct> { let vertices = unsafe { slice::from_raw_parts((&*self.inner).get_vert_ptr(), self.vertices_len()) }; @@ -143,6 +148,8 @@ impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { } /// Get an iterator of mesh faces (indices) + /// + /// Produces `(v1: i32, v2: i32, v3: i32)` tuples pub fn iter_faces<'b>(&'a self) -> MeshIterator<'a, ::FaceStruct> { let faces = unsafe { slice::from_raw_parts((&*self.inner).get_face_ptr(), self.faces_len()) }; @@ -151,6 +158,8 @@ impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { } /// Get an iterator of mesh normals. Only for 3d mesh, always None for 2d mesh + /// + /// Produces `(x: f32, y: f32, z: f32)` tuples for 3d mesh pub fn iter_normals<'b>( &'a self, ) -> Option::NormalStruct>> { diff --git a/src/outputs.rs b/src/output.rs similarity index 68% rename from src/outputs.rs rename to src/output.rs index e2e62c4..e6b28e0 100644 --- a/src/outputs.rs +++ b/src/output.rs @@ -1,3 +1,4 @@ +//! Entities for interacting with mesh-produced output (vertices, faces(indices) and normals) use std::fmt; use ttf2mesh_sys as sys; @@ -48,13 +49,27 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { } } +/// An iterator over an array of mesh values (separate output type for 2d vertices, 3d vertices, faces and normals) +/// +/// Usage: +/// ```rust +/// # use ttf2mesh::{TTFFile, Quality}; +/// # let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); +/// # let mut glyph = ttf.glyph_from_char('€').unwrap(); +/// # let mut mesh_2d = glyph.to_2d_mesh(Quality::Medium).unwrap(); +/// # +/// let vertices = mesh_2d.iter_vertices(); +/// for vertice in vertices { +/// let value: (f32, f32) = vertice.val(); +/// } +/// ``` pub struct MeshIterator<'a, T: IteratorValue<'a>> { index: usize, iterable: &'a [T], } impl<'a, T: IteratorValue<'a>> MeshIterator<'a, T> { - pub fn new(iterable: &'a [T]) -> Self { + pub(crate) fn new(iterable: &'a [T]) -> Self { Self { index: 0, iterable } } } @@ -74,18 +89,19 @@ impl<'a, T: IteratorValue<'a>> Iterator for MeshIterator<'a, T> { } } +/// Wrapper for an iterator value. Use [`Value::val`] to get inner value pub struct Value<'a, T> { inner: &'a T, } impl<'a, T: IteratorValue<'a>> Value<'a, T> { - pub fn value(&self) -> T::Output { + pub fn val(&self) -> T::Output { self.inner.value() } } impl<'a, T: IteratorValue<'a>> fmt::Debug for Value<'a, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Value {{ {:?} }}", self.value()) + write!(f, "Value {{ {:?} }}", self.val()) } } diff --git a/src/ttf.rs b/src/ttf.rs index 81c2f6c..d398172 100644 --- a/src/ttf.rs +++ b/src/ttf.rs @@ -6,20 +6,20 @@ use ttf2mesh_sys as sys; use crate::{path_to_cstring, Error, Glyph, Quality}; -/// A decoded TTF file instance +/// A decoded TTF file instance. Contains a list of [`Glyph`]'s /// /// Usage: /// ```rust /// # use ttf2mesh::{TTFFile, Quality}; -/// -/// // from a file +/// # +/// // initialize from a file /// let ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); /// -/// // from a buffer +/// // initialize from a buffer /// let my_vec = std::fs::read("./fonts/FiraMono-Medium.ttf").unwrap(); /// let mut ttf = TTFFile::from_buffer_vec(my_vec).unwrap(); /// -/// // how many fonts? +/// // get the decoded glyph count /// assert_eq!(ttf.glyph_count(), 1485); /// /// // export all glyphs as 2d meshes to a .obj file @@ -28,11 +28,13 @@ use crate::{path_to_cstring, Error, Glyph, Quality}; /// // generate 2d mesh for a glyph /// let mut glyph = ttf.glyph_from_char('€').unwrap(); /// let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); +/// +/// // work with Mesh vertices, faces (indices). See Mesh documentation for more /// assert_eq!(mesh.vertices_len(), 56); -/// assert_eq!(mesh.iter_vertices().next().unwrap().value(), (0.555, 0.656)); +/// assert_eq!(mesh.iter_vertices().next().unwrap().val(), (0.555, 0.656)); /// /// assert_eq!(mesh.faces_len(), 54); -/// assert_eq!(mesh.iter_faces().next().unwrap().value(), (53, 52, 5)); +/// assert_eq!(mesh.iter_faces().next().unwrap().val(), (53, 52, 5)); /// ``` pub struct TTFFile { ttf: *mut sys::ttf_file, @@ -118,7 +120,7 @@ impl TTFFile { unsafe { *self.ttf }.nglyphs.try_into().unwrap() } - /// Get a glyph by its index. See also [`glyph_from_char`] + /// Get a glyph by its index. See also [`TTFFile::glyph_from_char`] pub fn glyph_by_index<'a>(&'a mut self, index: usize) -> Result, Error> { let glyphs = unsafe { slice::from_raw_parts_mut((*self.ttf).glyphs, self.glyph_count()) }; From 3a6fabb92af2933284547cd5015dba5789c7e1bd Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 17:58:57 +0300 Subject: [PATCH 03/46] A few tags & security section --- Cargo.toml | 2 ++ README.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 2263cd2..927918c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,8 @@ description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" license = "MIT" readme = "README.md" +keywords = ["tessellation", "mesh", "3d", "2d", "truetype", "ttf", "glyphs"] +categories = ["multimedia", "api-bindings"] [dependencies] ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.0.1" } diff --git a/README.md b/README.md index e6de8cc..2eaa673 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ Add to `Cargo.toml`: See [examples](/examples) -folder and crate docs. +## Security + +The API surface (mainly `.ttf` loading) has been fuzzed with [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). Current findings have been reported upstream and being applied at build time. + +Still, be careful if planning to use this library for parsing untrusted fonts. + ## Development Install prequisites (see above). From c44c504a52fea31579e6b7a54289025b60998c2e Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 18:44:23 +0300 Subject: [PATCH 04/46] Public API simplification --- README.md | 6 ++---- src/glyph.rs | 9 ++++++--- src/lib.rs | 2 +- src/mesh.rs | 37 +++++++++++++++++++++++-------------- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2eaa673..1993062 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ -# ttf2mesh-rs   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] [![Lines of Code]][github] +# ttf2mesh-rs   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] [Build Status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh/test [actions]: https://github.com/blaind/ttf2mesh/actions?query=branch%3Amain [Latest Version]: https://img.shields.io/crates/v/ttf2mesh.svg [crates.io]: https://crates.io/crates/ttf2mesh -[Lines of Code]: https://tokei.rs/b1/github/blaind/ttf2mesh?category=code -[github]: https://github.com/blaind/ttf2mesh [Docs Version]: https://docs.rs/ttf2mesh/badge.svg [docs]: https://docs.rs/ttf2mesh @@ -21,7 +19,7 @@ Prequisites: Add to `Cargo.toml`: [dependencies] - ttf2mesh-rs = "0.0.1" + ttf2mesh-rs = "*" # change with latest version ## Examples diff --git a/src/glyph.rs b/src/glyph.rs index 303d9e6..6db60df 100644 --- a/src/glyph.rs +++ b/src/glyph.rs @@ -2,7 +2,10 @@ use std::{convert::TryInto, mem::MaybeUninit}; use ttf2mesh_sys as sys; -use crate::{mesh::Mesh, Error, Quality}; +use crate::{ + mesh::{Mesh, Mesh2d, Mesh3d}, + Error, Quality, +}; /// Represents a glyph in truetype font file. Can be converted to a 2d or 3d [`Mesh`] /// @@ -25,7 +28,7 @@ impl<'a> Glyph<'a> { } /// Generate a 2d mesh from the glyph with desired [`Quality`] - pub fn to_2d_mesh<'b>(&mut self, quality: Quality) -> Result, Error> { + pub fn to_2d_mesh<'b>(&mut self, quality: Quality) -> Result, Error> { let mut mesh = MaybeUninit::uninit(); let features = sys::TTF_FEATURES_DFLT; @@ -52,7 +55,7 @@ impl<'a> Glyph<'a> { &mut self, quality: Quality, depth: f32, - ) -> Result, Error> { + ) -> Result, Error> { let mut mesh = MaybeUninit::uninit(); let features = sys::TTF_FEATURES_DFLT; diff --git a/src/lib.rs b/src/lib.rs index 84ebf90..04e3711 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ mod ttf; pub use error::Error; pub use glyph::Glyph; -pub use mesh::Mesh; +pub use mesh::{Mesh, MeshPointer}; pub use quality::Quality; pub use ttf::TTFFile; diff --git a/src/mesh.rs b/src/mesh.rs index f347bd9..caebd8d 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -8,6 +8,15 @@ use crate::{ 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; @@ -58,13 +67,13 @@ pub trait MeshPointer<'a> { fn get_normals_ptr(&self) -> Option<*mut Self::NormalStruct>; fn get_normals_len(&self) -> usize; - fn free(&mut self); + unsafe fn free(&mut self); } -impl<'a> MeshPointer<'a> for sys::ttf_mesh { - type VertStruct = sys::ttf_mesh__bindgen_ty_1; - type FaceStruct = sys::ttf_mesh__bindgen_ty_2; - type NormalStruct = sys::ttf_mesh__bindgen_ty_2; +impl<'a> MeshPointer<'a> for Mesh2d { + type VertStruct = Vert2d; + type FaceStruct = Face2d; + type NormalStruct = Normal; fn get_vert_ptr(&self) -> *mut Self::VertStruct { self.vert @@ -90,15 +99,15 @@ impl<'a> MeshPointer<'a> for sys::ttf_mesh { 0 } - fn free(&mut self) { - unsafe { sys::ttf_free_mesh(&mut *self) } + unsafe fn free(&mut self) { + sys::ttf_free_mesh(&mut *self) } } -impl<'a> MeshPointer<'a> for sys::ttf_mesh3d { - type VertStruct = sys::ttf_mesh3d__bindgen_ty_1; - type FaceStruct = sys::ttf_mesh3d__bindgen_ty_2; - type NormalStruct = sys::ttf_mesh3d__bindgen_ty_3; +impl<'a> MeshPointer<'a> for Mesh3d { + type VertStruct = Vert3d; + type FaceStruct = Face3d; + type NormalStruct = Normal; fn get_vert_ptr(&self) -> *mut Self::VertStruct { self.vert @@ -124,8 +133,8 @@ impl<'a> MeshPointer<'a> for sys::ttf_mesh3d { self.nvert.try_into().unwrap() } - fn free(&mut self) { - unsafe { sys::ttf_free_mesh3d(&mut *self) } + unsafe fn free(&mut self) { + sys::ttf_free_mesh3d(&mut *self) } } @@ -191,6 +200,6 @@ impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { impl<'a, T: MeshPointer<'a>> Drop for Mesh<'a, T> { fn drop(&mut self) { - unsafe { &mut *self.inner }.free(); + unsafe { (&mut *self.inner).free() } } } From e384bb9dfeb0bfb838e0d22605511f3da2fd4793 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 19:04:53 +0300 Subject: [PATCH 05/46] API refactoring --- src/lib.rs | 2 +- src/mesh.rs | 86 +++++++++++++++++++++++++++------------------------ src/output.rs | 31 ++++++++++++------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 04e3711..84ebf90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ mod ttf; pub use error::Error; pub use glyph::Glyph; -pub use mesh::{Mesh, MeshPointer}; +pub use mesh::Mesh; pub use quality::Quality; pub use ttf::TTFFile; diff --git a/src/mesh.rs b/src/mesh.rs index caebd8d..971d353 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -4,7 +4,7 @@ use std::{convert::TryInto, marker::PhantomData}; use ttf2mesh_sys as sys; use crate::{ - output::{IteratorValue, MeshIterator}, + output::{DataIterator, IteratorValue}, Error, }; @@ -48,54 +48,61 @@ use crate::Glyph; /// .map(|v| v.val()) /// .collect::>(); /// ``` -pub struct Mesh<'a, T: MeshPointer<'a>> { +pub struct Mesh<'a, T: InnerMesh<'a>> { inner: *mut T, _phantom: &'a PhantomData, } -pub trait MeshPointer<'a> { +/// Representation of `ttf2mesh` internal mesh structure +/// +/// Do not use methods directly, but rather use [`IteratorValue`] methods +pub trait InnerMesh<'a> { + /// Value type for a vertices iterator type VertStruct: IteratorValue<'a>; + + /// Value type for a faces iterator type FaceStruct: IteratorValue<'a>; - type NormalStruct: IteratorValue<'a>; - fn get_vert_ptr(&self) -> *mut Self::VertStruct; - fn get_vert_len(&self) -> usize; + /// Value type for a normals iterator + type NormalStruct: IteratorValue<'a>; - fn get_face_ptr(&self) -> *mut Self::FaceStruct; - fn get_face_len(&self) -> usize; + fn vertices_len(&self) -> usize; + fn faces_len(&self) -> usize; + fn normals_len(&self) -> usize; - fn get_normals_ptr(&self) -> Option<*mut Self::NormalStruct>; - fn get_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> MeshPointer<'a> for Mesh2d { +impl<'a> InnerMesh<'a> for Mesh2d { type VertStruct = Vert2d; type FaceStruct = Face2d; type NormalStruct = Normal; - fn get_vert_ptr(&self) -> *mut Self::VertStruct { + fn vert_ptr(&self) -> *mut Self::VertStruct { self.vert } - fn get_vert_len(&self) -> usize { + fn vertices_len(&self) -> usize { self.nvert.try_into().unwrap() } - fn get_face_ptr(&self) -> *mut Self::FaceStruct { + fn face_ptr(&self) -> *mut Self::FaceStruct { self.faces } - fn get_face_len(&self) -> usize { + fn faces_len(&self) -> usize { self.nfaces.try_into().unwrap() } - fn get_normals_ptr(&self) -> Option<*mut Self::NormalStruct> { + fn normals_ptr(&self) -> Option<*mut Self::NormalStruct> { None } - fn get_normals_len(&self) -> usize { + fn normals_len(&self) -> usize { 0 } @@ -104,32 +111,32 @@ impl<'a> MeshPointer<'a> for Mesh2d { } } -impl<'a> MeshPointer<'a> for Mesh3d { +impl<'a> InnerMesh<'a> for Mesh3d { type VertStruct = Vert3d; type FaceStruct = Face3d; type NormalStruct = Normal; - fn get_vert_ptr(&self) -> *mut Self::VertStruct { + fn vert_ptr(&self) -> *mut Self::VertStruct { self.vert } - fn get_vert_len(&self) -> usize { + fn vertices_len(&self) -> usize { self.nvert.try_into().unwrap() } - fn get_face_ptr(&self) -> *mut Self::FaceStruct { + fn face_ptr(&self) -> *mut Self::FaceStruct { self.faces } - fn get_face_len(&self) -> usize { + fn faces_len(&self) -> usize { self.nfaces.try_into().unwrap() } - fn get_normals_ptr(&self) -> Option<*mut Self::NormalStruct> { + fn normals_ptr(&self) -> Option<*mut Self::NormalStruct> { Some(self.normals) } - fn get_normals_len(&self) -> usize { + fn normals_len(&self) -> usize { self.nvert.try_into().unwrap() } @@ -138,7 +145,7 @@ impl<'a> MeshPointer<'a> for Mesh3d { } } -impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { +impl<'a, T: InnerMesh<'a>> Mesh<'a, T> { pub(crate) fn from_raw(mesh: *mut T) -> Result { Ok(Mesh { inner: mesh, @@ -149,56 +156,53 @@ impl<'a, T: MeshPointer<'a>> Mesh<'a, T> { /// Get an iterator of mesh vertices /// /// Produces `(x: f32, y: f32, z: f32)` tuples for 3d mesh and `(x: f32, y: f32)` tuples for 2d mesh - pub fn iter_vertices(&'a self) -> MeshIterator<'a, ::VertStruct> { + pub fn iter_vertices(&'a self) -> DataIterator<'a, ::VertStruct> { let vertices = - unsafe { slice::from_raw_parts((&*self.inner).get_vert_ptr(), self.vertices_len()) }; + unsafe { slice::from_raw_parts((&*self.inner).vert_ptr(), self.vertices_len()) }; - MeshIterator::new(vertices) + DataIterator::new(vertices) } /// Get an iterator of mesh faces (indices) /// /// Produces `(v1: i32, v2: i32, v3: i32)` tuples - pub fn iter_faces<'b>(&'a self) -> MeshIterator<'a, ::FaceStruct> { - let faces = - unsafe { slice::from_raw_parts((&*self.inner).get_face_ptr(), self.faces_len()) }; + pub fn iter_faces<'b>(&'a self) -> DataIterator<'a, ::FaceStruct> { + let faces = unsafe { slice::from_raw_parts((&*self.inner).face_ptr(), self.faces_len()) }; - MeshIterator::new(faces) + DataIterator::new(faces) } /// Get an iterator of mesh normals. Only for 3d mesh, always None for 2d mesh /// /// Produces `(x: f32, y: f32, z: f32)` tuples for 3d mesh - pub fn iter_normals<'b>( - &'a self, - ) -> Option::NormalStruct>> { - let ptr = match unsafe { &*self.inner }.get_normals_ptr() { + pub fn iter_normals<'b>(&'a self) -> Option::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(MeshIterator::new(normals)) + Some(DataIterator::new(normals)) } /// Get the count of vertices pub fn vertices_len(&self) -> usize { - unsafe { &*self.inner }.get_vert_len() + unsafe { &*self.inner }.vertices_len() } /// Get the count of faces (indices) pub fn faces_len(&self) -> usize { - unsafe { &*self.inner }.get_face_len() + unsafe { &*self.inner }.faces_len() } /// Get the count of normals (always zero for 2d meshes) pub fn normals_len(&self) -> usize { - unsafe { &*self.inner }.get_normals_len() + unsafe { &*self.inner }.normals_len() } } -impl<'a, T: MeshPointer<'a>> Drop for Mesh<'a, T> { +impl<'a, T: InnerMesh<'a>> Drop for Mesh<'a, T> { fn drop(&mut self) { unsafe { (&mut *self.inner).free() } } diff --git a/src/output.rs b/src/output.rs index e6b28e0..c310e69 100644 --- a/src/output.rs +++ b/src/output.rs @@ -6,13 +6,13 @@ use ttf2mesh_sys as sys; pub trait IteratorValue<'a> { type Output: fmt::Debug; - fn value(&self) -> Self::Output; + fn val(&self) -> Self::Output; } impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_1 { type Output = (f32, f32); - fn value(&self) -> Self::Output { + fn val(&self) -> Self::Output { (self.x, self.y) } } @@ -20,7 +20,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_1 { impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_2 { type Output = (i32, i32, i32); - fn value(&self) -> Self::Output { + fn val(&self) -> Self::Output { (self.v1, self.v2, self.v3) } } @@ -28,7 +28,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_2 { impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_1 { type Output = (f32, f32, f32); - fn value(&self) -> Self::Output { + fn val(&self) -> Self::Output { (self.x, self.y, self.z) } } @@ -36,7 +36,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_1 { impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_2 { type Output = (i32, i32, i32); - fn value(&self) -> Self::Output { + fn val(&self) -> Self::Output { (self.v1, self.v2, self.v3) } } @@ -44,14 +44,22 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_2 { impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { type Output = (f32, f32, f32); - fn value(&self) -> Self::Output { + fn val(&self) -> Self::Output { (self.x, self.y, self.z) } } /// An iterator over an array of mesh values (separate output type for 2d vertices, 3d vertices, faces and normals) /// -/// Usage: +/// Produces [`IteratorValue`]'s, where internal value can be accessed by `.val()` method. +/// +/// Values produced by `.val()` depend on the mesh & data type: +/// * 2d vertices: `(f32, f32)` which represent x, y +/// * 3d vertices: `(f32, f32, f32)` which represent x, y, z +/// * indices (both 2d & 3d): `(i32, i32, i32)` +/// * normals (only for 3d): `(f32, f32, f32)` +/// +/// Example: /// ```rust /// # use ttf2mesh::{TTFFile, Quality}; /// # let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); @@ -63,18 +71,18 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { /// let value: (f32, f32) = vertice.val(); /// } /// ``` -pub struct MeshIterator<'a, T: IteratorValue<'a>> { +pub struct DataIterator<'a, T: IteratorValue<'a>> { index: usize, iterable: &'a [T], } -impl<'a, T: IteratorValue<'a>> MeshIterator<'a, T> { +impl<'a, T: IteratorValue<'a>> DataIterator<'a, T> { pub(crate) fn new(iterable: &'a [T]) -> Self { Self { index: 0, iterable } } } -impl<'a, T: IteratorValue<'a>> Iterator for MeshIterator<'a, T> { +impl<'a, T: IteratorValue<'a>> Iterator for DataIterator<'a, T> { type Item = Value<'a, T>; fn next(&mut self) -> Option { @@ -95,8 +103,9 @@ pub struct Value<'a, T> { } impl<'a, T: IteratorValue<'a>> Value<'a, T> { + /// Get the internal value. See [`DataIterator`] for value types pub fn val(&self) -> T::Output { - self.inner.value() + self.inner.val() } } From ff161972c68d313be85b3b50973b68f7c9c9495d Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 19:14:09 +0300 Subject: [PATCH 06/46] API simplification & docs --- examples/ttf2mesh.rs | 1 + src/lib.rs | 5 +++-- src/mesh.rs | 23 +++++++------------- src/output.rs | 51 +++++++++++++++++--------------------------- src/ttf.rs | 2 +- 5 files changed, 33 insertions(+), 49 deletions(-) diff --git a/examples/ttf2mesh.rs b/examples/ttf2mesh.rs index 1a2c323..536f70c 100644 --- a/examples/ttf2mesh.rs +++ b/examples/ttf2mesh.rs @@ -1,4 +1,5 @@ use std::env; +use ttf2mesh::Value; /// Output 2d mesh data from a glyph in an input .ttf file fn main() { diff --git a/src/lib.rs b/src/lib.rs index 84ebf90..59099d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ //! //! Usage: //! ```rust -//! # use ttf2mesh::{TTFFile, Quality}; +//! # use ttf2mesh::{TTFFile, Quality, Value}; //! # //! let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); //! @@ -32,13 +32,14 @@ use std::{ffi::CString, os::unix::prelude::OsStrExt, path::Path}; mod error; mod glyph; mod mesh; -pub mod output; +mod output; mod quality; mod ttf; pub use error::Error; pub use glyph::Glyph; pub use mesh::Mesh; +pub use output::{DataIterator, Value}; pub use quality::Quality; pub use ttf::TTFFile; diff --git a/src/mesh.rs b/src/mesh.rs index 971d353..606caab 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -4,7 +4,7 @@ use std::{convert::TryInto, marker::PhantomData}; use ttf2mesh_sys as sys; use crate::{ - output::{DataIterator, IteratorValue}, + output::{DataIterator, Value}, Error, }; @@ -24,19 +24,12 @@ use crate::Glyph; /// /// Usage: /// ```rust -/// # use ttf2mesh::{TTFFile, Quality}; +/// # use ttf2mesh::{TTFFile, Quality, Value}; /// # let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); /// # let mut glyph = ttf.glyph_from_char('€').unwrap(); /// # let mesh_3d = glyph.to_3d_mesh(Quality::Medium, 2.).unwrap(); -/// -/// // vertices with for-loop -/// for vertex in mesh_3d.iter_vertices() { -/// let values: (f32, f32, f32) = vertex.val(); -/// // do something -/// } -/// -/// // or copying to a new vector -/// let vertices = mesh_3d.iter_vertices() +/// # +/// let vertices_3d = mesh_3d.iter_vertices() /// .map(|v| v.val()) /// .collect::>(); /// @@ -55,16 +48,16 @@ pub struct Mesh<'a, T: InnerMesh<'a>> { /// Representation of `ttf2mesh` internal mesh structure /// -/// Do not use methods directly, but rather use [`IteratorValue`] methods +/// Do not use methods directly, but rather use [`Value`] methods pub trait InnerMesh<'a> { /// Value type for a vertices iterator - type VertStruct: IteratorValue<'a>; + type VertStruct: Value<'a>; /// Value type for a faces iterator - type FaceStruct: IteratorValue<'a>; + type FaceStruct: Value<'a>; /// Value type for a normals iterator - type NormalStruct: IteratorValue<'a>; + type NormalStruct: Value<'a>; fn vertices_len(&self) -> usize; fn faces_len(&self) -> usize; diff --git a/src/output.rs b/src/output.rs index c310e69..f8d43f3 100644 --- a/src/output.rs +++ b/src/output.rs @@ -3,13 +3,20 @@ use std::fmt; use ttf2mesh_sys as sys; -pub trait IteratorValue<'a> { +/// Value produced by a mesh data iterator. Access with `.val()` +/// +/// Values produced by `.val()` depend on the mesh & data type: +/// * 2d vertices: `(f32, f32)` which represent x, y +/// * 3d vertices: `(f32, f32, f32)` which represent x, y, z +/// * indices (both 2d & 3d): `(i32, i32, i32)` +/// * normals (only for 3d): `(f32, f32, f32)` +pub trait Value<'a> { type Output: fmt::Debug; fn val(&self) -> Self::Output; } -impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_1 { +impl<'a> Value<'a> for sys::ttf_mesh__bindgen_ty_1 { type Output = (f32, f32); fn val(&self) -> Self::Output { @@ -17,7 +24,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_1 { } } -impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_2 { +impl<'a> Value<'a> for sys::ttf_mesh__bindgen_ty_2 { type Output = (i32, i32, i32); fn val(&self) -> Self::Output { @@ -25,7 +32,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh__bindgen_ty_2 { } } -impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_1 { +impl<'a> Value<'a> for sys::ttf_mesh3d__bindgen_ty_1 { type Output = (f32, f32, f32); fn val(&self) -> Self::Output { @@ -33,7 +40,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_1 { } } -impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_2 { +impl<'a> Value<'a> for sys::ttf_mesh3d__bindgen_ty_2 { type Output = (i32, i32, i32); fn val(&self) -> Self::Output { @@ -41,7 +48,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_2 { } } -impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { +impl<'a> Value<'a> for sys::ttf_mesh3d__bindgen_ty_3 { type Output = (f32, f32, f32); fn val(&self) -> Self::Output { @@ -51,7 +58,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { /// An iterator over an array of mesh values (separate output type for 2d vertices, 3d vertices, faces and normals) /// -/// Produces [`IteratorValue`]'s, where internal value can be accessed by `.val()` method. +/// Produces [`Value`]'s, where internal value can be accessed by `.val()` method. /// /// Values produced by `.val()` depend on the mesh & data type: /// * 2d vertices: `(f32, f32)` which represent x, y @@ -61,7 +68,7 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { /// /// Example: /// ```rust -/// # use ttf2mesh::{TTFFile, Quality}; +/// # use ttf2mesh::{TTFFile, Quality, Value}; /// # let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); /// # let mut glyph = ttf.glyph_from_char('€').unwrap(); /// # let mut mesh_2d = glyph.to_2d_mesh(Quality::Medium).unwrap(); @@ -71,46 +78,28 @@ impl<'a> IteratorValue<'a> for sys::ttf_mesh3d__bindgen_ty_3 { /// let value: (f32, f32) = vertice.val(); /// } /// ``` -pub struct DataIterator<'a, T: IteratorValue<'a>> { +pub struct DataIterator<'a, T: Value<'a>> { index: usize, iterable: &'a [T], } -impl<'a, T: IteratorValue<'a>> DataIterator<'a, T> { +impl<'a, T: Value<'a>> DataIterator<'a, T> { pub(crate) fn new(iterable: &'a [T]) -> Self { Self { index: 0, iterable } } } -impl<'a, T: IteratorValue<'a>> Iterator for DataIterator<'a, T> { - type Item = Value<'a, T>; +impl<'a, T: Value<'a>> Iterator for DataIterator<'a, T> { + type Item = &'a T; fn next(&mut self) -> Option { match self.iterable.get(self.index) { Some(item) => { self.index += 1; - Some(Value { inner: item }) + Some(item) } None => None, } } } - -/// Wrapper for an iterator value. Use [`Value::val`] to get inner value -pub struct Value<'a, T> { - inner: &'a T, -} - -impl<'a, T: IteratorValue<'a>> Value<'a, T> { - /// Get the internal value. See [`DataIterator`] for value types - pub fn val(&self) -> T::Output { - self.inner.val() - } -} - -impl<'a, T: IteratorValue<'a>> fmt::Debug for Value<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Value {{ {:?} }}", self.val()) - } -} diff --git a/src/ttf.rs b/src/ttf.rs index d398172..972842e 100644 --- a/src/ttf.rs +++ b/src/ttf.rs @@ -10,7 +10,7 @@ use crate::{path_to_cstring, Error, Glyph, Quality}; /// /// Usage: /// ```rust -/// # use ttf2mesh::{TTFFile, Quality}; +/// # use ttf2mesh::{TTFFile, Quality, Value}; /// # /// // initialize from a file /// let ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); From 6d271f6e8f997044cd8182a3f131b04c431f94a1 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 19:20:03 +0300 Subject: [PATCH 07/46] More documentation --- src/lib.rs | 17 ++++++++++------- src/mesh.rs | 4 ++++ src/ttf.rs | 15 +++++++++------ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 59099d1..881ead5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ //! //! Usage: //! ```rust -//! # use ttf2mesh::{TTFFile, Quality, Value}; +//! # use ttf2mesh::{TTFFile, Quality, Value, Mesh, Mesh2d, Mesh3d}; //! # //! let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); //! @@ -15,14 +15,17 @@ //! //! // generate 2d mesh for a glyph //! let mut glyph = ttf.glyph_from_char('€').unwrap(); -//! let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); +//! let mesh_2d: Mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); //! //! // work with Mesh vertices, faces (indices). See Mesh documentation for more -//! assert_eq!(mesh.vertices_len(), 56); -//! assert_eq!(mesh.iter_vertices().next().unwrap().val(), (0.555, 0.656)); +//! assert_eq!(mesh_2d.vertices_len(), 56); +//! assert_eq!(mesh_2d.iter_vertices().next().unwrap().val(), (0.555, 0.656)); //! -//! assert_eq!(mesh.faces_len(), 54); -//! assert_eq!(mesh.iter_faces().next().unwrap().val(), (53, 52, 5)); +//! assert_eq!(mesh_2d.faces_len(), 54); +//! assert_eq!(mesh_2d.iter_faces().next().unwrap().val(), (53, 52, 5)); +//! +//! // 3d mesh with depth of 0.5 +//! let mesh_3d: Mesh = glyph.to_3d_mesh(Quality::Medium, 0.5).unwrap(); //! ``` #![feature(test)] extern crate test; @@ -38,7 +41,7 @@ mod ttf; pub use error::Error; pub use glyph::Glyph; -pub use mesh::Mesh; +pub use mesh::{Mesh, Mesh2d, Mesh3d}; pub use output::{DataIterator, Value}; pub use quality::Quality; pub use ttf::TTFFile; diff --git a/src/mesh.rs b/src/mesh.rs index 606caab..2ef4440 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,3 +1,4 @@ +//! Mesh -related structures use core::slice; use std::{convert::TryInto, marker::PhantomData}; @@ -8,7 +9,10 @@ use crate::{ Error, }; +/// Type for 3d mesh data pub type Mesh3d = ttf2mesh_sys::ttf_mesh3d; + +/// Type for 2d mesh data pub type Mesh2d = ttf2mesh_sys::ttf_mesh; type Vert2d = sys::ttf_mesh__bindgen_ty_1; diff --git a/src/ttf.rs b/src/ttf.rs index 972842e..01f76b3 100644 --- a/src/ttf.rs +++ b/src/ttf.rs @@ -10,7 +10,7 @@ use crate::{path_to_cstring, Error, Glyph, Quality}; /// /// Usage: /// ```rust -/// # use ttf2mesh::{TTFFile, Quality, Value}; +/// # use ttf2mesh::{TTFFile, Quality, Value, Mesh, Mesh2d, Mesh3d}; /// # /// // initialize from a file /// let ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); @@ -27,14 +27,17 @@ use crate::{path_to_cstring, Error, Glyph, Quality}; /// /// // generate 2d mesh for a glyph /// let mut glyph = ttf.glyph_from_char('€').unwrap(); -/// let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); +/// let mesh_2d: Mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); /// /// // work with Mesh vertices, faces (indices). See Mesh documentation for more -/// assert_eq!(mesh.vertices_len(), 56); -/// assert_eq!(mesh.iter_vertices().next().unwrap().val(), (0.555, 0.656)); +/// assert_eq!(mesh_2d.vertices_len(), 56); +/// assert_eq!(mesh_2d.iter_vertices().next().unwrap().val(), (0.555, 0.656)); /// -/// assert_eq!(mesh.faces_len(), 54); -/// assert_eq!(mesh.iter_faces().next().unwrap().val(), (53, 52, 5)); +/// assert_eq!(mesh_2d.faces_len(), 54); +/// assert_eq!(mesh_2d.iter_faces().next().unwrap().val(), (53, 52, 5)); +/// +/// // 3d mesh with depth of 0.5 +/// let mesh_3d: Mesh = glyph.to_3d_mesh(Quality::Medium, 0.5).unwrap(); /// ``` pub struct TTFFile { ttf: *mut sys::ttf_file, From 80be06809ebcba4f09a06529d96b49a2e7a53916 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 19:20:21 +0300 Subject: [PATCH 08/46] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 927918c..400cd79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.4" +version = "0.0.5" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 70d346fbff2428a2ca34e8e67c8c064362f3dc71 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 19:21:33 +0300 Subject: [PATCH 09/46] Reduce keywords --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 400cd79..d289e32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" license = "MIT" readme = "README.md" -keywords = ["tessellation", "mesh", "3d", "2d", "truetype", "ttf", "glyphs"] +keywords = ["tessellation", "mesh", "3d", "truetype", "ttf"] categories = ["multimedia", "api-bindings"] [dependencies] From f1078e5794917c124e9251f8c886439766a76921 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sat, 31 Jul 2021 20:05:14 +0300 Subject: [PATCH 10/46] Chars fix --- src/lib.rs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 881ead5..87b113a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,14 +87,13 @@ mod tests { #[test] fn test_get_glyph_from_char() { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - let char = "A".chars().next().unwrap(); - let _ = font.glyph_from_char(char).unwrap(); + let _ = font.glyph_from_char('A').unwrap(); } #[test] fn test_to_3d_mesh() { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - let mut glyph = font.glyph_from_char("€".chars().next().unwrap()).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); let mesh = glyph.to_3d_mesh(Quality::Low, 0.5).unwrap(); let mut sizes = Vec::new(); @@ -126,7 +125,7 @@ mod tests { #[test] fn test_to_2d_mesh() { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - let mut glyph = font.glyph_from_char("€".chars().next().unwrap()).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); let mut sizes = Vec::new(); let mesh = glyph.to_2d_mesh(Quality::Low).unwrap(); @@ -163,19 +162,16 @@ mod tests { #[bench] fn bench_get_glyph(b: &mut Bencher) { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - let char = "€".chars().next().unwrap(); b.iter(|| { - let _ = font.glyph_from_char(char).unwrap(); + let _ = font.glyph_from_char('€').unwrap(); }); } #[bench] fn bench_glyph_to_3d_mesh_low_quality(b: &mut Bencher) { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - - let char = "€".chars().next().unwrap(); - let mut glyph = font.glyph_from_char(char).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { let _ = glyph.to_3d_mesh(Quality::Low, 0.1).unwrap(); @@ -185,9 +181,7 @@ mod tests { #[bench] fn bench_glyph_to_3d_mesh_high_quality(b: &mut Bencher) { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - - let char = "€".chars().next().unwrap(); - let mut glyph = font.glyph_from_char(char).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { let _ = glyph.to_3d_mesh(Quality::High, 0.1).unwrap(); @@ -197,9 +191,7 @@ mod tests { #[bench] fn bench_glyph_to_2d_mesh_low_quality(b: &mut Bencher) { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - - let char = "€".chars().next().unwrap(); - let mut glyph = font.glyph_from_char(char).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { let _ = glyph.to_2d_mesh(Quality::Low).unwrap(); @@ -209,9 +201,7 @@ mod tests { #[bench] fn bench_glyph_to_2d_mesh_high_quality(b: &mut Bencher) { let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); - - let char = "€".chars().next().unwrap(); - let mut glyph = font.glyph_from_char(char).unwrap(); + let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { let _ = glyph.to_2d_mesh(Quality::High).unwrap(); From 9d72de18903313f33649a531ce70818ba23555dc Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 18:36:30 +0300 Subject: [PATCH 11/46] Add github actions --- .github/workflows/test.yml | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..105bd0f --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: test + +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Install dependencies + run: sudo apt-get install gcc patch libudev-dev + + - uses: actions/checkout@v2 + + - name: Cache Cargo registry + uses: actions/cache@v2 + with: + path: ~/.cargo/registry + key: ${{ matrix.build }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ matrix.build }}-cargo-registry- + + - name: Cache Cargo index + uses: actions/cache@v2 + with: + path: ~/.cargo/git + key: ${{ matrix.build }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ matrix.build }}-cargo-index- + + - name: Cache Cargo build + uses: actions/cache@v2 + with: + path: target + key: ${{ matrix.build }}-target-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ matrix.build }}-target- + + - name: Run tests + run: cargo test --verbose From 2baeedf6854663a77a5dd4359d99111ab777449f Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 18:39:57 +0300 Subject: [PATCH 12/46] Fix workflow --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 105bd0f..5bc688e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,10 @@ jobs: steps: - name: Install dependencies - run: sudo apt-get install gcc patch libudev-dev + run: sudo apt-get install gcc patch libudev-dev git + + - name: Init submodules + run: git submodule update --init - uses: actions/checkout@v2 From 5dedc873968fd17ec7e2d3906f07e887d356a59f Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 18:45:10 +0300 Subject: [PATCH 13/46] Add debug for TTFFont, try github actions fix, update patch to include newest fixes --- .github/workflows/test.yml | 4 +-- src/ttf.rs | 6 +++++ ttf2mesh-sys/ttf2mesh-fix.patch | 43 ++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5bc688e..8031846 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,11 +13,11 @@ jobs: - name: Install dependencies run: sudo apt-get install gcc patch libudev-dev git + - uses: actions/checkout@v2 + - name: Init submodules run: git submodule update --init - - uses: actions/checkout@v2 - - name: Cache Cargo registry uses: actions/cache@v2 with: diff --git a/src/ttf.rs b/src/ttf.rs index 01f76b3..995dc8c 100644 --- a/src/ttf.rs +++ b/src/ttf.rs @@ -43,6 +43,12 @@ pub struct TTFFile { ttf: *mut sys::ttf_file, } +impl std::fmt::Debug for TTFFile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "TTFFile<>") + } +} + impl TTFFile { /// Load TTF font from a memory buffer /// diff --git a/ttf2mesh-sys/ttf2mesh-fix.patch b/ttf2mesh-sys/ttf2mesh-fix.patch index 7fab431..47c5cb3 100644 --- a/ttf2mesh-sys/ttf2mesh-fix.patch +++ b/ttf2mesh-sys/ttf2mesh-fix.patch @@ -1,5 +1,5 @@ diff --git a/ttf2mesh.c b/ttf2mesh.c -index abf85ec..ea7fe26 100644 +index abf85ec..26f1814 100644 --- a/ttf2mesh.c +++ b/ttf2mesh.c @@ -56,6 +56,7 @@ @@ -10,7 +10,7 @@ index abf85ec..ea7fe26 100644 /* Big/little endian definitions */ #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) -@@ -676,12 +677,17 @@ int parse_simple_glyph(ttf_glyph_t *glyph, int glyph_index, uint8_t *p, int avai +@@ -676,12 +677,19 @@ int parse_simple_glyph(ttf_glyph_t *glyph, int glyph_index, uint8_t *p, int avai j = 0; n = -1; @@ -18,17 +18,42 @@ index abf85ec..ea7fe26 100644 for (i = 0; i < glyph->ncontours; i++) { j = (int)big16toh(endPtsOfContours[i]); - glyph->outline->cont[i].length = j - n; +- glyph->outline->cont[i].length = j - n; ++ ++ int length = j - n; ++ npoints_remaining -= length; ++ if (length < 0 || npoints_remaining < 0) return TTF_ERR_FMT; ++ ++ glyph->outline->cont[i].length = length; glyph->outline->cont[i].subglyph_id = glyph_index; glyph->outline->cont[i].subglyph_order = 0; -+ -+ npoints_remaining -= glyph->outline->cont[i].length; -+ if (npoints_remaining < 0) return TTF_ERR_FMT; + if (i != glyph->ncontours - 1) glyph->outline->cont[i + 1].pt = glyph->outline->cont[i].pt + j - n; n = j; -@@ -1151,11 +1157,15 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) +@@ -913,6 +921,7 @@ int parse_composite_glyph(ttf_t *ttf, ttf_glyph_t *glyph, uint8_t *p, int avail) + + /* initialize outline */ + glyph->outline = allocate_ttf_outline(glyph->ncontours, glyph->npoints); ++ int npoints_remaining = glyph->npoints; + if (glyph->outline == NULL) return TTF_ERR_NOMEM; + + /* initialize other glyph fields */ +@@ -985,7 +994,12 @@ int parse_composite_glyph(ttf_t *ttf, ttf_glyph_t *glyph, uint8_t *p, int avail) + for (i = 0; i < ttf->glyphs[glyphIndex].ncontours; i++) + { + glyph->outline->cont[n].pt = curr; +- glyph->outline->cont[n].length = ttf->glyphs[glyphIndex].outline->cont[i].length; ++ ++ int length = ttf->glyphs[glyphIndex].outline->cont[i].length; ++ npoints_remaining -= length; ++ if (length < 0 || npoints_remaining < 0) return TTF_ERR_FMT; ++ ++ glyph->outline->cont[n].length = length; + glyph->outline->cont[n].subglyph_id = glyphIndex; + glyph->outline->cont[n].subglyph_order = nglyphs; + for (j = 0; j < glyph->outline->cont[n].length; j++) +@@ -1151,11 +1165,15 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) rec = (ttf_tab_rec_t *)(s->hdr + 1); #define check_tag(str) (*(uint32_t *)rec->tableTag != *(uint32_t *)str) @@ -48,7 +73,7 @@ index abf85ec..ea7fe26 100644 } while (ntab--) -@@ -1163,6 +1173,7 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) +@@ -1163,6 +1181,7 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) conv32(rec->checkSum); conv32(rec->offset); conv32(rec->length); @@ -56,7 +81,7 @@ index abf85ec..ea7fe26 100644 if (rec->offset + rec->length > (unsigned)size) return TTF_ERR_FMT; if (check_tag("head")) if (ttf_checksum(data + rec->offset, rec->length) != rec->checkSum) -@@ -1314,7 +1325,7 @@ static int locate_fmt4_table(pps_t *s) +@@ -1314,7 +1333,7 @@ static int locate_fmt4_table(pps_t *s) for (i = 0; i < ntab; i++) { int offset = big32toh(s->pcmap->encRecs[i].offset); From 6e2a4bd9efef3310ecaf7460344fddba2f645af1 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 18:53:53 +0300 Subject: [PATCH 14/46] Separate benchmarks (allow compiling on rust stable) --- .github/workflows/test.yml | 4 ++++ Cargo.toml | 4 ++++ src/lib.rs | 26 ++++++++++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8031846..5201b62 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,10 @@ env: jobs: test: runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + rust: [stable, nightly] steps: - name: Install dependencies diff --git a/Cargo.toml b/Cargo.toml index d289e32..d113a1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,7 @@ ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.0.1" } [workspace] members = ["ttf2mesh-sys"] + +[features] +default = [] +unstable = [] diff --git a/src/lib.rs b/src/lib.rs index 87b113a..8f5c26d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,8 +27,7 @@ //! // 3d mesh with depth of 0.5 //! let mesh_3d: Mesh = glyph.to_3d_mesh(Quality::Medium, 0.5).unwrap(); //! ``` -#![feature(test)] -extern crate test; +#![cfg_attr(feature = "unstable", feature(test))] use std::{ffi::CString, os::unix::prelude::OsStrExt, path::Path}; @@ -57,7 +56,6 @@ mod tests { use std::path::PathBuf; use super::*; - use test::Bencher; fn get_font_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fonts") @@ -70,7 +68,7 @@ mod tests { } } - fn read_font(font_file: Option<&str>) -> Vec { + pub(crate) fn read_font(font_file: Option<&str>) -> Vec { std::fs::read(get_font(font_file)).unwrap() } @@ -149,10 +147,18 @@ mod tests { assert_eq!(sizes, &[41, 39, 92, 90, 194, 192]); } +} + +#[cfg(all(feature = "unstable", test))] +mod bench { + extern crate test; + + use super::*; + use test::Bencher; #[bench] fn bench_open_font(b: &mut Bencher) { - let buffer = read_font(None); + let buffer = tests::read_font(None); b.iter(|| { let _ = TTFFile::from_buffer_vec(buffer.clone()).unwrap(); @@ -161,7 +167,7 @@ mod tests { #[bench] fn bench_get_glyph(b: &mut Bencher) { - let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); + let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap(); b.iter(|| { let _ = font.glyph_from_char('€').unwrap(); @@ -170,7 +176,7 @@ mod tests { #[bench] fn bench_glyph_to_3d_mesh_low_quality(b: &mut Bencher) { - let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); + let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap(); let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { @@ -180,7 +186,7 @@ mod tests { #[bench] fn bench_glyph_to_3d_mesh_high_quality(b: &mut Bencher) { - let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); + let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap(); let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { @@ -190,7 +196,7 @@ mod tests { #[bench] fn bench_glyph_to_2d_mesh_low_quality(b: &mut Bencher) { - let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); + let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap(); let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { @@ -200,7 +206,7 @@ mod tests { #[bench] fn bench_glyph_to_2d_mesh_high_quality(b: &mut Bencher) { - let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap(); + let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap(); let mut glyph = font.glyph_from_char('€').unwrap(); b.iter(|| { From 13695cfa61c74f7bbc5125ec58cc986b2b66d83d Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 18:58:08 +0300 Subject: [PATCH 15/46] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d113a1a..571e327 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.5" +version = "0.0.6" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 962f9292618725a35e480c69afa002b1da8e4c59 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 2 Aug 2021 19:00:14 +0300 Subject: [PATCH 16/46] Fix build status --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 571e327..47cb6c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.6" +version = "0.0.7" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" diff --git a/README.md b/README.md index 1993062..ac8ddaf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ttf2mesh-rs   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] -[Build Status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh/test +[Build Status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh-rs/test [actions]: https://github.com/blaind/ttf2mesh/actions?query=branch%3Amain [Latest Version]: https://img.shields.io/crates/v/ttf2mesh.svg [crates.io]: https://crates.io/crates/ttf2mesh From 79e66aec2b1478024d3858645af98d4f7e1ee9dc Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Thu, 5 Aug 2021 18:49:50 +0300 Subject: [PATCH 17/46] Fix overflow --- ttf2mesh-sys/ttf2mesh-fix.patch | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ttf2mesh-sys/ttf2mesh-fix.patch b/ttf2mesh-sys/ttf2mesh-fix.patch index 47c5cb3..d439ad8 100644 --- a/ttf2mesh-sys/ttf2mesh-fix.patch +++ b/ttf2mesh-sys/ttf2mesh-fix.patch @@ -1,5 +1,5 @@ diff --git a/ttf2mesh.c b/ttf2mesh.c -index abf85ec..26f1814 100644 +index abf85ec..bf77745 100644 --- a/ttf2mesh.c +++ b/ttf2mesh.c @@ -56,6 +56,7 @@ @@ -53,7 +53,18 @@ index abf85ec..26f1814 100644 glyph->outline->cont[n].subglyph_id = glyphIndex; glyph->outline->cont[n].subglyph_order = nglyphs; for (j = 0; j < glyph->outline->cont[n].length; j++) -@@ -1151,11 +1165,15 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) +@@ -1044,6 +1058,10 @@ int parse_glyf_table(ttf_t *ttf, pps_t *pp) + { + offset = pp->ploca16 ? pp->ploca16[i] * 2 : pp->ploca32[i]; + if (offset == pp->sglyf) continue; ++ ++ if (offset + (int)sizeof(ttf_glyfh_t) > pp->sglyf) ++ return TTF_ERR_FMT; ++ + hdr = (ttf_glyfh_t *)(pp->pglyf + offset); + if ((int16_t)big16toh(hdr->numberOfContours) >= 0) continue; + result = parse_composite_glyph(ttf, ttf->glyphs + i, pp->pglyf + offset, pp->sglyf - offset); +@@ -1151,11 +1169,15 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) rec = (ttf_tab_rec_t *)(s->hdr + 1); #define check_tag(str) (*(uint32_t *)rec->tableTag != *(uint32_t *)str) @@ -73,7 +84,7 @@ index abf85ec..26f1814 100644 } while (ntab--) -@@ -1163,6 +1181,7 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) +@@ -1163,6 +1185,7 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) conv32(rec->checkSum); conv32(rec->offset); conv32(rec->length); @@ -81,7 +92,7 @@ index abf85ec..26f1814 100644 if (rec->offset + rec->length > (unsigned)size) return TTF_ERR_FMT; if (check_tag("head")) if (ttf_checksum(data + rec->offset, rec->length) != rec->checkSum) -@@ -1314,7 +1333,7 @@ static int locate_fmt4_table(pps_t *s) +@@ -1314,7 +1337,7 @@ static int locate_fmt4_table(pps_t *s) for (i = 0; i < ntab; i++) { int offset = big32toh(s->pcmap->encRecs[i].offset); From c1fe6f6dd1aa732ddcd3f849be1ffc4d61839183 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Thu, 5 Aug 2021 18:50:44 +0300 Subject: [PATCH 18/46] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 47cb6c4..be1e940 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.7" +version = "0.0.8" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 83662e2e80d6d9b8395563e852fdaff53195bf2c Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 8 Aug 2021 21:16:17 +0300 Subject: [PATCH 19/46] Compilation warning + unicode printing --- examples/ttf2check.rs | 3 ++- ttf2mesh-sys/build.rs | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/ttf2check.rs b/examples/ttf2check.rs index 8732716..53dec49 100644 --- a/examples/ttf2check.rs +++ b/examples/ttf2check.rs @@ -24,8 +24,9 @@ fn main() { println!("Input string: {:?}", utf8_string); for char in utf8_string.chars() { println!( - "- {} = {}", + "- {} ({}) = {}", char, + char.escape_unicode(), match font.glyph_from_char(char) { Ok(mut glyph) => { let len2dvert = match glyph.to_2d_mesh(ttf2mesh::Quality::Medium) { diff --git a/ttf2mesh-sys/build.rs b/ttf2mesh-sys/build.rs index d2dee5c..7d38b04 100644 --- a/ttf2mesh-sys/build.rs +++ b/ttf2mesh-sys/build.rs @@ -8,6 +8,13 @@ fn main() { println!("cargo:rerun-if-changed=ttf2mesh/ttf2mesh.c"); println!("cargo:rustc-link-lib=m"); + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + // check that submodule has been initialized + if !manifest_dir.join("ttf2mesh/ttf2mesh.h").is_file() { + panic!("ttf2mesh.h not found - have you initialized the submodule? (`git submodule update --init`)"); + } + let bindings = bindgen::Builder::default() .header("wrapper.h") .parse_callbacks(Box::new(bindgen::CargoCallbacks)) @@ -19,7 +26,6 @@ fn main() { .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let patch_path = manifest_dir.join("ttf2mesh-fix.patch"); let patch_file = std::fs::File::open(patch_path).unwrap(); From d504500e3836ed831de881ae7ed00288a99e8adf Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 8 Aug 2021 21:29:01 +0300 Subject: [PATCH 20/46] Update to latest ttf2mesh --- README.md | 4 +- ttf2mesh-sys/README.md | 8 --- ttf2mesh-sys/build.rs | 2 + ttf2mesh-sys/ttf2mesh | 2 +- ttf2mesh-sys/ttf2mesh-fix.patch | 103 -------------------------------- 5 files changed, 4 insertions(+), 115 deletions(-) delete mode 100644 ttf2mesh-sys/ttf2mesh-fix.patch diff --git a/README.md b/README.md index ac8ddaf..c7cd61b 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,7 @@ See [examples](/examples) -folder and crate docs. ## Security -The API surface (mainly `.ttf` loading) has been fuzzed with [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). Current findings have been reported upstream and being applied at build time. - -Still, be careful if planning to use this library for parsing untrusted fonts. +The API surface (mainly `.ttf` loading) has been fuzzed with [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). ## Development diff --git a/ttf2mesh-sys/README.md b/ttf2mesh-sys/README.md index bf03b4e..55ba119 100644 --- a/ttf2mesh-sys/README.md +++ b/ttf2mesh-sys/README.md @@ -11,11 +11,3 @@ The library is built at the build time, if you don't have compiler installed: ``` sudo apt-get install build-essential ``` - -(although a smaller subset might also be sufficient) - -Currently, a security patch from `ttf2mesh-fix.patch` is applied to the original library (see https://github.com/fetisov/ttf2mesh/pull/2). A patch command line utility is needed for building: - -``` -sudo apt-get install patch -``` diff --git a/ttf2mesh-sys/build.rs b/ttf2mesh-sys/build.rs index 7d38b04..741bc6c 100644 --- a/ttf2mesh-sys/build.rs +++ b/ttf2mesh-sys/build.rs @@ -26,6 +26,7 @@ fn main() { .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); + /* let patch_path = manifest_dir.join("ttf2mesh-fix.patch"); let patch_file = std::fs::File::open(patch_path).unwrap(); @@ -45,6 +46,7 @@ fn main() { .status() .unwrap(); //// /patching + */ cc::Build::new() .flag("-Wall") diff --git a/ttf2mesh-sys/ttf2mesh b/ttf2mesh-sys/ttf2mesh index e41d86a..e52ceb2 160000 --- a/ttf2mesh-sys/ttf2mesh +++ b/ttf2mesh-sys/ttf2mesh @@ -1 +1 @@ -Subproject commit e41d86a4bbd3166e79086215f3a463c64164fb10 +Subproject commit e52ceb228f4b1a0132780675cecbd1adad629e18 diff --git a/ttf2mesh-sys/ttf2mesh-fix.patch b/ttf2mesh-sys/ttf2mesh-fix.patch deleted file mode 100644 index d439ad8..0000000 --- a/ttf2mesh-sys/ttf2mesh-fix.patch +++ /dev/null @@ -1,103 +0,0 @@ -diff --git a/ttf2mesh.c b/ttf2mesh.c -index abf85ec..bf77745 100644 ---- a/ttf2mesh.c -+++ b/ttf2mesh.c -@@ -56,6 +56,7 @@ - #include - #include - #include -+#include - - /* Big/little endian definitions */ - #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) -@@ -676,12 +677,19 @@ int parse_simple_glyph(ttf_glyph_t *glyph, int glyph_index, uint8_t *p, int avai - - j = 0; - n = -1; -+ int npoints_remaining = glyph->npoints; - for (i = 0; i < glyph->ncontours; i++) - { - j = (int)big16toh(endPtsOfContours[i]); -- glyph->outline->cont[i].length = j - n; -+ -+ int length = j - n; -+ npoints_remaining -= length; -+ if (length < 0 || npoints_remaining < 0) return TTF_ERR_FMT; -+ -+ glyph->outline->cont[i].length = length; - glyph->outline->cont[i].subglyph_id = glyph_index; - glyph->outline->cont[i].subglyph_order = 0; -+ - if (i != glyph->ncontours - 1) - glyph->outline->cont[i + 1].pt = glyph->outline->cont[i].pt + j - n; - n = j; -@@ -913,6 +921,7 @@ int parse_composite_glyph(ttf_t *ttf, ttf_glyph_t *glyph, uint8_t *p, int avail) - - /* initialize outline */ - glyph->outline = allocate_ttf_outline(glyph->ncontours, glyph->npoints); -+ int npoints_remaining = glyph->npoints; - if (glyph->outline == NULL) return TTF_ERR_NOMEM; - - /* initialize other glyph fields */ -@@ -985,7 +994,12 @@ int parse_composite_glyph(ttf_t *ttf, ttf_glyph_t *glyph, uint8_t *p, int avail) - for (i = 0; i < ttf->glyphs[glyphIndex].ncontours; i++) - { - glyph->outline->cont[n].pt = curr; -- glyph->outline->cont[n].length = ttf->glyphs[glyphIndex].outline->cont[i].length; -+ -+ int length = ttf->glyphs[glyphIndex].outline->cont[i].length; -+ npoints_remaining -= length; -+ if (length < 0 || npoints_remaining < 0) return TTF_ERR_FMT; -+ -+ glyph->outline->cont[n].length = length; - glyph->outline->cont[n].subglyph_id = glyphIndex; - glyph->outline->cont[n].subglyph_order = nglyphs; - for (j = 0; j < glyph->outline->cont[n].length; j++) -@@ -1044,6 +1058,10 @@ int parse_glyf_table(ttf_t *ttf, pps_t *pp) - { - offset = pp->ploca16 ? pp->ploca16[i] * 2 : pp->ploca32[i]; - if (offset == pp->sglyf) continue; -+ -+ if (offset + (int)sizeof(ttf_glyfh_t) > pp->sglyf) -+ return TTF_ERR_FMT; -+ - hdr = (ttf_glyfh_t *)(pp->pglyf + offset); - if ((int16_t)big16toh(hdr->numberOfContours) >= 0) continue; - result = parse_composite_glyph(ttf, ttf->glyphs + i, pp->pglyf + offset, pp->sglyf - offset); -@@ -1151,11 +1169,15 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) - rec = (ttf_tab_rec_t *)(s->hdr + 1); - - #define check_tag(str) (*(uint32_t *)rec->tableTag != *(uint32_t *)str) -- #define match(type, name, str) \ -+ #define match(type, name, str) \ - if (*(uint32_t *)rec->tableTag == *(uint32_t *)str) \ -- { \ -- s->s##name = rec->length; \ -- s->p##name = (type)(data + rec->offset); \ -+ { \ -+ s->s##name = rec->length; \ -+ s->p##name = (type)(data + rec->offset); \ -+ if (rec->offset > INT_MAX - rec->length) \ -+ return TTF_ERR_FMT; \ -+ if (rec->offset + rec->length > (unsigned)size) \ -+ return TTF_ERR_FMT; \ - } - - while (ntab--) -@@ -1163,6 +1185,7 @@ static int ttf_extract_tables(const uint8_t *data, int size, pps_t *s) - conv32(rec->checkSum); - conv32(rec->offset); - conv32(rec->length); -+ if (rec->offset > INT_MAX - rec->length) return TTF_ERR_FMT; - if (rec->offset + rec->length > (unsigned)size) return TTF_ERR_FMT; - if (check_tag("head")) - if (ttf_checksum(data + rec->offset, rec->length) != rec->checkSum) -@@ -1314,7 +1337,7 @@ static int locate_fmt4_table(pps_t *s) - for (i = 0; i < ntab; i++) - { - int offset = big32toh(s->pcmap->encRecs[i].offset); -- if (offset + 4 > s->scmap) return TTF_ERR_FMT; -+ if (offset + 4 > s->scmap || offset < 0) return TTF_ERR_FMT; - uint16_t format = *(uint16_t *)((char *)s->pcmap + offset); - if (big16toh(format) != 4) continue; - s->pfmt4 = (ttf_fmt4_t *)((char *)s->pcmap + offset); From b45fa852915cf5f738eac2311c05fcb9aa324f62 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 8 Aug 2021 21:29:14 +0300 Subject: [PATCH 21/46] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index be1e940..622deb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.8" +version = "0.0.9" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 37915033559fbe867d5652b42a45f3b0ba062f0b Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 13 Sep 2021 21:03:35 +0300 Subject: [PATCH 22/46] Windows fixes? --- fonts/.gitignore | 1 + src/lib.rs | 20 ++++++++++++++++++-- src/ttf.rs | 2 +- ttf2mesh-sys/build.rs | 3 ++- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 fonts/.gitignore diff --git a/fonts/.gitignore b/fonts/.gitignore new file mode 100644 index 0000000..6dba6e8 --- /dev/null +++ b/fonts/.gitignore @@ -0,0 +1 @@ +FiraMono-Medium.obj \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 8f5c26d..3106796 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ //! let mut ttf = TTFFile::from_file("./fonts/FiraMono-Medium.ttf").unwrap(); //! //! // export all glyphs as 2d meshes to a .obj file -//! ttf.export_to_obj("/dev/null", Quality::Low).unwrap(); +//! ttf.export_to_obj("./fonts/FiraMono-Medium.obj", Quality::Low).unwrap(); //! //! // generate 2d mesh for a glyph //! let mut glyph = ttf.glyph_from_char('€').unwrap(); @@ -29,7 +29,7 @@ //! ``` #![cfg_attr(feature = "unstable", feature(test))] -use std::{ffi::CString, os::unix::prelude::OsStrExt, path::Path}; +use std::{ffi::CString, path::Path}; mod error; mod glyph; @@ -47,10 +47,26 @@ pub use ttf::TTFFile; // TODO: support TTF_FEATURE_IGN_ERR as bitflag +#[cfg(not(windows))] fn path_to_cstring>(path: P) -> CString { + use os::unix::prelude::OsStrExt; CString::new(path.as_ref().as_os_str().as_bytes()).unwrap() } +#[cfg(windows)] +fn path_to_cstring>(path: P) -> CString { + // TODO: is this really ok? + CString::new( + path.as_ref() + .to_str() + .unwrap() + .to_string() + .as_bytes() + .to_vec(), + ) + .unwrap() +} + #[cfg(test)] mod tests { use std::path::PathBuf; diff --git a/src/ttf.rs b/src/ttf.rs index 995dc8c..2775005 100644 --- a/src/ttf.rs +++ b/src/ttf.rs @@ -23,7 +23,7 @@ use crate::{path_to_cstring, Error, Glyph, Quality}; /// assert_eq!(ttf.glyph_count(), 1485); /// /// // export all glyphs as 2d meshes to a .obj file -/// ttf.export_to_obj("/dev/null", Quality::Low).unwrap(); +/// ttf.export_to_obj("./fonts/FiraMono-Medium.obj", Quality::Low).unwrap(); /// /// // generate 2d mesh for a glyph /// let mut glyph = ttf.glyph_from_char('€').unwrap(); diff --git a/ttf2mesh-sys/build.rs b/ttf2mesh-sys/build.rs index 741bc6c..9db58ce 100644 --- a/ttf2mesh-sys/build.rs +++ b/ttf2mesh-sys/build.rs @@ -6,6 +6,8 @@ use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=wrapper.h"); println!("cargo:rerun-if-changed=ttf2mesh/ttf2mesh.c"); + + #[cfg(unix)] println!("cargo:rustc-link-lib=m"); let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -50,7 +52,6 @@ fn main() { cc::Build::new() .flag("-Wall") - .flag("-Wextra") .flag("-pedantic") .flag("-std=c99") .flag("-D_POSIX_C_SOURCE=199309L") From e3121f1244a7d2640d4c66894761b54eda1f75c9 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 13 Sep 2021 22:45:10 +0300 Subject: [PATCH 23/46] Fix test --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3106796..f1e238a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ pub use ttf::TTFFile; #[cfg(not(windows))] fn path_to_cstring>(path: P) -> CString { - use os::unix::prelude::OsStrExt; + use std::os::unix::ffi::OsStrExt; CString::new(path.as_ref().as_os_str().as_bytes()).unwrap() } From 16c5948973e7af3e94f9cd1598db7c052d360c73 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 27 Sep 2021 20:36:40 +0300 Subject: [PATCH 24/46] Windows cstring --- src/lib.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f1e238a..51c9538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,16 +55,7 @@ fn path_to_cstring>(path: P) -> CString { #[cfg(windows)] fn path_to_cstring>(path: P) -> CString { - // TODO: is this really ok? - CString::new( - path.as_ref() - .to_str() - .unwrap() - .to_string() - .as_bytes() - .to_vec(), - ) - .unwrap() + CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap() } #[cfg(test)] From a4a1ec516dc8ac7dfed60b4cdb8048d3052e0da9 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Mon, 27 Sep 2021 20:40:53 +0300 Subject: [PATCH 25/46] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 622deb0..dc37215 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.9" +version = "0.0.10" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From c16cfe6d7ae2e93f59d2520ff1a60ab42f267df7 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Tue, 28 Sep 2021 18:19:47 +0300 Subject: [PATCH 26/46] Publish ttf2mesh-sys v0.0.2 --- Cargo.toml | 4 ++-- ttf2mesh-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dc37215..15afe34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.10" +version = "0.0.11" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" @@ -10,7 +10,7 @@ keywords = ["tessellation", "mesh", "3d", "truetype", "ttf"] categories = ["multimedia", "api-bindings"] [dependencies] -ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.0.1" } +ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.0.2" } [workspace] members = ["ttf2mesh-sys"] diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 727f62e..0c85ac2 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh-sys" -version = "0.0.1" +version = "0.0.2" edition = "2018" description = "Rust FFI bindings for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 16d76542dea590a7b14a548ce0d5984046df8a8e Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:17:42 +0300 Subject: [PATCH 27/46] Add simple example, bump version to 0.1.0 --- Cargo.toml | 4 ++-- README.md | 47 ++++++++++++++++++++++++++++++++++++----- examples/ttf2simple.rs | 33 +++++++++++++++++++++++++++++ ttf2mesh-sys/Cargo.toml | 2 +- 4 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 examples/ttf2simple.rs diff --git a/Cargo.toml b/Cargo.toml index 15afe34..3753045 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.0.11" +version = "0.1.0" edition = "2018" description = "Rust API for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" @@ -10,7 +10,7 @@ keywords = ["tessellation", "mesh", "3d", "truetype", "ttf"] categories = ["multimedia", "api-bindings"] [dependencies] -ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.0.2" } +ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.1.0" } [workspace] members = ["ttf2mesh-sys"] diff --git a/README.md b/README.md index c7cd61b..abce1b3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # ttf2mesh-rs   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] -[Build Status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh-rs/test +[build status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh-rs/test [actions]: https://github.com/blaind/ttf2mesh/actions?query=branch%3Amain -[Latest Version]: https://img.shields.io/crates/v/ttf2mesh.svg +[latest version]: https://img.shields.io/crates/v/ttf2mesh.svg [crates.io]: https://crates.io/crates/ttf2mesh - -[Docs Version]: https://docs.rs/ttf2mesh/badge.svg +[docs version]: https://docs.rs/ttf2mesh/badge.svg [docs]: https://docs.rs/ttf2mesh A high-level Rust wrapper API for [fetisov's ttf2mesh](https://github.com/fetisov/ttf2mesh/) library for generating a 2d/3d mesh (vertices, indices and normals [only for 3D]) from TrueType (`.ttf`) glyphs. @@ -25,6 +24,44 @@ Add to `Cargo.toml`: See [examples](/examples) -folder and crate docs. +Simple usage: + +```rust +use ttf2mesh::{Quality, TTFFile, Value}; + +let mut font = TTFFile::from_file("fonts/FiraMono-Medium.ttf").unwrap(); + +for char in "Hello_World".chars() { + let mut glyph = font.glyph_from_char(char).unwrap(); + let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); + + println!("Mesh data char {:?}", char); + println!( + "- vertices: [{}]", + mesh.iter_vertices() + .map(|v| { + let v = v.val(); + format!("({:.3}, {:.2})", v.0, v.1) + }) + .collect::>() + .join(", ") + ); + println!( + "- faces: [{}]", + mesh.iter_faces() + .map(|v| { + let v = v.val(); + format!("({}, {}, {})", v.0, v.1, v.2) + }) + .collect::>() + .join(", ") + ); + println!(""); +} + + +``` + ## Security The API surface (mainly `.ttf` loading) has been fuzzed with [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). @@ -50,4 +87,4 @@ Licensed under MIT license ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the software by you, shall be licensed as above, without any additional terms or conditions. +for inclusion in the software by you, shall be licensed as above, without any additional terms or conditions. diff --git a/examples/ttf2simple.rs b/examples/ttf2simple.rs new file mode 100644 index 0000000..8d54aa0 --- /dev/null +++ b/examples/ttf2simple.rs @@ -0,0 +1,33 @@ +use ttf2mesh::{Quality, TTFFile, Value}; + +fn main() { + let mut font = TTFFile::from_file("fonts/FiraMono-Medium.ttf").unwrap(); + + for char in "Hello_World".chars() { + let mut glyph = font.glyph_from_char(char).unwrap(); + let mesh = glyph.to_2d_mesh(Quality::Medium).unwrap(); + + println!("Mesh data char {:?}", char); + println!( + "- vertices: [{}]", + mesh.iter_vertices() + .map(|v| { + let v = v.val(); + format!("({:.3}, {:.2})", v.0, v.1) + }) + .collect::>() + .join(", ") + ); + println!( + "- faces: [{}]", + mesh.iter_faces() + .map(|v| { + let v = v.val(); + format!("({}, {}, {})", v.0, v.1, v.2) + }) + .collect::>() + .join(", ") + ); + println!(""); + } +} diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 0c85ac2..664c688 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh-sys" -version = "0.0.2" +version = "0.1.0" edition = "2018" description = "Rust FFI bindings for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" From 36a411743fba93d20b69a1fc7c7d5f1c37f13391 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:23:06 +0300 Subject: [PATCH 28/46] Add a release test --- .gitignore | 1 + Cargo.toml | 1 + README.md | 2 +- crates/simple_test/.gitignore | 1 + crates/simple_test/Cargo.toml | 7 +++++++ crates/simple_test/src/main.rs | 3 +++ 6 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 crates/simple_test/.gitignore create mode 100644 crates/simple_test/Cargo.toml create mode 100644 crates/simple_test/src/main.rs diff --git a/.gitignore b/.gitignore index 96ef6c0..c599b62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +*.sw* diff --git a/Cargo.toml b/Cargo.toml index 3753045..cfdebdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.1.0" } [workspace] members = ["ttf2mesh-sys"] +exclude = ["crates/simple_test"] [features] default = [] diff --git a/README.md b/README.md index abce1b3..53e3c13 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Prequisites: Add to `Cargo.toml`: [dependencies] - ttf2mesh-rs = "*" # change with latest version + ttf2mesh = "*" # change to latest version ## Examples diff --git a/crates/simple_test/.gitignore b/crates/simple_test/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/crates/simple_test/.gitignore @@ -0,0 +1 @@ +target diff --git a/crates/simple_test/Cargo.toml b/crates/simple_test/Cargo.toml new file mode 100644 index 0000000..daac355 --- /dev/null +++ b/crates/simple_test/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "simple_test" +version = "0.1.0" +edition = "2018" + +[dependencies] +ttf2mesh = { git = "https://github.com/blaind/ttf2mesh-rs.git" } diff --git a/crates/simple_test/src/main.rs b/crates/simple_test/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/simple_test/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} From 2aae4fafe5cd573c478551086d95b88b5d979667 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:27:55 +0300 Subject: [PATCH 29/46] Remove commented out code --- ttf2mesh-sys/build.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/ttf2mesh-sys/build.rs b/ttf2mesh-sys/build.rs index 9db58ce..a115005 100644 --- a/ttf2mesh-sys/build.rs +++ b/ttf2mesh-sys/build.rs @@ -28,28 +28,6 @@ fn main() { .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); - /* - let patch_path = manifest_dir.join("ttf2mesh-fix.patch"); - let patch_file = std::fs::File::open(patch_path).unwrap(); - - //// patching, see https://github.com/fetisov/ttf2mesh/pull/2 - if std::process::Command::new("patch") - .arg("-v") - .status() - .is_err() - { - panic!("Can not apply ttf2mesh patch. Please make sure that you have `patch` command installed.") - } - - std::process::Command::new("patch") - .current_dir(manifest_dir.join("ttf2mesh")) - .args("-r - --forward -p1".split(" ")) - .stdin(patch_file) - .status() - .unwrap(); - //// /patching - */ - cc::Build::new() .flag("-Wall") .flag("-pedantic") From 57027479227467e708d5c0e989fbd60c85585085 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:30:37 +0300 Subject: [PATCH 30/46] Update description --- ttf2mesh-sys/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 664c688..51b43d1 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ttf2mesh-sys" -version = "0.1.0" +version = "0.1.1" edition = "2018" -description = "Rust FFI bindings for ttf2mesh" +description = "Rust FFI bindings for ttf2mesh - a crossplatform library allows to convert a glyphs of truetype font (ttf) to a mesh objects in 2d and 3d space" repository = "https://github.com/blaind/ttf2mesh-rs" license = "MIT" readme = "README.md" From 87370df8ac32188d6beb2b1676419e7248d40fe6 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:34:04 +0300 Subject: [PATCH 31/46] Update description - take two --- Cargo.toml | 4 ++-- ttf2mesh-sys/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cfdebdf..b9d9ce9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ttf2mesh" -version = "0.1.0" +version = "0.1.2" edition = "2018" -description = "Rust API for ttf2mesh" +description = "Rust API for ttf2mesh - a crossplatform library allows to convert a glyphs of truetype font (ttf) to a mesh objects in 2d and 3d space" repository = "https://github.com/blaind/ttf2mesh-rs" license = "MIT" readme = "README.md" diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 51b43d1..90b0e70 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ttf2mesh-sys" -version = "0.1.1" +version = "0.1.2" edition = "2018" -description = "Rust FFI bindings for ttf2mesh - a crossplatform library allows to convert a glyphs of truetype font (ttf) to a mesh objects in 2d and 3d space" +description = "Rust FFI bindings for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs" license = "MIT" readme = "README.md" From a35dbf88d90593e5b82e161c3aa722d9dc933ff4 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:34:47 +0300 Subject: [PATCH 32/46] Bump ttf2mesh-sys --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b9d9ce9..60c563f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["tessellation", "mesh", "3d", "truetype", "ttf"] categories = ["multimedia", "api-bindings"] [dependencies] -ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.1.0" } +ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.1.2" } [workspace] members = ["ttf2mesh-sys"] From db4640f07dfe4d13c37d2790dc66b788c8166301 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 12:36:52 +0300 Subject: [PATCH 33/46] Remove -rs from title, since its only a repo name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53e3c13..ae03d9b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ttf2mesh-rs   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] +# ttf2mesh   [![Build Status]][actions] [![Latest Version]][crates.io] [![Docs Version]][docs] [build status]: https://img.shields.io/github/workflow/status/blaind/ttf2mesh-rs/test [actions]: https://github.com/blaind/ttf2mesh/actions?query=branch%3Amain From 1b9f0414a865032b42d2f1f24299b9b1003494fc Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 24 Oct 2021 20:18:29 +0300 Subject: [PATCH 34/46] MSRV 1.43 --- .github/workflows/test.yml | 2 +- Cargo.toml | 3 ++- README.md | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5201b62..2553db5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - rust: [stable, nightly] + rust: [stable, 1.43] steps: - name: Install dependencies diff --git a/Cargo.toml b/Cargo.toml index 60c563f..308b7fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.1.2" +version = "0.2.0" edition = "2018" description = "Rust API for ttf2mesh - a crossplatform library allows to convert a glyphs of truetype font (ttf) to a mesh objects in 2d and 3d space" repository = "https://github.com/blaind/ttf2mesh-rs" @@ -8,6 +8,7 @@ license = "MIT" readme = "README.md" keywords = ["tessellation", "mesh", "3d", "truetype", "ttf"] categories = ["multimedia", "api-bindings"] +rust-version = "1.43" [dependencies] ttf2mesh-sys = { path = "ttf2mesh-sys", version = "0.1.2" } diff --git a/README.md b/README.md index ae03d9b..addb585 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,10 @@ Update submodules Develop +## Rust Version Support + +The minimum supported Rust version is 1.43 + ## License Licensed under MIT license From 66d17f3a5b6d7e8ba7e3cc5336e073bd0bc69ab5 Mon Sep 17 00:00:00 2001 From: Mika <1299457+blaind@users.noreply.github.com> Date: Mon, 25 Oct 2021 19:49:39 +0300 Subject: [PATCH 35/46] Create dependabot.yml --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..219c13a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" From d8578ce3eaa8f61941608dc8e654d3116fe6c1fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jun 2022 01:09:23 +0000 Subject: [PATCH 36/46] Update bindgen requirement from 0.59 to 0.60 Updates the requirements on [bindgen](https://github.com/rust-lang/rust-bindgen) to permit the latest version. - [Release notes](https://github.com/rust-lang/rust-bindgen/releases) - [Changelog](https://github.com/rust-lang/rust-bindgen/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.59.0...v0.60.0) --- updated-dependencies: - dependency-name: bindgen dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- ttf2mesh-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 90b0e70..77f4239 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT" readme = "README.md" [build-dependencies] -bindgen = "0.59" +bindgen = "0.60" cc = "1.0" From 026e43bd885d0431864215fdcdb4a18110498df9 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 13 Nov 2022 17:12:51 +0200 Subject: [PATCH 37/46] CI improvements v1 --- .github/workflows/test.yml | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2553db5..bcb6daa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,41 +10,28 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [windows-latest, ubuntu-latest, macos-latest] rust: [stable, 1.43] + runs-on: ${{ matrix.os }} steps: - name: Install dependencies run: sudo apt-get install gcc patch libudev-dev git - uses: actions/checkout@v2 + - uses: dtolnay/rust-toolchain@${{ matrix.rust }} - name: Init submodules run: git submodule update --init - - name: Cache Cargo registry - uses: actions/cache@v2 + - name: Cache + uses: actions/cache@v3 with: - path: ~/.cargo/registry - key: ${{ matrix.build }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ matrix.build }}-cargo-registry- - - - name: Cache Cargo index - uses: actions/cache@v2 - with: - path: ~/.cargo/git - key: ${{ matrix.build }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ matrix.build }}-cargo-index- - - - name: Cache Cargo build - uses: actions/cache@v2 - with: - path: target - key: ${{ matrix.build }}-target-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ matrix.build }}-target- + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Run tests run: cargo test --verbose From 05f0f9d8baca54cca8eb398e86b2fc25e9f83296 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 13 Nov 2022 17:16:16 +0200 Subject: [PATCH 38/46] CI v2 --- .github/workflows/test.yml | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bcb6daa..0859a08 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,6 @@ env: jobs: test: - runs-on: ubuntu-latest strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] @@ -15,23 +14,23 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Install dependencies - run: sudo apt-get install gcc patch libudev-dev git + - name: Install dependencies + run: sudo apt-get install gcc patch libudev-dev git - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - uses: dtolnay/rust-toolchain@${{ matrix.rust }} - - name: Init submodules - run: git submodule update --init + - name: Init submodules + run: git submodule update --init - - name: Cache - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Cache + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Run tests - run: cargo test --verbose + - name: Run tests + run: cargo test --verbose From a811034846788553673045ad1aad79ad82cfee13 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 13 Nov 2022 17:21:18 +0200 Subject: [PATCH 39/46] CI v3 --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0859a08..e355b56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,10 @@ jobs: run: sudo apt-get install gcc patch libudev-dev git - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@${{ matrix.rust }} + + - uses: dtolnay/rust-toolchain@v1 + with: + toolchain: ${{matrix.rust}} - name: Init submodules run: git submodule update --init From 76da039b93577e0562056d31a704a59fe8cd9aba Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 13 Nov 2022 17:23:22 +0200 Subject: [PATCH 40/46] CI v4 --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e355b56..2cedf71 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,13 +9,14 @@ jobs: test: strategy: matrix: - os: [windows-latest, ubuntu-latest, macos-latest] + os: [windows-latest, ubuntu-latest] rust: [stable, 1.43] runs-on: ${{ matrix.os }} steps: - name: Install dependencies run: sudo apt-get install gcc patch libudev-dev git + if: runner.os == 'linux' - uses: actions/checkout@v2 From 5bdc2f63168da7fbab02810c47644a3d004fb359 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 13 Nov 2022 17:37:57 +0200 Subject: [PATCH 41/46] CI v5 --- .github/workflows/{test.yml => ci.yml} | 4 ++-- README.md | 4 ---- src/quality.rs | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) rename .github/workflows/{test.yml => ci.yml} (93%) diff --git a/.github/workflows/test.yml b/.github/workflows/ci.yml similarity index 93% rename from .github/workflows/test.yml rename to .github/workflows/ci.yml index 2cedf71..60e06a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: os: [windows-latest, ubuntu-latest] - rust: [stable, 1.43] + rust: [stable, nightly] runs-on: ${{ matrix.os }} steps: @@ -34,7 +34,7 @@ jobs: ~/.cargo/registry ~/.cargo/git target - key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.toml') }} - name: Run tests run: cargo test --verbose diff --git a/README.md b/README.md index addb585..ae03d9b 100644 --- a/README.md +++ b/README.md @@ -80,10 +80,6 @@ Update submodules Develop -## Rust Version Support - -The minimum supported Rust version is 1.43 - ## License Licensed under MIT license diff --git a/src/quality.rs b/src/quality.rs index 3ec35a7..70fb51e 100644 --- a/src/quality.rs +++ b/src/quality.rs @@ -46,7 +46,7 @@ impl Quality { Quality::Low => 10, Quality::Medium => 20, Quality::High => 50, - Quality::Custom(value) => (*value), + Quality::Custom(value) => *value, } } } From e0c47469063c179a024d8fe66799dcad6f3d4b09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 00:59:26 +0000 Subject: [PATCH 42/46] Update bindgen requirement from 0.60 to 0.65 Updates the requirements on [bindgen](https://github.com/rust-lang/rust-bindgen) to permit the latest version. - [Release notes](https://github.com/rust-lang/rust-bindgen/releases) - [Changelog](https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.60.0...v0.65.1) --- updated-dependencies: - dependency-name: bindgen dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- ttf2mesh-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index 77f4239..f1362ec 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT" readme = "README.md" [build-dependencies] -bindgen = "0.60" +bindgen = "0.65" cc = "1.0" From 778b11c76a29b84315a791693bedd05bf23512df Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Tue, 11 Apr 2023 17:30:23 +0300 Subject: [PATCH 43/46] Prepare to publish 0.2.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 308b7fd..84a0396 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh" -version = "0.2.0" +version = "0.2.1" edition = "2018" description = "Rust API for ttf2mesh - a crossplatform library allows to convert a glyphs of truetype font (ttf) to a mesh objects in 2d and 3d space" repository = "https://github.com/blaind/ttf2mesh-rs" From 1ecc54f174caf2f8676542f11fa1a396aad0286c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 00:50:34 +0000 Subject: [PATCH 44/46] Update bindgen requirement from 0.65 to 0.68 Updates the requirements on [bindgen](https://github.com/rust-lang/rust-bindgen) to permit the latest version. - [Release notes](https://github.com/rust-lang/rust-bindgen/releases) - [Changelog](https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.65.0...v0.68.1) --- updated-dependencies: - dependency-name: bindgen dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- ttf2mesh-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index f1362ec..c5dbdb7 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT" readme = "README.md" [build-dependencies] -bindgen = "0.65" +bindgen = "0.68" cc = "1.0" From d1c9204d82549f26ec93c7c71a83de83a0e43a73 Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 19 Nov 2023 14:13:39 +0200 Subject: [PATCH 45/46] Upgrade bindgen to 0.69 --- ttf2mesh-sys/Cargo.toml | 2 +- ttf2mesh-sys/build.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index c5dbdb7..bef08eb 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT" readme = "README.md" [build-dependencies] -bindgen = "0.68" +bindgen = "0.69" cc = "1.0" diff --git a/ttf2mesh-sys/build.rs b/ttf2mesh-sys/build.rs index a115005..45ae914 100644 --- a/ttf2mesh-sys/build.rs +++ b/ttf2mesh-sys/build.rs @@ -19,7 +19,7 @@ fn main() { let bindings = bindgen::Builder::default() .header("wrapper.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) .generate() .expect("Unable to generate bindings"); From d662262f10bc8cf7d81959424581072f38c2d16e Mon Sep 17 00:00:00 2001 From: Mika Vatanen Date: Sun, 19 Nov 2023 14:15:00 +0200 Subject: [PATCH 46/46] ttf2mesh-sys prepare for 0.1.3 --- ttf2mesh-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf2mesh-sys/Cargo.toml b/ttf2mesh-sys/Cargo.toml index bef08eb..8fe67bc 100644 --- a/ttf2mesh-sys/Cargo.toml +++ b/ttf2mesh-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ttf2mesh-sys" -version = "0.1.2" +version = "0.1.3" edition = "2018" description = "Rust FFI bindings for ttf2mesh" repository = "https://github.com/blaind/ttf2mesh-rs"