use font_descriptor;
use font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors};
use font_manager::CTFontManagerCopyAvailableFontFamilyNames;
use core_foundation::array::{CFArray, CFArrayRef};
use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use core_foundation::number::CFNumber;
use core_foundation::set::CFSet;
use core_foundation::string::{CFString, CFStringRef};
use libc::c_void;
use std::mem;
use std::ptr;
#[repr(C)]
pub struct __CTFontCollection(c_void);
pub type CTFontCollectionRef = *const __CTFontCollection;
#[derive(Debug)]
pub struct CTFontCollection {
obj: CTFontCollectionRef,
}
impl Drop for CTFontCollection {
fn drop(&mut self) {
unsafe {
CFRelease(self.as_CFTypeRef())
}
}
}
impl TCFType<CTFontCollectionRef> for CTFontCollection {
#[inline]
fn as_concrete_TypeRef(&self) -> CTFontCollectionRef {
self.obj
}
#[inline]
unsafe fn wrap_under_get_rule(reference: CTFontCollectionRef) -> CTFontCollection {
let reference: CTFontCollectionRef = mem::transmute(CFRetain(mem::transmute(reference)));
TCFType::wrap_under_create_rule(reference)
}
#[inline]
unsafe fn wrap_under_create_rule(obj: CTFontCollectionRef) -> CTFontCollection {
CTFontCollection {
obj: obj,
}
}
#[inline]
fn as_CFTypeRef(&self) -> CFTypeRef {
unsafe {
mem::transmute(self.as_concrete_TypeRef())
}
}
#[inline]
fn type_id() -> CFTypeID {
unsafe {
CTFontCollectionGetTypeID()
}
}
}
impl CTFontCollection {
pub fn get_descriptors(&self) -> CFArray {
unsafe {
TCFType::wrap_under_get_rule(CTFontCollectionCreateMatchingFontDescriptors(self.obj))
}
}
}
pub fn new_from_descriptors(descs: &CFArray) -> CTFontCollection {
unsafe {
let key: CFString = TCFType::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from_i64(1);
let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]);
let font_collection_ref =
CTFontCollectionCreateWithFontDescriptors(descs.as_concrete_TypeRef(),
options.as_concrete_TypeRef());
TCFType::wrap_under_create_rule(font_collection_ref)
}
}
pub fn create_for_all_families() -> CTFontCollection {
unsafe {
let key: CFString = TCFType::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from_i64(1);
let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]);
let font_collection_ref =
CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef());
TCFType::wrap_under_create_rule(font_collection_ref)
}
}
pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
use font_descriptor::kCTFontFamilyNameAttribute;
unsafe {
let family_attr: CFString = TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute);
let family_name: CFString = family.parse().unwrap();
let specified_attrs = CFDictionary::from_CFType_pairs(&[
(family_attr.as_CFType(), family_name.as_CFType())
]);
let wildcard_desc: CTFontDescriptor =
font_descriptor::new_from_attributes(&specified_attrs);
let mandatory_attrs = CFSet::from_slice(&[ family_attr.as_CFType() ]);
let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors(
wildcard_desc.as_concrete_TypeRef(),
mandatory_attrs.as_concrete_TypeRef());
if matched_descs == ptr::null() {
return None;
}
let matched_descs: CFArray = TCFType::wrap_under_create_rule(matched_descs);
Some(new_from_descriptors(&matched_descs))
}
}
pub fn get_family_names() -> CFArray {
unsafe {
TCFType::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames())
}
}
extern {
static kCTFontCollectionRemoveDuplicatesOption: CFStringRef;
fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef;
fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef) -> CFArrayRef;
fn CTFontCollectionCreateWithFontDescriptors(descriptors: CFArrayRef,
options: CFDictionaryRef) -> CTFontCollectionRef;
fn CTFontCollectionGetTypeID() -> CFTypeID;
}