diff options
Diffstat (limited to 'font/src/ft/list_fonts.rs')
-rw-r--r-- | font/src/ft/list_fonts.rs | 586 |
1 files changed, 0 insertions, 586 deletions
diff --git a/font/src/ft/list_fonts.rs b/font/src/ft/list_fonts.rs deleted file mode 100644 index 18cc5007..00000000 --- a/font/src/ft/list_fonts.rs +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2016 Joe Wilm, The Alacritty Project Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -pub mod fc { - use std::ptr; - use std::ffi::{CStr, CString}; - use std::str; - use std::ops::Deref; - use std::path::PathBuf; - - use foreign_types::{ForeignType, ForeignTypeRef}; - - use libc::{c_char, c_int}; - use fontconfig::fontconfig as ffi; - - use self::ffi::{FcConfigGetCurrent, FcConfigGetFonts, FcSetSystem, FcSetApplication}; - use self::ffi::{FcPatternGetString, FcPatternCreate, FcPatternAddString}; - use self::ffi::{FcPatternGetInteger, FcPatternAddInteger}; - use self::ffi::{FcObjectSetCreate, FcObjectSetAdd}; - use self::ffi::{FcResultMatch, FcResultNoMatch, FcFontSetList}; - use self::ffi::{FcChar8, FcConfig, FcPattern, FcFontSet, FcObjectSet}; - use self::ffi::{FcFontSetDestroy, FcPatternDestroy, FcObjectSetDestroy, FcConfigDestroy}; - use self::ffi::{FcFontMatch, FcFontList, FcFontSort, FcConfigSubstitute, FcDefaultSubstitute}; - use self::ffi::{FcMatchFont, FcMatchPattern, FcMatchScan, FC_SLANT_ITALIC, FC_SLANT_ROMAN}; - use self::ffi::{FC_SLANT_OBLIQUE}; - use self::ffi::{FC_WEIGHT_THIN, FC_WEIGHT_EXTRALIGHT, FC_WEIGHT_LIGHT}; - use self::ffi::{FC_WEIGHT_BOOK, FC_WEIGHT_REGULAR, FC_WEIGHT_MEDIUM, FC_WEIGHT_SEMIBOLD}; - use self::ffi::{FC_WEIGHT_BOLD, FC_WEIGHT_EXTRABOLD, FC_WEIGHT_BLACK, FC_WEIGHT_EXTRABLACK}; - use self::ffi::{FcCharSet, FcCharSetDestroy, FcPatternAddCharSet, FcCharSetAddChar}; - use self::ffi::{FcCharSetCreate}; - - /// Iterator over a font set - pub struct FontSetIter<'a> { - font_set: &'a FontSetRef, - num_fonts: usize, - current: usize, - } - - foreign_type! { - type CType = FcPattern; - fn drop = FcPatternDestroy; - pub struct Pattern; - pub struct PatternRef; - } - - foreign_type! { - type CType = FcConfig; - fn drop = FcConfigDestroy; - pub struct Config; - pub struct ConfigRef; - } - - foreign_type! { - type CType = FcObjectSet; - fn drop = FcObjectSetDestroy; - pub struct ObjectSet; - pub struct ObjectSetRef; - } - - foreign_type! { - type CType = FcFontSet; - fn drop = FcFontSetDestroy; - pub struct FontSet; - pub struct FontSetRef; - } - - foreign_type! { - type CType = FcCharSet; - fn drop = FcCharSetDestroy; - pub struct CharSet; - pub struct CharSetRef; - } - - impl ObjectSet { - #[allow(dead_code)] - pub fn new() -> ObjectSet { - ObjectSet(unsafe { - FcObjectSetCreate() - }) - } - } - - /// Find the font closest matching the provided pattern. - pub fn font_match( - config: &ConfigRef, - pattern: &mut PatternRef, - ) -> Option<Pattern> { - pattern.config_subsitute(config, MatchKind::Pattern); - pattern.default_substitute(); - - 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 - #[allow(dead_code)] - pub fn font_sort( - config: &ConfigRef, - pattern: &mut PatternRef, - ) -> Option<FontSet> { - pattern.config_subsitute(config, MatchKind::Pattern); - pattern.default_substitute(); - - unsafe { - // What is this result actually used for? Seems redundant with - // return type. - let mut result = FcResultNoMatch; - - let mut charsets: *mut FcCharSet = ptr::null_mut(); - - let ptr = FcFontSort( - config.as_ptr(), - pattern.as_ptr(), - 0, // false - &mut charsets, - &mut result, - ); - - if ptr.is_null() { - None - } else { - Some(FontSet::from_ptr(ptr)) - } - } - } - - /// List fonts matching pattern - #[allow(dead_code)] - pub fn font_list( - config: &ConfigRef, - pattern: &mut PatternRef, - objects: &ObjectSetRef, - ) -> Option<FontSet> { - pattern.config_subsitute(config, MatchKind::Pattern); - pattern.default_substitute(); - - unsafe { - let ptr = FcFontList( - config.as_ptr(), - pattern.as_ptr(), - objects.as_ptr(), - ); - - if ptr.is_null() { - None - } else { - Some(FontSet::from_ptr(ptr)) - } - } - } - - 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"); - } - } - - macro_rules! pattern_add_string { - ($($name:ident => $object:expr),*) => { - $( - #[inline] - pub fn $name(&mut self, value: &str) -> bool { - unsafe { - self.add_string($object, value) - } - } - )* - } - } - - impl Pattern { - pub fn new() -> Pattern { - Pattern(unsafe { FcPatternCreate() }) - } - } - - /// 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, - } - - pub unsafe fn char8_to_string(fc_str: *mut FcChar8) -> String { - str::from_utf8(CStr::from_ptr(fc_str as *const c_char).to_bytes()).unwrap().to_owned() - } - - macro_rules! pattern_get_string { - ($($method:ident() => $property:expr),+) => { - $( - pub fn $method(&self, id: isize) -> Option<String> { - unsafe { - self.get_string($property, id) - } - } - )+ - }; - } - - macro_rules! pattern_get_integer { - ($($method:ident() => $property:expr),+) => { - $( - pub fn $method(&self, id: isize) -> Option<isize> { - let mut index = 0 as c_int; - unsafe { - let result = FcPatternGetInteger( - self.as_ptr(), - $property.as_ptr() as *mut c_char, - id as c_int, - &mut index - ); - - if result == FcResultMatch { - Some(index as isize) - } else { - None - } - } - } - )+ - }; - } - - #[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, - } - - impl CharSet { - pub fn new() -> CharSet { - CharSet(unsafe { FcCharSetCreate() }) - } - } - - impl CharSetRef { - pub fn add(&mut self, glyph: char) -> bool { - unsafe { - FcCharSetAddChar( - self.as_ptr(), - glyph as _ - ) == 1 - } - } - } - - impl PatternRef { - /// 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 get_string(&self, object: &[u8], index: isize) -> Option<String> { - let mut format: *mut FcChar8 = ptr::null_mut(); - - let result = FcPatternGetString( - self.as_ptr(), - object.as_ptr() as *mut c_char, - index as c_int, - &mut format - ); - - if result == FcResultMatch { - Some(char8_to_string(format)) - } else { - None - } - } - - pattern_add_string! { - add_family => b"family\0", - add_style => b"style\0" - } - - pub fn set_slant(&mut self, slant: Slant) -> bool { - unsafe { - self.add_integer(b"slant\0", slant as isize) - } - } - - pub fn set_weight(&mut self, weight: Weight) -> bool { - unsafe { - self.add_integer(b"weight\0", weight as isize) - } - } - - - /// 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 - } - } - - pub fn file(&self, index: isize) -> Option<PathBuf> { - unsafe { - self.get_string(b"file\0", index) - }.map(From::from) - } - - pattern_get_string! { - fontformat() => b"fontformat\0", - family() => b"family\0", - style() => b"style\0" - } - - pattern_get_integer! { - index() => b"index\0" - } - - pub fn config_subsitute(&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()); - } - } - } - - impl<'a> IntoIterator for &'a FontSet { - type Item = &'a PatternRef; - type IntoIter = FontSetIter<'a>; - fn into_iter(self) -> FontSetIter<'a> { - let num_fonts = unsafe { - (*self.as_ptr()).nfont as isize - }; - - info!("num fonts = {}", num_fonts); - - FontSetIter { - font_set: self.deref(), - num_fonts: num_fonts as _, - current: 0, - } - } - } - - impl<'a> IntoIterator for &'a FontSetRef { - type Item = &'a PatternRef; - type IntoIter = FontSetIter<'a>; - fn into_iter(self) -> FontSetIter<'a> { - let num_fonts = unsafe { - (*self.as_ptr()).nfont as isize - }; - - info!("num fonts = {}", num_fonts); - - FontSetIter { - font_set: self, - num_fonts: num_fonts as _, - current: 0, - } - } - } - - impl<'a> Iterator for FontSetIter<'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.offset(self.current as isize); - PatternRef::from_ptr(ptr) - }; - - self.current += 1; - Some(pattern) - } - } - } - - 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(raw) - } - } - - 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<'a>(&'a self, set: SetName) -> &'a FontSetRef { - unsafe { - let ptr = FcConfigGetFonts(self.as_ptr(), set as u32); - FontSetRef::from_ptr(ptr) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::fc; - - #[test] - fn font_match() { - let mut pattern = fc::Pattern::new(); - pattern.add_family("monospace"); - pattern.add_style("regular"); - - let config = fc::Config::get_current(); - let font = fc::font_match(config, &mut pattern).expect("match font monospace"); - - print!("family={:?}", font.family(0)); - for i in 0.. { - if let Some(style) = font.style(i) { - print!(", style={:?}, ", style); - } else { - break; - } - } - info!(""); - } - - #[test] - fn font_sort() { - let mut pattern = fc::Pattern::new(); - pattern.add_family("monospace"); - pattern.set_slant(fc::Slant::Italic); - - let config = fc::Config::get_current(); - let fonts = fc::font_sort(config, &mut pattern) - .expect("sort font monospace"); - - for font in fonts.into_iter().take(10) { - print!("family={:?}", font.family(0)); - for i in 0.. { - if let Some(style) = font.style(i) { - print!(", style={:?}", style); - } else { - break; - } - } - println!(""); - } - } - - #[test] - fn font_sort_with_glyph() { - let mut charset = fc::CharSet::new(); - charset.add('💖'); - let mut pattern = fc::Pattern::new(); - pattern.add_charset(&charset); - drop(charset); - - let config = fc::Config::get_current(); - let fonts = fc::font_sort(config, &mut pattern).expect("font_sort"); - - for font in fonts.into_iter().take(10) { - print!("family={:?}", font.family(0)); - for i in 0.. { - if let Some(style) = font.style(i) { - print!(", style={:?}", style); - } else { - break; - } - } - println!(""); - } - } -} |