From 06779822b76cb1d2920e422203d4f129298e4f66 Mon Sep 17 00:00:00 2001 From: Michael Zoech Date: Fri, 2 Mar 2018 16:36:19 -0800 Subject: [PATCH] Add support for FT_Glyph_Stroke and FT_Glyph_StrokeBorder --- src/glyph.rs | 29 +++++++++++++++++++++ src/lib.rs | 2 ++ src/library.rs | 16 +++++++++++- src/stroker.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/stroker.rs diff --git a/src/glyph.rs b/src/glyph.rs index 86ab72c..9dba285 100644 --- a/src/glyph.rs +++ b/src/glyph.rs @@ -6,6 +6,7 @@ use { FtResult, Matrix, RenderMode, + Stroker, Vector }; @@ -88,6 +89,34 @@ impl Glyph { } } + pub fn stroke(&self, stroker: &Stroker) -> FtResult { + let mut the_glyph = self.raw; + + let err = unsafe { + ffi::FT_Glyph_Stroke(&mut the_glyph, stroker.raw_stroker(), false as ffi::FT_Bool) + }; + + if err == ffi::FT_Err_Ok { + Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) }) + } else { + Err(err.into()) + } + } + + pub fn stroke_border(&self, stroker: &Stroker, inside: bool) -> FtResult { + let mut the_glyph = self.raw; + + let err = unsafe { + ffi::FT_Glyph_StrokeBorder(&mut the_glyph, stroker.raw_stroker(), inside as ffi::FT_Bool, false as ffi::FT_Bool) + }; + + if err == ffi::FT_Err_Ok { + Ok(unsafe { Glyph::from_raw(self.library_raw, the_glyph) }) + } else { + Err(err.into()) + } + } + pub fn advance_x(&self) -> isize { unsafe { (*self.raw).advance.x as isize diff --git a/src/lib.rs b/src/lib.rs index 615b068..823e3cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ pub use glyph_slot::GlyphSlot; pub use library::{ Library, LcdFilter }; pub use outline::Outline; pub use render_mode::RenderMode; +pub use stroker::{Stroker, StrokerLineCap, StrokerLineJoin }; pub use freetype_sys as ffi; pub mod bitmap; @@ -62,6 +63,7 @@ pub mod glyph_slot; pub mod library; pub mod outline; pub mod render_mode; +pub mod stroker; pub mod tt_os2; pub type BBox = ffi::FT_BBox; diff --git a/src/library.rs b/src/library.rs index c8642e8..6542a53 100644 --- a/src/library.rs +++ b/src/library.rs @@ -2,7 +2,7 @@ use std::ffi::{ CString, OsStr }; use std::ptr::null_mut; use std::rc::Rc; use libc::{ self, c_void, c_long, size_t }; -use { Face, FtResult, Error }; +use { Face, FtResult, Error, Stroker }; use ffi; extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void { @@ -89,6 +89,20 @@ impl Library { } } + pub fn new_stroker(&self) -> FtResult { + let mut stroker = null_mut(); + + let err = unsafe { + ffi::FT_Stroker_New(self.raw, &mut stroker) + }; + + if err == ffi::FT_Err_Ok { + Ok(unsafe { Stroker::from_raw(self.raw, stroker) }) + } else { + Err(err.into()) + } + } + /// Similar to `new_face`, but loads file data from a byte array in memory pub fn new_memory_face(&self, buffer: T, face_index: isize) -> FtResult where diff --git a/src/stroker.rs b/src/stroker.rs new file mode 100644 index 0000000..d2e871e --- /dev/null +++ b/src/stroker.rs @@ -0,0 +1,68 @@ +use { ffi }; + +#[repr(u32)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum StrokerLineCap { + Butt = ffi::FT_STROKER_LINECAP_BUTT, + Round = ffi::FT_STROKER_LINECAP_ROUND, + Square = ffi::FT_STROKER_LINECAP_SQUARE, +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum StrokerLineJoin { + Round = ffi::FT_STROKER_LINEJOIN_ROUND, + Bevel = ffi::FT_STROKER_LINEJOIN_BEVEL, + MiterVariable = ffi::FT_STROKER_LINEJOIN_MITER_VARIABLE, + MiterFixed = ffi::FT_STROKER_LINEJOIN_MITER_FIXED, +} + +pub struct Stroker { + library_raw: ffi::FT_Library, + raw: ffi::FT_Stroker, +} + +impl Stroker { + pub unsafe fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Stroker) -> Self { + ffi::FT_Reference_Library(library_raw); + Stroker { + library_raw: library_raw, + raw: raw, + } + } + + pub fn set(&self, radius: ffi::FT_Fixed, line_cap: StrokerLineCap, line_join: StrokerLineJoin, miter_limit: ffi::FT_Fixed) { + unsafe { + ffi::FT_Stroker_Set(self.raw, radius, line_cap as u32, line_join as u32, miter_limit); + } + } + + pub fn raw(&self) -> &ffi::FT_StrokerRec { + unsafe { + &*self.raw + } + } + + pub fn raw_mut(&mut self) -> &mut ffi::FT_StrokerRec { + unsafe { + &mut *self.raw + } + } + + pub(crate) fn raw_stroker(&self) -> ffi::FT_Stroker { + self.raw + } +} + +impl Drop for Stroker { + + fn drop(&mut self) { + let err = unsafe { + ffi::FT_Stroker_Done(self.raw); + ffi::FT_Done_Library(self.library_raw) + }; + if err != ffi::FT_Err_Ok { + panic!("Failed to drop library"); + } + } +}