Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T05:39:46.733Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

open_type.rs

192 lines · 7.2 KB · rust
1#![allow(unused, non_upper_case_globals)]
2
3use cocoa::appkit::CGFloat;
4use core_foundation::{
5    array::{
6        CFArray, CFArrayAppendArray, CFArrayAppendValue, CFArrayCreateMutable, CFArrayGetCount,
7        CFArrayGetValueAtIndex, CFArrayRef, CFMutableArrayRef, kCFTypeArrayCallBacks,
8    },
9    base::{CFRelease, TCFType, kCFAllocatorDefault},
10    dictionary::{
11        CFDictionaryCreate, kCFTypeDictionaryKeyCallBacks, kCFTypeDictionaryValueCallBacks,
12    },
13    number::CFNumber,
14    string::{CFString, CFStringRef},
15};
16use core_foundation_sys::locale::CFLocaleCopyPreferredLanguages;
17use core_graphics::{display::CFDictionary, geometry::CGAffineTransform};
18use core_text::font_descriptor::{
19    TraitAccessors, kCTFontFamilyNameAttribute, kCTFontItalicTrait, kCTFontSlantTrait,
20    kCTFontTraitsAttribute, kCTFontWeightTrait, kCTFontWidthTrait,
21};
22use core_text::{
23    font::{CTFont, CTFontRef, cascade_list_for_languages},
24    font_descriptor::{
25        CTFontDescriptor, CTFontDescriptorCopyAttributes, CTFontDescriptorCreateCopyWithFeature,
26        CTFontDescriptorCreateWithAttributes, CTFontDescriptorCreateWithNameAndSize,
27        CTFontDescriptorRef, kCTFontCascadeListAttribute, kCTFontFeatureSettingsAttribute,
28    },
29};
30use font_kit::font::Font as FontKitFont;
31use gpui::{FontFallbacks, FontFeatures};
32use std::ptr;
33
34pub fn apply_features_and_fallbacks(
35    font: &mut FontKitFont,
36    features: &FontFeatures,
37    fallbacks: Option<&FontFallbacks>,
38) -> anyhow::Result<()> {
39    unsafe {
40        let mut keys = vec![kCTFontFeatureSettingsAttribute];
41        let mut values = vec![generate_feature_array(features)];
42        if let Some(fallbacks) = fallbacks
43            && !fallbacks.fallback_list().is_empty()
44        {
45            keys.push(kCTFontCascadeListAttribute);
46            values.push(generate_fallback_array(fallbacks, font));
47        }
48        let attrs = CFDictionaryCreate(
49            kCFAllocatorDefault,
50            keys.as_ptr() as _,
51            values.as_ptr() as _,
52            keys.len() as isize,
53            &kCFTypeDictionaryKeyCallBacks,
54            &kCFTypeDictionaryValueCallBacks,
55        );
56
57        for value in &values {
58            CFRelease(*value as _);
59        }
60
61        let new_descriptor = CTFontDescriptorCreateWithAttributes(attrs);
62        CFRelease(attrs as _);
63        let new_descriptor = CTFontDescriptor::wrap_under_create_rule(new_descriptor);
64        let new_font = CTFontCreateCopyWithAttributes(
65            font.native_font().as_concrete_TypeRef(),
66            0.0,
67            std::ptr::null(),
68            new_descriptor.as_concrete_TypeRef(),
69        );
70        let new_font = CTFont::wrap_under_create_rule(new_font);
71        *font = font_kit::font::Font::from_native_font(&new_font);
72
73        Ok(())
74    }
75}
76
77fn generate_feature_array(features: &FontFeatures) -> CFMutableArrayRef {
78    unsafe {
79        let feature_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
80        for (tag, value) in features.tag_value_list() {
81            let keys = [kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue];
82            let values = [
83                CFString::new(tag).as_CFTypeRef(),
84                CFNumber::from(*value as i32).as_CFTypeRef(),
85            ];
86            let dict = CFDictionaryCreate(
87                kCFAllocatorDefault,
88                &keys as *const _ as _,
89                &values as *const _ as _,
90                2,
91                &kCFTypeDictionaryKeyCallBacks,
92                &kCFTypeDictionaryValueCallBacks,
93            );
94            values.into_iter().for_each(|value| CFRelease(value));
95            CFArrayAppendValue(feature_array, dict as _);
96            CFRelease(dict as _);
97        }
98        feature_array
99    }
100}
101
102fn generate_fallback_array(fallbacks: &FontFallbacks, font: &mut FontKitFont) -> CFMutableArrayRef {
103    unsafe {
104        let symbolic_traits = font.native_font().symbolic_traits();
105        let all_traits = font.native_font().all_traits();
106
107        let fallback_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
108        for user_fallback in fallbacks.fallback_list() {
109            let name = CFString::from(user_fallback.as_str());
110
111            let traits_keys = [kCTFontWeightTrait, kCTFontSlantTrait];
112            let weight_value = CFNumber::from(all_traits.normalized_weight());
113            let slant_value = CFNumber::from(if (symbolic_traits & kCTFontItalicTrait) != 0 {
114                1.0
115            } else {
116                0.0
117            });
118            let traits_values = [weight_value.as_CFTypeRef(), slant_value.as_CFTypeRef()];
119            let traits = CFDictionaryCreate(
120                kCFAllocatorDefault,
121                &traits_keys as *const _ as _,
122                &traits_values as *const _ as _,
123                traits_keys.len() as isize,
124                &kCFTypeDictionaryKeyCallBacks,
125                &kCFTypeDictionaryValueCallBacks,
126            );
127            drop(weight_value);
128            drop(slant_value);
129
130            let attr_keys = [kCTFontFamilyNameAttribute, kCTFontTraitsAttribute];
131            let attr_values = [name.as_CFTypeRef(), traits as _];
132            let attrs = CFDictionaryCreate(
133                kCFAllocatorDefault,
134                &attr_keys as *const _ as _,
135                &attr_values as *const _ as _,
136                attr_keys.len() as isize,
137                &kCFTypeDictionaryKeyCallBacks,
138                &kCFTypeDictionaryValueCallBacks,
139            );
140            CFRelease(traits as _);
141
142            let fallback_desc = CTFontDescriptorCreateWithAttributes(attrs);
143            CFRelease(attrs as _);
144
145            CFArrayAppendValue(fallback_array, fallback_desc as _);
146            CFRelease(fallback_desc as _);
147        }
148
149        let font_ref = font.native_font().as_concrete_TypeRef();
150        append_system_fallbacks(fallback_array, font_ref);
151        fallback_array
152    }
153}
154
155fn append_system_fallbacks(fallback_array: CFMutableArrayRef, font_ref: CTFontRef) {
156    unsafe {
157        let preferred_languages: CFArray<CFString> =
158            CFArray::wrap_under_create_rule(CFLocaleCopyPreferredLanguages());
159
160        let default_fallbacks = CTFontCopyDefaultCascadeListForLanguages(
161            font_ref,
162            preferred_languages.as_concrete_TypeRef(),
163        );
164        let default_fallbacks: CFArray<CTFontDescriptor> =
165            CFArray::wrap_under_create_rule(default_fallbacks);
166
167        for desc in default_fallbacks
168            .iter()
169            .filter(|desc| desc.font_path().is_some())
170        {
171            CFArrayAppendValue(fallback_array, desc.as_concrete_TypeRef() as _);
172        }
173    }
174}
175
176#[link(name = "CoreText", kind = "framework")]
177unsafe extern "C" {
178    static kCTFontOpenTypeFeatureTag: CFStringRef;
179    static kCTFontOpenTypeFeatureValue: CFStringRef;
180
181    fn CTFontCreateCopyWithAttributes(
182        font: CTFontRef,
183        size: CGFloat,
184        matrix: *const CGAffineTransform,
185        attributes: CTFontDescriptorRef,
186    ) -> CTFontRef;
187    fn CTFontCopyDefaultCascadeListForLanguages(
188        font: CTFontRef,
189        languagePrefList: CFArrayRef,
190    ) -> CFArrayRef;
191}
192
Served at tenant.openagents/omega Member data and write actions are omitted.