use font_descriptor;
use font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors};
use font_manager::{
CTFontManagerCopyAvailableFontFamilyNames, CTFontManagerCopyAvailablePostScriptNames,
};
use core_foundation::array::{CFArray, CFArrayRef};
use core_foundation::base::{CFTypeID, TCFType};
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use core_foundation::number::CFNumber;
use core_foundation::set::CFSet;
use core_foundation::string::{CFString, CFStringRef};
use std::os::raw::c_void;
#[repr(C)]
pub struct __CTFontCollection(c_void);
pub type CTFontCollectionRef = *const __CTFontCollection;
declare_TCFType! {
CTFontCollection, CTFontCollectionRef
}
impl_TCFType!(
CTFontCollection,
CTFontCollectionRef,
CTFontCollectionGetTypeID
);
impl_CFTypeDescription!(CTFontCollection);
impl CTFontCollection {
pub fn get_descriptors(&self) -> Option<CFArray<CTFontDescriptor>> {
unsafe {
let font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(self.0);
if font_descriptors.is_null() {
None
} else {
Some(CFArray::wrap_under_get_rule(font_descriptors))
}
}
}
}
pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection {
unsafe {
let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from(1i64);
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(),
);
CTFontCollection::wrap_under_create_rule(font_collection_ref)
}
}
pub fn create_for_all_families() -> CTFontCollection {
unsafe {
let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from(1i64);
let options = CFDictionary::from_CFType_pairs(&[(key.as_CFType(), value.as_CFType())]);
let font_collection_ref =
CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef());
CTFontCollection::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::wrap_under_get_rule(kCTFontFamilyNameAttribute);
let family_name: CFString = family.parse().unwrap();
let specified_attrs =
CFDictionary::from_CFType_pairs(&[(family_attr.clone(), 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.is_null() {
return None;
}
let matched_descs = CFArray::wrap_under_create_rule(matched_descs);
Some(new_from_descriptors(&matched_descs))
}
}
pub fn get_family_names() -> CFArray<CFString> {
unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames()) }
}
pub fn get_postscript_names() -> CFArray<CFString> {
unsafe { CFArray::wrap_under_create_rule(CTFontManagerCopyAvailablePostScriptNames()) }
}
extern "C" {
static kCTFontCollectionRemoveDuplicatesOption: CFStringRef;
fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef;
fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef)
-> CFArrayRef;
fn CTFontCollectionCreateWithFontDescriptors(
descriptors: CFArrayRef,
options: CFDictionaryRef,
) -> CTFontCollectionRef;
fn CTFontCollectionGetTypeID() -> CFTypeID;
}