use alloc::vec::Vec;
use core::ffi::c_void;
use std::os::raw::{c_char, c_long, c_uchar};
use std::path::PathBuf;
#[repr(C)]
pub(crate) struct __CFArray(c_void);
#[repr(C)]
pub(crate) struct __CFURL(c_void);
type CFArrayRef = *const __CFArray;
type CFURLRef = *const __CFURL;
type CFIndex = c_long;
#[link(name = "CoreText", kind = "framework")]
#[link(name = "CoreFoundation", kind = "framework")]
extern "C" {
fn CTFontManagerCopyAvailableFontURLs() -> CFArrayRef;
fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *const c_void;
fn CFURLGetFileSystemRepresentation(
url: CFURLRef,
resolve_against_base: bool,
buffer: *mut c_uchar,
max_buf_len: CFIndex,
) -> bool;
fn CFRelease(cf: *const c_void);
}
pub(crate) fn copy_available_font_urls() -> Vec<PathBuf> {
let mut out: Vec<PathBuf> = Vec::new();
unsafe {
let urls_array: CFArrayRef = CTFontManagerCopyAvailableFontURLs();
if urls_array.is_null() {
return out;
}
let count = CFArrayGetCount(urls_array);
out.reserve(count.max(0) as usize);
let mut buf = [0u8; 4096];
for i in 0..count {
let url = CFArrayGetValueAtIndex(urls_array, i) as CFURLRef;
if url.is_null() {
continue;
}
let ok = CFURLGetFileSystemRepresentation(
url,
true,
buf.as_mut_ptr(),
buf.len() as CFIndex,
);
if !ok {
continue;
}
let nul_idx = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
if nul_idx == 0 {
continue;
}
let s = core::str::from_utf8(&buf[..nul_idx]).unwrap_or("");
if !s.is_empty() {
out.push(PathBuf::from(s));
}
}
CFRelease(urls_array as *const c_void);
}
out
}