1use crate::{
2 interop::{self, AsStr},
3 prelude::*,
4 FontMgr, FontStyleSet, Typeface,
5};
6use skia_bindings as sb;
7use std::{
8 fmt,
9 mem::transmute,
10 ops::{Deref, DerefMut},
11 ptr,
12};
13
14pub type TypefaceFontStyleSet = RCHandle<sb::skia_textlayout_TypefaceFontStyleSet>;
15require_base_type!(sb::skia_textlayout_TypefaceFontStyleSet, sb::SkFontStyleSet);
16
17impl NativeRefCountedBase for sb::skia_textlayout_TypefaceFontStyleSet {
18 type Base = sb::SkRefCntBase;
19}
20
21impl Deref for TypefaceFontStyleSet {
22 type Target = FontStyleSet;
23 fn deref(&self) -> &Self::Target {
24 unsafe { transmute_ref(self) }
25 }
26}
27
28impl DerefMut for TypefaceFontStyleSet {
29 fn deref_mut(&mut self) -> &mut Self::Target {
30 unsafe { transmute_ref_mut(self) }
31 }
32}
33
34impl fmt::Debug for TypefaceFontStyleSet {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f&mut DebugStruct<'_, '_>.debug_struct("TypefaceFontStyleSet")
37 .field("base", self as &FontStyleSet)
38 .field("family_name", &self.family_name())
39 .field(name:"alias", &self.alias())
40 .finish()
41 }
42}
43
44impl TypefaceFontStyleSet {
45 pub fn new(family_name: impl AsRef<str>) -> Self {
46 let family: Handle = interop::String::from_str(family_name.as_ref());
47 Self::from_ptr(unsafe { sb::C_TypefaceFontStyleSet_new(family_name:family.native()) }).unwrap()
48 }
49
50 pub fn family_name(&self) -> &str {
51 self.native().fFamilyName.as_str()
52 }
53
54 pub fn alias(&self) -> &str {
55 self.native().fAlias.as_str()
56 }
57
58 pub fn append_typeface(&mut self, typeface: Typeface) -> &mut Self {
59 unsafe { sb::C_TypefaceFontStyleSet_appendTypeface(self.native_mut(), typeface.into_ptr()) }
60 self
61 }
62}
63
64pub type TypefaceFontProvider = RCHandle<sb::skia_textlayout_TypefaceFontProvider>;
65require_base_type!(sb::skia_textlayout_TypefaceFontProvider, sb::SkFontMgr);
66
67impl NativeRefCountedBase for sb::skia_textlayout_TypefaceFontProvider {
68 type Base = sb::SkRefCntBase;
69}
70
71impl Deref for TypefaceFontProvider {
72 type Target = FontMgr;
73 fn deref(&self) -> &Self::Target {
74 unsafe { transmute_ref(self) }
75 }
76}
77
78impl DerefMut for TypefaceFontProvider {
79 fn deref_mut(&mut self) -> &mut Self::Target {
80 unsafe { transmute_ref_mut(self) }
81 }
82}
83
84impl Default for TypefaceFontProvider {
85 fn default() -> Self {
86 Self::new()
87 }
88}
89
90impl From<TypefaceFontProvider> for FontMgr {
91 fn from(provider: TypefaceFontProvider) -> Self {
92 unsafe { transmute(src:provider) }
93 }
94}
95
96impl fmt::Debug for TypefaceFontProvider {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f&mut DebugStruct<'_, '_>.debug_struct("TypefaceFontProvider")
99 .field(name:"base", self as &FontMgr)
100 .finish()
101 }
102}
103
104impl TypefaceFontProvider {
105 pub fn new() -> Self {
106 Self::from_ptr(unsafe { sb::C_TypefaceFontProvider_new() }).unwrap()
107 }
108
109 pub fn register_typeface<'a>(
110 &mut self,
111 typeface: Typeface,
112 alias: impl Into<Option<&'a str>>,
113 ) -> usize {
114 unsafe {
115 match alias.into() {
116 Some(alias) => {
117 let alias = interop::String::from_str(alias);
118 sb::C_TypefaceFontProvider_registerTypeface(
119 self.native_mut(),
120 typeface.into_ptr(),
121 alias.native(),
122 )
123 }
124 None => sb::C_TypefaceFontProvider_registerTypeface(
125 self.native_mut(),
126 typeface.into_ptr(),
127 ptr::null(),
128 ),
129 }
130 }
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::{TypefaceFontProvider, TypefaceFontStyleSet};
137 use crate::{
138 prelude::{NativeAccess, NativeRefCounted, NativeRefCountedBase},
139 textlayout::FontCollection,
140 FontMgr, FontStyle,
141 };
142
143 #[test]
144 #[serial_test::serial]
145 fn font_style_set_typeface_ref_counts() {
146 let mut style_set = TypefaceFontStyleSet::new("");
147 assert_eq!(style_set.native().ref_counted_base()._ref_cnt(), 1);
148
149 let tf = FontMgr::new()
150 .legacy_make_typeface(None, FontStyle::default())
151 .unwrap();
152 let base_cnt = tf.native().ref_counted_base()._ref_cnt();
153
154 let tfclone = tf.clone();
155 assert_eq!(tf.native().ref_counted_base()._ref_cnt(), base_cnt + 1);
156
157 style_set.append_typeface(tfclone);
158 assert_eq!(tf.native().ref_counted_base()._ref_cnt(), base_cnt + 1);
159
160 drop(style_set);
161 assert_eq!(tf.native().ref_counted_base()._ref_cnt(), base_cnt);
162 drop(tf);
163 }
164
165 #[test]
166 #[serial_test::serial]
167 fn treat_font_provider_as_font_mgr() {
168 let mut font_collection = FontCollection::new();
169 let typeface = FontMgr::new()
170 .legacy_make_typeface(None, FontStyle::default())
171 .unwrap();
172 let mut manager = TypefaceFontProvider::new();
173 manager.register_typeface(typeface, Some("AlArabiya"));
174 assert_eq!(font_collection.font_managers_count(), 0);
175 font_collection.set_asset_font_manager(Some(manager.into()));
176 assert_eq!(font_collection.font_managers_count(), 1);
177 }
178}
179