pub mod system_fonts {
use core_text::font_descriptor::*;
use core_text::font_descriptor;
use core_text;
use std::fs::File;
use std::mem;
use std::ptr;
use core_foundation::string::CFString;
use core_foundation::number::CFNumber;
use core_foundation::array::CFArray;
use core_foundation::dictionary::CFDictionary;
use core_foundation::base::{CFType, TCFType};
use core_foundation::url::CFURL;
use libc::c_int;
use std::io::Read;
pub type FontProperty = CTFontDescriptor;
pub struct FontPropertyBuilder {
symbolic_traits: CTFontSymbolicTraits,
family: String
}
impl FontPropertyBuilder {
pub fn new() -> FontPropertyBuilder {
FontPropertyBuilder{ symbolic_traits: 0, family: String::new()}
}
pub fn italic(mut self) -> FontPropertyBuilder {
self.symbolic_traits |= kCTFontItalicTrait;
self
}
pub fn oblique(self) -> FontPropertyBuilder {
self.italic()
}
pub fn monospace(mut self) -> FontPropertyBuilder {
self.symbolic_traits |= kCTFontMonoSpaceTrait;
self
}
pub fn bold(mut self) -> FontPropertyBuilder {
self.symbolic_traits |= kCTFontBoldTrait;
self
}
pub fn family(mut self, name: &str) -> FontPropertyBuilder {
self.family = name.to_string();
self
}
pub fn build(self) -> FontProperty {
let family_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute) };
let family_name: CFString = self.family.parse().unwrap();
let traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontTraitsAttribute) };
let symbolic_traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontSymbolicTrait) };
let traits = CFDictionary::from_CFType_pairs(&[(symbolic_traits_attr.as_CFType(), CFNumber::from(self.symbolic_traits as i32).as_CFType())]);
let mut attributes = Vec::new();
attributes.push((traits_attr, traits.as_CFType()));
if self.family.len() != 0 {
attributes.push((family_attr, family_name.as_CFType()));
}
let attributes = CFDictionary::from_CFType_pairs(&attributes);
font_descriptor::new_from_attributes(&attributes)
}
}
pub fn get(config: &FontProperty) -> Option<(Vec<u8>, c_int)> {
let mut buffer = Vec::new();
let url: CFURL;
unsafe {
let value =
CTFontDescriptorCopyAttribute(config.as_concrete_TypeRef(), kCTFontURLAttribute);
if value.is_null() {
return None
}
let value: CFType = TCFType::wrap_under_get_rule(value);
if !value.instance_of::<CFURL>() {
return None
}
url = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
}
if let Some(path) = url.to_path() {
match File::open(path).and_then(|mut f| f.read_to_end(&mut buffer)) {
Ok(_) => return Some((buffer, 0)),
Err(_) => return None,
}
};
return None
}
pub fn query_all() -> Vec<String> {
core_text::font_collection::get_family_names()
.iter()
.map(|family_name| family_name.to_string())
.collect()
}
pub fn query_specific(property: &mut FontProperty) -> Vec<String> {
let descs: CFArray<CTFontDescriptor> = unsafe {
let descs = CTFontDescriptorCreateMatchingFontDescriptors(
property.as_concrete_TypeRef(),
ptr::null(),
);
TCFType::wrap_under_create_rule(descs)
};
descs
.iter()
.map(|desc| desc.family_name())
.collect::<Vec<_>>()
}
}