diff --git a/font/Cargo.lock b/font/Cargo.lock index 9464e209..0b271c0c 100644 --- a/font/Cargo.lock +++ b/font/Cargo.lock @@ -10,6 +10,7 @@ dependencies = [ "ffi-util 0.1.0", "freetype-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.2.0 (git+https://github.com/jwilm/rust-fontconfig)", ] diff --git a/font/src/ft/list_fonts.rs b/font/src/ft/list_fonts.rs index 9847283f..cedd0c5e 100644 --- a/font/src/ft/list_fonts.rs +++ b/font/src/ft/list_fonts.rs @@ -29,7 +29,7 @@ pub mod fc { use self::ffi::{FcPatternGetInteger, FcPatternAddInteger}; use self::ffi::{FcObjectSetCreate, FcObjectSetAdd}; use self::ffi::{FcResultMatch, FcResultNoMatch, FcFontSetList}; - use self::ffi::{FcChar8, FcConfig, FcPattern, FcFontSet, FcObjectSet, FcCharSet}; + 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}; @@ -37,6 +37,8 @@ pub mod fc { 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> { @@ -49,6 +51,7 @@ pub mod fc { ffi_type!(Config, ConfigRef, FcConfig, FcConfigDestroy); ffi_type!(ObjectSet, ObjectSetRef, FcObjectSet, FcObjectSetDestroy); ffi_type!(FontSet, FontSetRef, FcFontSet, FcFontSetDestroy); + ffi_type!(CharSet, CharSetRef, FcCharSet, FcCharSetDestroy); impl ObjectSet { #[allow(dead_code)] @@ -291,6 +294,23 @@ pub mod fc { 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 /// @@ -353,6 +373,21 @@ pub mod fc { } } + + /// Add charset to the pattern + /// + /// The lifetimes here ensure that the charset is alive at least as long + /// as the pattern. + pub fn add_charset<'b, 'a: 'b>(&'b self, charset: &'a 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 { unsafe { self.get_string(b"file\0", index) @@ -520,7 +555,30 @@ mod tests { break; } } - info!(""); + 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); + + 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!(""); } } }