1use crate::{
4 util::{path_to_c, str_to_c},
5 AddonApi, FontApi, Revertible,
6};
7use imgui::sys::{ImFont, ImFontConfig};
8use std::{
9 ffi::{c_char, c_void},
10 path::Path,
11};
12use windows::Win32::Foundation::HMODULE;
13
14pub type RawFontReceive = unsafe extern "C-unwind" fn(identifier: *const c_char, font: *mut ImFont);
15
16pub type RawFontGet =
17 unsafe extern "C-unwind" fn(identifier: *const c_char, callback: RawFontReceive);
18
19pub type RawFontRelease =
20 unsafe extern "C-unwind" fn(identifier: *const c_char, callback: RawFontReceive);
21
22pub type RawFontAddFromFile = unsafe extern "C-unwind" fn(
23 identifier: *const c_char,
24 font_size: f32,
25 filename: *const c_char,
26 callback: RawFontReceive,
27 config: *mut ImFontConfig,
28);
29
30pub type RawFontAddFromResource = unsafe extern "C-unwind" fn(
31 identifier: *const c_char,
32 font_size: f32,
33 resource_id: u32,
34 module: HMODULE,
35 callback: RawFontReceive,
36 config: *mut ImFontConfig,
37);
38
39pub type RawFontAddFromMemory = unsafe extern "C-unwind" fn(
40 identifier: *const c_char,
41 font_size: f32,
42 data: *const c_void,
43 size: usize,
44 callback: RawFontReceive,
45 config: *mut ImFontConfig,
46);
47
48pub type RawFontResize = unsafe extern "C-unwind" fn(identifier: *const c_char, font_size: f32);
49
50pub fn get_font(
52 identifier: impl AsRef<str>,
53 callback: RawFontReceive,
54) -> Revertible<impl Fn() + Send + Sync + 'static> {
55 let FontApi { get, release, .. } = AddonApi::get().font;
56 let identifier = str_to_c(identifier, "failed to convert font identifier");
57 unsafe { get(identifier.as_ptr(), callback) };
58 let revert = move || unsafe { release(identifier.as_ptr(), callback) };
59 revert.into()
60}
61
62pub fn release_font(identifier: impl AsRef<str>, callback: RawFontReceive) {
64 let FontApi { release, .. } = AddonApi::get().font;
65 let identifier = str_to_c(identifier, "failed to convert font identifier");
66 unsafe { release(identifier.as_ptr(), callback) }
67}
68
69pub fn add_font_from_file(
71 identifier: impl AsRef<str>,
72 file: impl AsRef<Path>,
73 font_size: f32,
74 config: &mut ImFontConfig,
75 callback: RawFontReceive,
76) -> Revertible<impl Fn() + Send + Sync + 'static> {
77 let FontApi {
78 add_from_file,
79 release,
80 ..
81 } = AddonApi::get().font;
82 let identifier = str_to_c(identifier, "failed to convert font identifier");
83 let file = path_to_c(file, "failed to convert font file path");
84 unsafe {
85 add_from_file(
86 identifier.as_ptr(),
87 font_size,
88 file.as_ptr(),
89 callback,
90 config,
91 )
92 };
93 let revert = move || unsafe { release(identifier.as_ptr(), callback) };
94 revert.into()
95}
96
97pub fn add_font_from_resource(
99 identifier: impl AsRef<str>,
100 handle: HMODULE,
101 resource: u32,
102 font_size: f32,
103 config: &mut ImFontConfig,
104 callback: RawFontReceive,
105) -> Revertible<impl Fn() + Send + Sync + 'static> {
106 let FontApi {
107 add_from_resource,
108 release,
109 ..
110 } = AddonApi::get().font;
111 let identifier = str_to_c(identifier, "failed to convert font identifier");
112 unsafe {
113 add_from_resource(
114 identifier.as_ptr(),
115 font_size,
116 resource,
117 handle,
118 callback,
119 config,
120 )
121 };
122 let revert = move || unsafe { release(identifier.as_ptr(), callback) };
123 revert.into()
124}
125
126pub fn add_font_from_memory(
128 identifier: impl AsRef<str>,
129 data: impl AsRef<[u8]>,
130 font_size: f32,
131 config: &mut ImFontConfig,
132 callback: RawFontReceive,
133) -> Revertible<impl Fn() + Send + Sync + 'static> {
134 let FontApi {
135 add_from_memory,
136 release,
137 ..
138 } = AddonApi::get().font;
139 let identifier = str_to_c(identifier, "failed to convert font identifier");
140 let data = data.as_ref();
141 unsafe {
142 add_from_memory(
143 identifier.as_ptr(),
144 font_size,
145 data.as_ptr().cast(),
146 data.len(),
147 callback,
148 config,
149 )
150 };
151 let revert = move || unsafe { release(identifier.as_ptr(), callback) };
152 revert.into()
153}
154
155#[macro_export]
168macro_rules! font_receive {
169 ( $callback:expr $(,)? ) => {{
170 const __CALLBACK: fn(
171 &::std::primitive::str,
172 ::std::option::Option<&mut $crate::imgui::sys::ImFont>,
173 ) = $callback;
174
175 extern "C-unwind" fn __font_receive_wrapper(
176 identifier: *const ::std::ffi::c_char,
177 font: *mut $crate::imgui::sys::ImFont,
178 ) {
179 let identifier = unsafe { $crate::__macro::str_from_c(identifier) }
180 .expect("invalid identifier in font callback");
181 let font = unsafe { font.as_mut() };
182 __CALLBACK(identifier, font)
183 }
184
185 __font_receive_wrapper
186 }};
187}
188
189pub use font_receive;
190
191pub fn resize_font(identifier: impl AsRef<str>, font_size: f32) {
193 let FontApi { resize, .. } = AddonApi::get().font;
194 let identifier = str_to_c(identifier, "failed to convert font identifier");
195 unsafe { resize(identifier.as_ptr(), font_size) }
196}