diff options
author | Christian Duerr <contact@christianduerr.com> | 2020-07-19 20:35:15 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-19 20:35:15 +0000 |
commit | 714bbb769ec1ff4a32e594aa6d67d13b98814caa (patch) | |
tree | 453e5dc8b23b209f8bbac5a288d0b8584aaa8ffc /font/src/ft/fc | |
parent | fa79758f5645bff66f8d12797832fa2b57157975 (diff) | |
download | alacritty-714bbb769ec1ff4a32e594aa6d67d13b98814caa.tar.gz alacritty-714bbb769ec1ff4a32e594aa6d67d13b98814caa.zip |
Bump version to 0.5.0-rc2v0.5.0-rc2
Diffstat (limited to 'font/src/ft/fc')
-rw-r--r-- | font/src/ft/fc/char_set.rs | 70 | ||||
-rw-r--r-- | font/src/ft/fc/config.rs | 29 | ||||
-rw-r--r-- | font/src/ft/fc/font_set.rs | 87 | ||||
-rw-r--r-- | font/src/ft/fc/mod.rs | 337 | ||||
-rw-r--r-- | font/src/ft/fc/object_set.rs | 48 | ||||
-rw-r--r-- | font/src/ft/fc/pattern.rs | 627 |
6 files changed, 0 insertions, 1198 deletions
diff --git a/font/src/ft/fc/char_set.rs b/font/src/ft/fc/char_set.rs deleted file mode 100644 index 9579b7b9..00000000 --- a/font/src/ft/fc/char_set.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::ptr::NonNull; - -use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; - -use super::ffi::FcCharSetCreate; -use super::ffi::{ - FcBool, FcCharSet, FcCharSetAddChar, FcCharSetCopy, FcCharSetCount, FcCharSetDestroy, - FcCharSetHasChar, FcCharSetMerge, FcCharSetSubtract, FcCharSetUnion, -}; - -foreign_type! { - pub unsafe type CharSet { - type CType = FcCharSet; - fn drop = FcCharSetDestroy; - fn clone = FcCharSetCopy; - } -} - -impl CharSet { - pub fn new() -> Self { - Self::default() - } -} - -impl Default for CharSet { - fn default() -> Self { - CharSet(unsafe { NonNull::new(FcCharSetCreate()).unwrap() }) - } -} - -impl CharSetRef { - pub fn add(&mut self, glyph: char) -> bool { - unsafe { FcCharSetAddChar(self.as_ptr(), glyph as _) == 1 } - } - - pub fn has_char(&self, glyph: char) -> bool { - unsafe { FcCharSetHasChar(self.as_ptr(), glyph as _) == 1 } - } - - pub fn count(&self) -> u32 { - unsafe { FcCharSetCount(self.as_ptr()) as u32 } - } - - pub fn union(&self, other: &CharSetRef) -> CharSet { - unsafe { - let ptr = FcCharSetUnion(self.as_ptr() as _, other.as_ptr() as _); - CharSet::from_ptr(ptr) - } - } - - pub fn subtract(&self, other: &CharSetRef) -> CharSet { - unsafe { - let ptr = FcCharSetSubtract(self.as_ptr() as _, other.as_ptr() as _); - CharSet::from_ptr(ptr) - } - } - - pub fn merge(&self, other: &CharSetRef) -> Result<bool, ()> { - unsafe { - // Value is just an indicator whether something was added or not. - let mut value: FcBool = 0; - let res = FcCharSetMerge(self.as_ptr() as _, other.as_ptr() as _, &mut value); - if res == 0 { - Err(()) - } else { - Ok(value != 0) - } - } - } -} diff --git a/font/src/ft/fc/config.rs b/font/src/ft/fc/config.rs deleted file mode 100644 index ac87a284..00000000 --- a/font/src/ft/fc/config.rs +++ /dev/null @@ -1,29 +0,0 @@ -use foreign_types::{foreign_type, ForeignTypeRef}; - -use super::ffi::{FcConfig, FcConfigDestroy, FcConfigGetCurrent, FcConfigGetFonts}; -use super::{FontSetRef, SetName}; - -foreign_type! { - pub unsafe type Config { - type CType = FcConfig; - fn drop = FcConfigDestroy; - } -} - -impl Config { - /// Get the current configuration. - pub fn get_current() -> &'static ConfigRef { - unsafe { ConfigRef::from_ptr(FcConfigGetCurrent()) } - } -} - -impl ConfigRef { - /// Returns one of the two sets of fonts from the configuration as - /// specified by `set`. - pub fn get_fonts(&self, set: SetName) -> &FontSetRef { - unsafe { - let ptr = FcConfigGetFonts(self.as_ptr(), set as u32); - FontSetRef::from_ptr(ptr) - } - } -} diff --git a/font/src/ft/fc/font_set.rs b/font/src/ft/fc/font_set.rs deleted file mode 100644 index 2f003312..00000000 --- a/font/src/ft/fc/font_set.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::ops::Deref; -use std::ptr::NonNull; - -use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; -use log::trace; - -use super::{ConfigRef, ObjectSetRef, PatternRef}; - -use super::ffi::{FcFontSet, FcFontSetDestroy, FcFontSetList}; - -foreign_type! { - pub unsafe type FontSet { - type CType = FcFontSet; - fn drop = FcFontSetDestroy; - } -} - -impl FontSet { - pub fn list( - config: &ConfigRef, - source: &mut FontSetRef, - pattern: &PatternRef, - objects: &ObjectSetRef, - ) -> FontSet { - let raw = unsafe { - FcFontSetList( - config.as_ptr(), - &mut source.as_ptr(), - 1, // nsets. - pattern.as_ptr(), - objects.as_ptr(), - ) - }; - FontSet(NonNull::new(raw).unwrap()) - } -} - -/// Iterator over a font set. -pub struct Iter<'a> { - font_set: &'a FontSetRef, - num_fonts: usize, - current: usize, -} - -impl<'a> IntoIterator for &'a FontSet { - type IntoIter = Iter<'a>; - type Item = &'a PatternRef; - - fn into_iter(self) -> Iter<'a> { - let num_fonts = unsafe { (*self.as_ptr()).nfont as isize }; - - trace!("Number of fonts is {}", num_fonts); - - Iter { font_set: self.deref(), num_fonts: num_fonts as _, current: 0 } - } -} - -impl<'a> IntoIterator for &'a FontSetRef { - type IntoIter = Iter<'a>; - type Item = &'a PatternRef; - - fn into_iter(self) -> Iter<'a> { - let num_fonts = unsafe { (*self.as_ptr()).nfont as isize }; - - trace!("Number of fonts is {}", num_fonts); - - Iter { font_set: self, num_fonts: num_fonts as _, current: 0 } - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = &'a PatternRef; - - fn next(&mut self) -> Option<Self::Item> { - if self.current == self.num_fonts { - None - } else { - let pattern = unsafe { - let ptr = *(*self.font_set.as_ptr()).fonts.add(self.current); - PatternRef::from_ptr(ptr) - }; - - self.current += 1; - Some(pattern) - } - } -} diff --git a/font/src/ft/fc/mod.rs b/font/src/ft/fc/mod.rs deleted file mode 100644 index 1058bea3..00000000 --- a/font/src/ft/fc/mod.rs +++ /dev/null @@ -1,337 +0,0 @@ -use std::fmt; -use std::ptr; - -use foreign_types::{ForeignType, ForeignTypeRef}; - -use fontconfig::fontconfig as ffi; - -use ffi::FcResultNoMatch; -use ffi::{FcFontList, FcFontMatch, FcFontSort}; -use ffi::{FcMatchFont, FcMatchPattern, FcMatchScan}; -use ffi::{FcSetApplication, FcSetSystem}; -use ffi::{FC_SLANT_ITALIC, FC_SLANT_OBLIQUE, FC_SLANT_ROMAN}; -use ffi::{FC_WEIGHT_BLACK, FC_WEIGHT_BOLD, FC_WEIGHT_EXTRABLACK, FC_WEIGHT_EXTRABOLD}; -use ffi::{FC_WEIGHT_BOOK, FC_WEIGHT_MEDIUM, FC_WEIGHT_REGULAR, FC_WEIGHT_SEMIBOLD}; -use ffi::{FC_WEIGHT_EXTRALIGHT, FC_WEIGHT_LIGHT, FC_WEIGHT_THIN}; - -pub mod config; -pub use config::{Config, ConfigRef}; - -pub mod font_set; -pub use font_set::{FontSet, FontSetRef}; - -pub mod object_set; -pub use object_set::{ObjectSet, ObjectSetRef}; - -pub mod char_set; -pub use char_set::{CharSet, CharSetRef}; - -pub mod pattern; -pub use pattern::{FTFaceLocation, Pattern, PatternHash, PatternRef}; - -/// Find the font closest matching the provided pattern. -/// -/// The returned pattern is the result of Pattern::render_prepare. -pub fn font_match(config: &ConfigRef, pattern: &PatternRef) -> Option<Pattern> { - unsafe { - // What is this result actually used for? Seems redundant with - // return type. - let mut result = FcResultNoMatch; - let ptr = FcFontMatch(config.as_ptr(), pattern.as_ptr(), &mut result); - - if ptr.is_null() { - None - } else { - Some(Pattern::from_ptr(ptr)) - } - } -} - -/// List fonts by closeness to the pattern. -pub fn font_sort(config: &ConfigRef, pattern: &PatternRef) -> Option<FontSet> { - unsafe { - // What is this result actually used for? Seems redundant with - // return type. - let mut result = FcResultNoMatch; - - let mut charsets: *mut _ = ptr::null_mut(); - let ptr = FcFontSort( - config.as_ptr(), - pattern.as_ptr(), - 1, // Trim font list. - &mut charsets, - &mut result, - ); - - if ptr.is_null() { - None - } else { - Some(FontSet::from_ptr(ptr)) - } - } -} - -/// List fonts matching pattern. -pub fn font_list( - config: &ConfigRef, - pattern: &PatternRef, - objects: &ObjectSetRef, -) -> Option<FontSet> { - unsafe { - let ptr = FcFontList(config.as_ptr(), pattern.as_ptr(), objects.as_ptr()); - - if ptr.is_null() { - None - } else { - Some(FontSet::from_ptr(ptr)) - } - } -} - -/// Available font sets. -#[derive(Debug, Copy, Clone)] -pub enum SetName { - System = FcSetSystem as isize, - Application = FcSetApplication as isize, -} - -/// When matching, how to match. -#[derive(Debug, Copy, Clone)] -pub enum MatchKind { - Font = FcMatchFont as isize, - Pattern = FcMatchPattern as isize, - Scan = FcMatchScan as isize, -} - -#[derive(Debug, Copy, Clone)] -pub enum Slant { - Italic = FC_SLANT_ITALIC as isize, - Oblique = FC_SLANT_OBLIQUE as isize, - Roman = FC_SLANT_ROMAN as isize, -} - -#[derive(Debug, Copy, Clone)] -pub enum Weight { - Thin = FC_WEIGHT_THIN as isize, - Extralight = FC_WEIGHT_EXTRALIGHT as isize, - Light = FC_WEIGHT_LIGHT as isize, - Book = FC_WEIGHT_BOOK as isize, - Regular = FC_WEIGHT_REGULAR as isize, - Medium = FC_WEIGHT_MEDIUM as isize, - Semibold = FC_WEIGHT_SEMIBOLD as isize, - Bold = FC_WEIGHT_BOLD as isize, - Extrabold = FC_WEIGHT_EXTRABOLD as isize, - Black = FC_WEIGHT_BLACK as isize, - Extrablack = FC_WEIGHT_EXTRABLACK as isize, -} - -#[derive(Debug, Copy, Clone)] -pub enum Width { - Ultracondensed, - Extracondensed, - Condensed, - Semicondensed, - Normal, - Semiexpanded, - Expanded, - Extraexpanded, - Ultraexpanded, - Other(i32), -} - -impl Width { - fn to_isize(self) -> isize { - match self { - Width::Ultracondensed => 50, - Width::Extracondensed => 63, - Width::Condensed => 75, - Width::Semicondensed => 87, - Width::Normal => 100, - Width::Semiexpanded => 113, - Width::Expanded => 125, - Width::Extraexpanded => 150, - Width::Ultraexpanded => 200, - Width::Other(value) => value as isize, - } - } -} - -impl From<isize> for Width { - fn from(value: isize) -> Self { - match value { - 50 => Width::Ultracondensed, - 63 => Width::Extracondensed, - 75 => Width::Condensed, - 87 => Width::Semicondensed, - 100 => Width::Normal, - 113 => Width::Semiexpanded, - 125 => Width::Expanded, - 150 => Width::Extraexpanded, - 200 => Width::Ultraexpanded, - _ => Width::Other(value as _), - } - } -} - -/// Subpixel geometry. -#[derive(Debug)] -pub enum Rgba { - Unknown, - Rgb, - Bgr, - Vrgb, - Vbgr, - None, -} - -impl Rgba { - fn to_isize(&self) -> isize { - match *self { - Rgba::Unknown => 0, - Rgba::Rgb => 1, - Rgba::Bgr => 2, - Rgba::Vrgb => 3, - Rgba::Vbgr => 4, - Rgba::None => 5, - } - } -} - -impl fmt::Display for Rgba { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(match *self { - Rgba::Unknown => "unknown", - Rgba::Rgb => "rgb", - Rgba::Bgr => "bgr", - Rgba::Vrgb => "vrgb", - Rgba::Vbgr => "vbgr", - Rgba::None => "none", - }) - } -} - -impl From<isize> for Rgba { - fn from(val: isize) -> Rgba { - match val { - 1 => Rgba::Rgb, - 2 => Rgba::Bgr, - 3 => Rgba::Vrgb, - 4 => Rgba::Vbgr, - 5 => Rgba::None, - _ => Rgba::Unknown, - } - } -} - -/// Hinting Style. -#[derive(Debug, Copy, Clone)] -pub enum HintStyle { - None, - Slight, - Medium, - Full, -} - -impl fmt::Display for HintStyle { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(match *self { - HintStyle::None => "none", - HintStyle::Slight => "slight", - HintStyle::Medium => "medium", - HintStyle::Full => "full", - }) - } -} - -/// Lcd filter, used to reduce color fringing with subpixel rendering. -pub enum LcdFilter { - None, - Default, - Light, - Legacy, -} - -impl fmt::Display for LcdFilter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(match *self { - LcdFilter::None => "none", - LcdFilter::Default => "default", - LcdFilter::Light => "light", - LcdFilter::Legacy => "legacy", - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn font_match() { - let mut pattern = Pattern::new(); - pattern.add_family("monospace"); - pattern.add_style("regular"); - - let config = Config::get_current(); - pattern.config_substitute(config, MatchKind::Pattern); - pattern.default_substitute(); - let font = super::font_match(config, &pattern).expect("match font monospace"); - - print!("index={:?}; ", font.index()); - print!("family={:?}; ", font.family()); - print!("style={:?}; ", font.style()); - print!("antialias={:?}; ", font.antialias()); - print!("autohint={:?}; ", font.autohint()); - print!("hinting={:?}; ", font.hinting()); - print!("rgba={:?}; ", font.rgba()); - print!("embeddedbitmap={:?}; ", font.embeddedbitmap()); - print!("lcdfilter={:?}; ", font.lcdfilter()); - print!("hintstyle={:?}", font.hintstyle()); - println!(); - } - - #[test] - fn font_sort() { - let mut pattern = Pattern::new(); - pattern.add_family("monospace"); - pattern.set_slant(Slant::Italic); - - let config = Config::get_current(); - pattern.config_substitute(config, MatchKind::Pattern); - pattern.default_substitute(); - let fonts = super::font_sort(config, &pattern).expect("sort font monospace"); - - for font in fonts.into_iter().take(10) { - let font = pattern.render_prepare(&config, &font); - print!("index={:?}; ", font.index()); - print!("family={:?}; ", font.family()); - print!("style={:?}; ", font.style()); - print!("rgba={:?}", font.rgba()); - print!("rgba={:?}", font.rgba()); - println!(); - } - } - - #[test] - fn font_sort_with_glyph() { - let mut charset = CharSet::new(); - charset.add('💖'); - let mut pattern = Pattern::new(); - pattern.add_charset(&charset); - drop(charset); - - let config = Config::get_current(); - pattern.config_substitute(config, MatchKind::Pattern); - pattern.default_substitute(); - let fonts = super::font_sort(config, &pattern).expect("font_sort"); - - for font in fonts.into_iter().take(10) { - let font = pattern.render_prepare(&config, &font); - print!("index={:?}; ", font.index()); - print!("family={:?}; ", font.family()); - print!("style={:?}; ", font.style()); - print!("rgba={:?}", font.rgba()); - println!(); - } - } -} diff --git a/font/src/ft/fc/object_set.rs b/font/src/ft/fc/object_set.rs deleted file mode 100644 index 74faabbf..00000000 --- a/font/src/ft/fc/object_set.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::ptr::NonNull; - -use libc::c_char; - -use super::ffi::{FcObjectSet, FcObjectSetAdd, FcObjectSetCreate, FcObjectSetDestroy}; -use foreign_types::{foreign_type, ForeignTypeRef}; - -foreign_type! { - pub unsafe type ObjectSet { - type CType = FcObjectSet; - fn drop = FcObjectSetDestroy; - } -} - -impl ObjectSet { - pub fn new() -> Self { - Self::default() - } -} - -impl Default for ObjectSet { - fn default() -> Self { - ObjectSet(unsafe { NonNull::new(FcObjectSetCreate()).unwrap() }) - } -} - -impl ObjectSetRef { - fn add(&mut self, property: &[u8]) { - unsafe { - FcObjectSetAdd(self.as_ptr(), property.as_ptr() as *mut c_char); - } - } - - #[inline] - pub fn add_file(&mut self) { - self.add(b"file\0"); - } - - #[inline] - pub fn add_index(&mut self) { - self.add(b"index\0"); - } - - #[inline] - pub fn add_style(&mut self) { - self.add(b"style\0"); - } -} diff --git a/font/src/ft/fc/pattern.rs b/font/src/ft/fc/pattern.rs deleted file mode 100644 index 19d72b47..00000000 --- a/font/src/ft/fc/pattern.rs +++ /dev/null @@ -1,627 +0,0 @@ -use std::ffi::{CStr, CString}; -use std::fmt; -use std::mem; -use std::path::PathBuf; -use std::ptr::{self, NonNull}; -use std::str; - -use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; -use libc::{c_char, c_double, c_int}; - -use super::ffi::FcMatrix; -use super::ffi::FcResultMatch; -use super::ffi::{FcBool, FcFontRenderPrepare, FcPatternGetBool, FcPatternGetDouble}; -use super::ffi::{FcChar8, FcConfigSubstitute, FcDefaultSubstitute, FcPattern, FcPatternHash}; -use super::ffi::{ - FcPatternAddCharSet, FcPatternDestroy, FcPatternDuplicate, FcPatternGetCharSet, - FcPatternGetMatrix, -}; -use super::ffi::{FcPatternAddDouble, FcPatternAddString, FcPatternCreate, FcPatternGetString}; -use super::ffi::{FcPatternAddInteger, FcPatternGetInteger, FcPatternPrint}; - -use super::{CharSetRef, ConfigRef, HintStyle, LcdFilter, MatchKind, Rgba, Slant, Weight, Width}; - -pub struct StringPropertyIter<'a> { - pattern: &'a PatternRef, - object: &'a [u8], - index: usize, -} - -impl<'a> StringPropertyIter<'a> { - fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> StringPropertyIter<'b> { - StringPropertyIter { pattern, object, index: 0 } - } - - fn get_value(&self, index: usize) -> Option<&'a str> { - let mut value: *mut FcChar8 = ptr::null_mut(); - - let result = unsafe { - FcPatternGetString( - self.pattern.as_ptr(), - self.object.as_ptr() as *mut c_char, - index as c_int, - &mut value, - ) - }; - - if result == FcResultMatch { - // Transmute here is to extend lifetime of the str to that of the iterator. - // - // Potential unsafety? What happens if the pattern is modified while this ptr is - // borrowed out? - Some(unsafe { - mem::transmute(CStr::from_ptr(value as *const c_char).to_str().unwrap()) - }) - } else { - None - } - } -} - -/// Iterator over integer properties. -pub struct BooleanPropertyIter<'a> { - pattern: &'a PatternRef, - object: &'a [u8], - index: usize, -} - -impl<'a> BooleanPropertyIter<'a> { - fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> BooleanPropertyIter<'b> { - BooleanPropertyIter { pattern, object, index: 0 } - } - - fn get_value(&self, index: usize) -> Option<bool> { - let mut value: FcBool = 0; - - let result = unsafe { - FcPatternGetBool( - self.pattern.as_ptr(), - self.object.as_ptr() as *mut c_char, - index as c_int, - &mut value, - ) - }; - - if result == FcResultMatch { - Some(value != 0) - } else { - None - } - } -} - -/// Iterator over integer properties. -pub struct IntPropertyIter<'a> { - pattern: &'a PatternRef, - object: &'a [u8], - index: usize, -} - -impl<'a> IntPropertyIter<'a> { - fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> IntPropertyIter<'b> { - IntPropertyIter { pattern, object, index: 0 } - } - - fn get_value(&self, index: usize) -> Option<isize> { - let mut value = 0 as c_int; - - let result = unsafe { - FcPatternGetInteger( - self.pattern.as_ptr(), - self.object.as_ptr() as *mut c_char, - index as c_int, - &mut value, - ) - }; - - if result == FcResultMatch { - Some(value as isize) - } else { - None - } - } -} - -pub struct RgbaPropertyIter<'a> { - inner: IntPropertyIter<'a>, -} - -impl<'a> RgbaPropertyIter<'a> { - fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> RgbaPropertyIter<'b> { - RgbaPropertyIter { inner: IntPropertyIter::new(pattern, object) } - } - - #[inline] - fn inner<'b>(&'b mut self) -> &'b mut IntPropertyIter<'a> { - &mut self.inner - } - - fn get_value(&self, index: usize) -> Option<Rgba> { - self.inner.get_value(index).map(Rgba::from) - } -} - -pub struct HintStylePropertyIter<'a> { - inner: IntPropertyIter<'a>, -} - -impl<'a> HintStylePropertyIter<'a> { - fn new(pattern: &PatternRef) -> HintStylePropertyIter { - HintStylePropertyIter { inner: IntPropertyIter::new(pattern, b"hintstyle\0") } - } - - #[inline] - fn inner<'b>(&'b mut self) -> &'b mut IntPropertyIter<'a> { - &mut self.inner - } - - fn get_value(&self, index: usize) -> Option<HintStyle> { - self.inner.get_value(index).and_then(|hint_style| { - Some(match hint_style { - 0 => HintStyle::None, - 1 => HintStyle::Slight, - 2 => HintStyle::Medium, - 3 => HintStyle::Full, - _ => return None, - }) - }) - } -} - -pub struct LcdFilterPropertyIter<'a> { - inner: IntPropertyIter<'a>, -} - -impl<'a> LcdFilterPropertyIter<'a> { - fn new(pattern: &PatternRef) -> LcdFilterPropertyIter { - LcdFilterPropertyIter { inner: IntPropertyIter::new(pattern, b"lcdfilter\0") } - } - - #[inline] - fn inner<'b>(&'b mut self) -> &'b mut IntPropertyIter<'a> { - &mut self.inner - } - - fn get_value(&self, index: usize) -> Option<LcdFilter> { - self.inner.get_value(index).and_then(|hint_style| { - Some(match hint_style { - 0 => LcdFilter::None, - 1 => LcdFilter::Default, - 2 => LcdFilter::Light, - 3 => LcdFilter::Legacy, - _ => return None, - }) - }) - } -} - -/// Iterator over integer properties. -pub struct DoublePropertyIter<'a> { - pattern: &'a PatternRef, - object: &'a [u8], - index: usize, -} - -impl<'a> DoublePropertyIter<'a> { - fn new<'b>(pattern: &'b PatternRef, object: &'b [u8]) -> DoublePropertyIter<'b> { - DoublePropertyIter { pattern, object, index: 0 } - } - - fn get_value(&self, index: usize) -> Option<f64> { - let mut value = f64::from(0); - - let result = unsafe { - FcPatternGetDouble( - self.pattern.as_ptr(), - self.object.as_ptr() as *mut c_char, - index as c_int, - &mut value, - ) - }; - - if result == FcResultMatch { - Some(value as f64) - } else { - None - } - } -} - -/// Implement debug for a property iterator. -macro_rules! impl_property_iter_debug { - ($iter:ty => $item:ty) => { - impl<'a> fmt::Debug for $iter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[")?; - for i in 0.. { - match self.get_value(i) { - Some(val) => { - if i > 0 { - write!(f, ", {}", val)?; - } else { - write!(f, "{}", val)?; - } - }, - _ => break, - } - } - write!(f, "]") - } - } - }; -} - -/// Implement Iterator and Debug for a property iterator. -macro_rules! impl_property_iter { - ($($iter:ty => $item:ty),*) => { - $( - impl<'a> Iterator for $iter { - type Item = $item; - - fn next(&mut self) -> Option<Self::Item> { - let res = self.get_value(self.index); - self.index += 1; - res - } - - #[inline] - fn nth(&mut self, n: usize) -> Option<Self::Item> { - self.index += n; - self.next() - } - } - impl_property_iter_debug!($iter => $item); - )* - } -} - -/// Implement Iterator and Debug for a property iterator which internally relies -/// on another property iterator. -macro_rules! impl_derived_property_iter { - ($($iter:ty => $item:ty),*) => { - $( - impl<'a> Iterator for $iter { - type Item = $item; - - fn next(&mut self) -> Option<Self::Item> { - let index = { self.inner().index }; - let res = self.get_value(index); - self.inner().index += 1; - res - } - - #[inline] - fn nth(&mut self, n: usize) -> Option<Self::Item> { - self.inner().index += n; - self.next() - } - } - impl_property_iter_debug!($iter => $item); - )* - } -} - -// Basic Iterators. -impl_property_iter! { - StringPropertyIter<'a> => &'a str, - IntPropertyIter<'a> => isize, - DoublePropertyIter<'a> => f64, - BooleanPropertyIter<'a> => bool -} - -// Derived Iterators. -impl_derived_property_iter! { - RgbaPropertyIter<'a> => Rgba, - HintStylePropertyIter<'a> => HintStyle, - LcdFilterPropertyIter<'a> => LcdFilter -} - -foreign_type! { - pub unsafe type Pattern { - type CType = FcPattern; - fn drop = FcPatternDestroy; - fn clone = FcPatternDuplicate; - } -} - -macro_rules! string_accessor { - ($([$getter:ident, $setter:ident] => $object_name:expr),*) => { - $( - #[inline] - pub fn $setter(&mut self, value: &str) -> bool { - unsafe { - self.add_string($object_name, value) - } - } - - #[inline] - pub fn $getter(&self) -> StringPropertyIter { - unsafe { - self.get_string($object_name) - } - } - )* - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct PatternHash(pub u32); - -#[derive(Hash, Eq, PartialEq, Debug)] -pub struct FTFaceLocation { - pub path: PathBuf, - pub index: isize, -} - -impl FTFaceLocation { - pub fn new(path: PathBuf, index: isize) -> Self { - Self { path, index } - } -} - -impl Pattern { - pub fn new() -> Self { - Self::default() - } -} - -impl Default for Pattern { - fn default() -> Self { - Pattern(unsafe { NonNull::new(FcPatternCreate()).unwrap() }) - } -} - -macro_rules! pattern_get_integer { - ($($method:ident() => $property:expr),+) => { - $( - pub fn $method(&self) -> IntPropertyIter { - unsafe { - self.get_integer($property) - } - } - )+ - }; -} - -macro_rules! boolean_getter { - ($($method:ident() => $property:expr),*) => { - $( - pub fn $method(&self) -> BooleanPropertyIter { - unsafe { - self.get_boolean($property) - } - } - )* - } -} - -macro_rules! double_getter { - ($($method:ident() => $property:expr),*) => { - $( - pub fn $method(&self) -> DoublePropertyIter { - unsafe { - self.get_double($property) - } - } - )* - } -} - -impl PatternRef { - boolean_getter! { - antialias() => b"antialias\0", - hinting() => b"hinting\0", - verticallayout() => b"verticallayout\0", - autohint() => b"autohint\0", - globaladvance() => b"globaladvance\0", - scalable() => b"scalable\0", - symbol() => b"symbol\0", - color() => b"color\0", - minspace() => b"minspace\0", - embolden() => b"embolden\0", - embeddedbitmap() => b"embeddedbitmap\0", - decorative() => b"decorative\0" - } - - double_getter! { - size() => b"size\0", - aspect() => b"aspect\0", - pixelsize() => b"pixelsize\0", - pixelsizefixupfactor() => b"pixelsizefixupfactor\0", - scale() => b"scale\0", - dpi() => b"dpi\0" - } - - string_accessor! { - [family, add_family] => b"family\0", - [familylang, add_familylang] => b"familylang\0", - [style, add_style] => b"style\0", - [stylelang, add_stylelang] => b"stylelang\0", - [fullname, add_fullname] => b"fullname\0", - [fullnamelang, add_fullnamelang] => b"fullnamelang\0", - [foundry, add_foundry] => b"foundry\0", - [capability, add_capability] => b"capability\0", - [fontformat, add_fontformat] => b"fontformat\0", - [fontfeatures, add_fontfeatures] => b"fontfeatures\0", - [namelang, add_namelang] => b"namelang\0", - [postscriptname, add_postscriptname] => b"postscriptname\0" - } - - pattern_get_integer! { - index() => b"index\0" - } - - /// Prints the pattern to stdout. - /// - /// FontConfig doesn't expose a way to iterate over all members of a pattern; - /// instead, we just defer to FcPatternPrint. Otherwise, this could have been - /// a `fmt::Debug` impl. - pub fn print(&self) { - unsafe { FcPatternPrint(self.as_ptr()) } - } - - /// Add a string value to the pattern. - /// - /// If the returned value is `true`, the value is added at the end of - /// any existing list, otherwise it is inserted at the beginning. - /// - /// # Unsafety - /// - /// `object` is not checked to be a valid null-terminated string. - unsafe fn add_string(&mut self, object: &[u8], value: &str) -> bool { - let value = CString::new(&value[..]).unwrap(); - let value = value.as_ptr(); - - FcPatternAddString(self.as_ptr(), object.as_ptr() as *mut c_char, value as *mut FcChar8) - == 1 - } - - unsafe fn add_integer(&self, object: &[u8], int: isize) -> bool { - FcPatternAddInteger(self.as_ptr(), object.as_ptr() as *mut c_char, int as c_int) == 1 - } - - unsafe fn add_double(&self, object: &[u8], value: f64) -> bool { - FcPatternAddDouble(self.as_ptr(), object.as_ptr() as *mut c_char, value as c_double) == 1 - } - - unsafe fn get_string<'a>(&'a self, object: &'a [u8]) -> StringPropertyIter<'a> { - StringPropertyIter::new(self, object) - } - - unsafe fn get_integer<'a>(&'a self, object: &'a [u8]) -> IntPropertyIter<'a> { - IntPropertyIter::new(self, object) - } - - unsafe fn get_double<'a>(&'a self, object: &'a [u8]) -> DoublePropertyIter<'a> { - DoublePropertyIter::new(self, object) - } - - unsafe fn get_boolean<'a>(&'a self, object: &'a [u8]) -> BooleanPropertyIter<'a> { - BooleanPropertyIter::new(self, object) - } - - pub fn hintstyle(&self) -> HintStylePropertyIter { - HintStylePropertyIter::new(self) - } - - pub fn lcdfilter(&self) -> LcdFilterPropertyIter { - LcdFilterPropertyIter::new(self) - } - - pub fn set_slant(&mut self, slant: Slant) -> bool { - unsafe { self.add_integer(b"slant\0", slant as isize) } - } - - pub fn add_pixelsize(&mut self, size: f64) -> bool { - unsafe { self.add_double(b"pixelsize\0", size) } - } - - pub fn set_weight(&mut self, weight: Weight) -> bool { - unsafe { self.add_integer(b"weight\0", weight as isize) } - } - - pub fn set_width(&mut self, width: Width) -> bool { - unsafe { self.add_integer(b"width\0", width.to_isize()) } - } - - pub fn get_width(&self) -> Option<Width> { - unsafe { self.get_integer(b"width\0").next().map(Width::from) } - } - - pub fn rgba(&self) -> RgbaPropertyIter { - RgbaPropertyIter::new(self, b"rgba\0") - } - - pub fn set_rgba(&self, rgba: &Rgba) -> bool { - unsafe { self.add_integer(b"rgba\0", rgba.to_isize()) } - } - - pub fn render_prepare(&self, config: &ConfigRef, request: &PatternRef) -> Pattern { - unsafe { - let ptr = FcFontRenderPrepare(config.as_ptr(), self.as_ptr(), request.as_ptr()); - Pattern::from_ptr(ptr) - } - } - - pub fn hash(&self) -> PatternHash { - unsafe { PatternHash(FcPatternHash(self.as_ptr())) } - } - - /// Add charset to the pattern. - /// - /// The referenced charset is copied by Fontconfig internally using - /// FcValueSave so that no references to application provided memory are - /// retained. That is, the CharSet can be safely dropped immediately - /// after being added to the pattern. - pub fn add_charset(&self, charset: &CharSetRef) -> bool { - unsafe { - FcPatternAddCharSet( - self.as_ptr(), - b"charset\0".as_ptr() as *mut c_char, - charset.as_ptr(), - ) == 1 - } - } - - /// Get charset from the pattern. - pub fn get_charset(&self) -> Option<&CharSetRef> { - unsafe { - let mut charset = ptr::null_mut(); - - let result = FcPatternGetCharSet( - self.as_ptr(), - b"charset\0".as_ptr() as *mut c_char, - 0, - &mut charset, - ); - - if result == FcResultMatch { - Some(&*(charset as *const CharSetRef)) - } else { - None - } - } - } - - /// Get matrix from the pattern. - pub fn get_matrix(&self) -> Option<FcMatrix> { - unsafe { - let mut matrix = ptr::null_mut(); - let result = FcPatternGetMatrix( - self.as_ptr(), - b"matrix\0".as_ptr() as *mut c_char, - 0, - &mut matrix, - ); - - if result == FcResultMatch { - Some(*matrix) - } else { - None - } - } - } - - pub fn file(&self, index: usize) -> Option<PathBuf> { - unsafe { self.get_string(b"file\0").nth(index) }.map(From::from) - } - - pub fn ft_face_location(&self, index: usize) -> Option<FTFaceLocation> { - match (self.file(index), self.index().next()) { - (Some(path), Some(index)) => Some(FTFaceLocation::new(path, index)), - _ => None, - } - } - - pub fn config_substitute(&mut self, config: &ConfigRef, kind: MatchKind) { - unsafe { - FcConfigSubstitute(config.as_ptr(), self.as_ptr(), kind as u32); - } - } - - pub fn default_substitute(&mut self) { - unsafe { - FcDefaultSubstitute(self.as_ptr()); - } - } -} |