--- lib/font.ml 2023-03-21 18:21:51.000000000 +0800 +++ lib/font.ml 2025-10-18 14:53:28.000000000 +0800 @@ -72,11 +72,25 @@ let atts_of_desc d = (d.underline, d.strikethrough, d.kerning, d.outline) let font_exts = ref [".ttf"] -let font_dirs = ref - [ Filename.current_dir_name, false ; - "/usr/share/fonts/truetype", true ; + +let candidate_font_dirs = + [ + Filename.current_dir_name, false ; + "@PREFIX@/share/fonts/truetype", true ; + "/opt/local/share/fonts", true ; (* MacPorts *) + "/Library/Fonts", false ; (* macOS user-visible fonts *) + "/System/Library/Fonts", false ; (* macOS system fonts *) ] +let dir_exists d = + try + match (Unix.stat d).Unix.st_kind with + | Unix.S_DIR -> true + | _ -> false + with _ -> false + +let font_dirs = ref (List.filter (fun (d,_) -> dir_exists d) candidate_font_dirs) + let fonts = ref SMap.empty let add_font ?(close=false) size file fn = @@ -167,31 +181,37 @@ let mutex = Lwt_mutex.create () in let rec iter size recur dir = Log.debug (fun m -> m "Loading fonts from directory %s" dir); - let stream = Lwt_unix.files_of_directory dir in - let%lwt l = Lwt_stream.to_list stream in - Lwt_list.iter_p - (fun e -> - if e = Filename.parent_dir_name || - e = Filename.current_dir_name - then - Lwt.return_unit - else - ( - let e = Filename.concat dir e in - match%lwt Lwt_unix.stat e with - | exception _ -> Lwt.return_unit - | { Unix.st_kind = S_REG } -> - Lwt_mutex.with_lock mutex - (fun () -> Lwt.return(may_load_font size e)) - | { st_kind = S_DIR } -> - if recur then - iter size recur e - else - Lwt.return_unit - | _ -> Lwt.return_unit - ) - ) - l + (* Guard directory existence again just in case the dir disappeared *) + match%lwt + (try Lwt.return (dir_exists dir) with _ -> Lwt.return_false) + with + | false -> Lwt.return_unit + | true -> + let stream = Lwt_unix.files_of_directory dir in + let%lwt l = Lwt_stream.to_list stream in + Lwt_list.iter_p + (fun e -> + if e = Filename.parent_dir_name || + e = Filename.current_dir_name + then + Lwt.return_unit + else + ( + let e = Filename.concat dir e in + match%lwt Lwt_unix.stat e with + | exception _ -> Lwt.return_unit + | { Unix.st_kind = S_REG } -> + Lwt_mutex.with_lock mutex + (fun () -> Lwt.return(may_load_font size e)) + | { st_kind = S_DIR } -> + if recur then + iter size recur e + else + Lwt.return_unit + | _ -> Lwt.return_unit + ) + ) + l in iter