font_loader/
macos.rs

1// The MIT License (MIT)
2// Copyright (c) font-loader Developers
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5// associated documentation files (the "Software"), to deal in the Software without restriction,
6// including without limitation the rights to use, copy, modify, merge, publish, distribute,
7// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all copies or
11// substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
19/// Font loading utilities for installed system fonts
20pub mod system_fonts {
21    use core_text::font_descriptor::*;
22    use core_text::font_descriptor;
23    use core_text;
24    use std::fs::File;
25    use std::mem;
26    use std::ptr;
27    use core_foundation::string::CFString;
28    use core_foundation::number::CFNumber;
29    use core_foundation::array::CFArray;
30    use core_foundation::dictionary::CFDictionary;
31    use core_foundation::base::{CFType, TCFType};
32    use core_foundation::url::CFURL;
33    use libc::c_int;
34    use std::io::Read;
35    /// The platform specific font properties
36    pub type FontProperty = CTFontDescriptor;
37
38    /// Builder for FontProperty
39    pub struct FontPropertyBuilder {
40        symbolic_traits: CTFontSymbolicTraits,
41        family: String
42    }
43
44    impl FontPropertyBuilder {
45        pub fn new() -> FontPropertyBuilder {
46            FontPropertyBuilder{ symbolic_traits: 0, family: String::new()}
47        }
48
49        pub fn italic(mut self) -> FontPropertyBuilder {
50            self.symbolic_traits |= kCTFontItalicTrait;
51            self
52        }
53
54        pub fn oblique(self) -> FontPropertyBuilder {
55            self.italic()
56        }
57
58        pub fn monospace(mut self) -> FontPropertyBuilder {
59            self.symbolic_traits |= kCTFontMonoSpaceTrait;
60            self
61        }
62
63        pub fn bold(mut self) -> FontPropertyBuilder {
64            self.symbolic_traits |= kCTFontBoldTrait;
65            self
66        }
67
68        pub fn family(mut self, name: &str) -> FontPropertyBuilder {
69            self.family = name.to_string();
70            self
71        }
72
73        pub fn build(self) -> FontProperty {
74            let family_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute) };
75            let family_name: CFString = self.family.parse().unwrap();
76            let traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontTraitsAttribute) };
77            let symbolic_traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontSymbolicTrait) };
78            let traits = CFDictionary::from_CFType_pairs(&[(symbolic_traits_attr.as_CFType(), CFNumber::from(self.symbolic_traits as i32).as_CFType())]);
79            let mut attributes = Vec::new();
80            attributes.push((traits_attr, traits.as_CFType()));
81            if self.family.len() != 0 {
82                attributes.push((family_attr, family_name.as_CFType()));
83            }
84            let attributes = CFDictionary::from_CFType_pairs(&attributes);
85            font_descriptor::new_from_attributes(&attributes)
86        }
87    }
88
89    /// Get the binary data and index of a specific font
90    pub fn get(config: &FontProperty) -> Option<(Vec<u8>, c_int)> {
91        let mut buffer = Vec::new();
92        let url: CFURL;
93        unsafe {
94            let value =
95                CTFontDescriptorCopyAttribute(config.as_concrete_TypeRef(), kCTFontURLAttribute);
96
97            if value.is_null() {
98                return None
99            }
100
101            let value: CFType = TCFType::wrap_under_get_rule(value);
102            if !value.instance_of::<CFURL>() {
103                return None
104            }
105            url = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
106        }
107        if let Some(path) = url.to_path() {
108            match File::open(path).and_then(|mut f| f.read_to_end(&mut buffer)) {
109                Ok(_) => return Some((buffer, 0)),
110                Err(_) => return None,
111            }
112        };
113        return None
114    }
115
116    /// Query the names of all fonts installed in the system
117    pub fn query_all() -> Vec<String> {
118        core_text::font_collection::get_family_names()
119            .iter()
120            .map(|family_name| family_name.to_string())
121            .collect()
122    }
123
124    /// Query the names of specifc fonts installed in the system
125    pub fn query_specific(property: &mut FontProperty) -> Vec<String> {
126        let descs: CFArray<CTFontDescriptor> = unsafe {
127            let descs = CTFontDescriptorCreateMatchingFontDescriptors(
128                property.as_concrete_TypeRef(),
129                ptr::null(),
130            );
131            TCFType::wrap_under_create_rule(descs)
132        };
133        descs
134            .iter()
135            .map(|desc| desc.family_name())
136            .collect::<Vec<_>>()
137    }
138}