diff --git a/src/Graphics/Fonts/font.hpp b/src/Graphics/Fonts/font.hpp index 2ef474b822..49a431aef4 100644 --- a/src/Graphics/Fonts/font.hpp +++ b/src/Graphics/Fonts/font.hpp @@ -251,7 +251,6 @@ array font_database_search (string fam, string var, string series, string shape); array font_database_characteristics (string family, string style); tree font_database_substitutions (string family); -bool font_database_rev_contains (string font_file_name); // Font selection tree array_as_tuple (array a); diff --git a/src/Graphics/Fonts/font_database.cpp b/src/Graphics/Fonts/font_database.cpp index e98fb6915c..b69600e241 100644 --- a/src/Graphics/Fonts/font_database.cpp +++ b/src/Graphics/Fonts/font_database.cpp @@ -79,9 +79,7 @@ struct font_less_eq_operator { static bool fonts_loaded = false; static bool fonts_global_loaded= false; hashmap font_table (UNINIT); -hashmap font_rev_table (UNINIT); hashmap font_global_table (UNINIT); -hashmap font_global_rev_table (UNINIT); hashmap font_features (UNINIT); hashmap font_variants (UNINIT); hashmap font_characteristics (UNINIT); @@ -95,8 +93,7 @@ tuple_insert (tree& t, tree x) { } void -font_database_load_database (url u, hashmap& ftab= font_table, - hashmap& frev= font_rev_table) { +font_database_load_database (url u, hashmap& ftab= font_table) { if (!exists (u)) return; string s; if (!load_string (u, s, false)) { @@ -107,9 +104,6 @@ font_database_load_database (url u, hashmap& ftab= font_table, tree family_style = t[i][0]; tree files = t[i][1]; ftab (family_style)= files; - for (int j= 0; j < N (files); j++) { - frev (files[j][0]->label)= family_style; - } } } } @@ -241,8 +235,7 @@ void font_database_global_load () { if (fonts_global_loaded) return; cout << "TeXmacs] warning, missing font, loading global substitution list\n"; - font_database_load_database (GLOBAL_DATABASE, font_global_table, - font_global_rev_table); + font_database_load_database (GLOBAL_DATABASE, font_global_table); font_database_load_features (GLOBAL_FEATURES); font_database_load_characteristics (GLOBAL_CHARACTERISTICS); font_database_load_substitutions (GLOBAL_SUBSTITUTIONS); @@ -464,11 +457,12 @@ find_best_approximation (tree ff) { } static void -font_collect (url dir, string font_name) { +font_collect (url path) { int i; const int MAX_SUBFONTS= 512; + string font_name = as_string (tail (path)); for (i= 0; i < MAX_SUBFONTS; i++) { - int sz= file_size (dir * font_name); + int sz= file_size (path); tree ff= tuple (font_name, as_string (i), as_string (sz)); if (!back_font_table->contains (ff) && back_font_table->contains (ff (0, 2))) { @@ -512,7 +506,7 @@ font_database_collect (url u) { string suf = suffix (a[i]); array allowed= array ("ttf", "ttc", "otf", "tfm"); if (contains (suf, allowed)) { - font_collect (u, a[i]); + font_collect (u * a[i]); } } } @@ -526,7 +520,10 @@ font_database_filter () { new_font_table = hashmap (UNINIT); back_font_table= hashmap (UNINIT); build_back_table (); - font_database_collect (tt_font_path ()); + array paths= tt_font_paths (); + for (int i= 0; i < N (paths); i++) { + font_collect (paths[i]); + } font_database_collect (tfm_font_path ()); font_table = new_font_table; new_font_table = hashmap (UNINIT); @@ -709,9 +706,3 @@ font_database_substitutions (string family) { if (font_substitutions->contains (family)) return font_substitutions[family]; else return tree (TUPLE); } - -bool -font_database_rev_contains (string font_file_name) { - font_database_load (); - return font_rev_table->contains (font_file_name); -} \ No newline at end of file diff --git a/src/Plugins/Freetype/tt_file.cpp b/src/Plugins/Freetype/tt_file.cpp index 9f36c47767..5085fce8f0 100644 --- a/src/Plugins/Freetype/tt_file.cpp +++ b/src/Plugins/Freetype/tt_file.cpp @@ -16,6 +16,7 @@ #include "file.hpp" #include "font.hpp" #include "hashmap.hpp" +#include "hashset.hpp" #include "preferences.hpp" #include "scheme.hpp" #include "sys_utils.hpp" @@ -27,7 +28,8 @@ #include #endif -static hashmap tt_fonts ("no"); +static hashset tt_fonts; +static hashmap tt_font_locations; url add_to_path (url u, url d) { @@ -50,12 +52,21 @@ tt_extend_font_path (url u) { } url -tt_font_path () { +tt_font_search_path () { + // NOTICE: the order of the search path here is very important + // Please use ret= ret | u to append the url, the former appended url will + // precede the latter appended url + url ret= url_none (); string xtt= get_env ("TEXMACS_FONT_PATH"); - url xu = url_none (); - if (xtt != "") xu= search_sub_dirs (xtt); + if (!is_empty (xtt)) { + ret= ret | url (xtt); + } string ximp= get_preference ("imported fonts", ""); - if (ximp != "") xu= xu | search_sub_dirs (url_unix (ximp)); + if (!is_empty (ximp)) { + ret= ret | url_system (ximp); + } + ret= ret | url ("$TEXMACS_HOME_PATH/fonts/truetype") | + url ("$TEXMACS_PATH/fonts/truetype"); #ifdef _FONTCONFIG_H_ FcConfig* config = FcInitLoadConfig (); FcStrList* fontdirs= FcConfigGetFontDirs (config); @@ -63,108 +74,137 @@ tt_font_path () { FcStrListFirst (fontdirs); while (fontdir= FcStrListNext (fontdirs)) { - xu= xu | search_sub_dirs ((char*) fontdir); + ret= ret | url_system ((char*) fontdir); } #endif - return xu | search_sub_dirs ("$TEXMACS_HOME_PATH/fonts/truetype") | - search_sub_dirs ("$TEXMACS_PATH/fonts/truetype") | -#if defined(OS_MINGW) || defined(OS_WIN) - search_sub_dirs ("$windir/Fonts"); -#elif defined OS_MACOS - search_sub_dirs ("$HOME/Library/Fonts") | - search_sub_dirs ("/Library/Fonts") | - search_sub_dirs ("/Library/Application Support/Apple/Fonts/iLife") | - search_sub_dirs ("/Library/Application Support/Apple/Fonts/iWork") | - search_sub_dirs ("/System/Library/Fonts") | - search_sub_dirs ( - "/System/Library/PrivateFrameworks/FontServices.framework/" - "Versions/A/Resources/Fonts/ApplicationSupport") | - search_sub_dirs ("/opt/local/share/texmf-texlive/fonts/opentype") | - search_sub_dirs ("/opt/local/share/texmf-texlive/fonts/truetype") | - search_sub_dirs ( - "/opt/local/share/texmf-texlive-dist/fonts/opentype") | - search_sub_dirs ( - "/opt/local/share/texmf-texlive-dist/fonts/truetype") | - search_sub_dirs ("/usr/local/texlive/2020/texmf-dist/fonts/opentype") | - search_sub_dirs ("/usr/local/texlive/2020/texmf-dist/fonts/truetype") | - search_sub_dirs ("/usr/local/texlive/2021/texmf-dist/fonts/opentype") | - search_sub_dirs ("/usr/local/texlive/2021/texmf-dist/fonts/truetype") | - search_sub_dirs ("/usr/local/texlive/2022/texmf-dist/fonts/opentype") | - search_sub_dirs ("/usr/local/texlive/2022/texmf-dist/fonts/truetype"); -#else - search_sub_dirs ("$HOME/.fonts") | - search_sub_dirs ("/usr/share/fonts/opentype") | - search_sub_dirs ("/usr/share/fonts/truetype") | - search_sub_dirs ("/usr/local/share/fonts/opentype") | - search_sub_dirs ("/usr/local/share/fonts/truetype") | - search_sub_dirs ("/usr/share/texlive/texmf-dist/fonts/opentype") | - search_sub_dirs ("/usr/share/texlive/texmf-dist/fonts/truetype"); -#endif + if (os_win () || os_mingw ()) { + ret= ret | url ("$windir/Fonts"); + } + else if (os_macos ()) { + ret= ret | url ("$HOME/Library/Fonts") | url ("/Library/Fonts") | + url ("/Library/Application Support/Apple/Fonts/iLife") | + url ("/Library/Application Support/Apple/Fonts/iWork") | + url ("/System/Library/Fonts") | + url ("/System/Library/PrivateFrameworks/FontServices.framework/" + "Versions/A/Resources/Fonts/ApplicationSupport") | + url ("/opt/local/share/texmf-texlive/fonts/opentype") | + url ("/opt/local/share/texmf-texlive/fonts/truetype") | + url ("/opt/local/share/texmf-texlive-dist/fonts/opentype") | + url ("/opt/local/share/texmf-texlive-dist/fonts/truetype") | + url ("/usr/local/texlive/2020/texmf-dist/fonts/opentype") | + url ("/usr/local/texlive/2020/texmf-dist/fonts/truetype") | + url ("/usr/local/texlive/2021/texmf-dist/fonts/opentype") | + url ("/usr/local/texlive/2021/texmf-dist/fonts/truetype") | + url ("/usr/local/texlive/2022/texmf-dist/fonts/opentype") | + url ("/usr/local/texlive/2022/texmf-dist/fonts/truetype"); + } + else { + ret= ret | url ("$HOME/.fonts") | url ("/usr/share/fonts/opentype") | + url ("/usr/share/fonts/truetype") | + url ("/usr/local/share/fonts/opentype") | + url ("/usr/local/share/fonts/truetype") | + url ("/usr/share/texlive/texmf-dist/fonts/opentype") | + url ("/usr/share/texlive/texmf-dist/fonts/truetype"); + } + return ret; +} + +url +tt_font_path () { + bench_start ("tt_font_path"); + url xu= search_sub_dirs (tt_font_search_path ()); + bench_end ("tt_font_path"); + return xu; +} + +static void +tt_locate_all () { + url suffixes = url ("*.ttf") | url ("*.ttc") | url ("*.otf"); + url all_fonts= expand (complete (tt_font_path () * suffixes)); + url iter = all_fonts; + while (is_or (iter)) { + url font_u= iter[1]; + // eg. (basename.ttf, url(/path/to/basename.ttf)) + tt_font_locations (as_string (tail (font_u)))= font_u; + tt_fonts->insert (basename (font_u)); + iter= iter[2]; + } + url font_last = iter; + tt_font_locations (as_string (tail (font_last)))= font_last; + tt_fonts->insert (basename (font_last)); +} + +array +tt_font_paths () { + int num_of_fonts= N (tt_font_locations); + if (num_of_fonts == 0) { + tt_locate_all (); + } + array ret; + iterator it= iterate (tt_font_locations); + while (it->busy ()) { + string key= it->next (); + ret << tt_font_locations[key]; + } + return ret; +} + +static url +tt_locate_pfb (string name) { + bench_start ("tt_locate_pfb " * name); + /* + if (starts (name, "rpag")) name= "uag" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpbk")) name= "ubk" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpcr")) name= "ucr" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rphv")) name= "uhv" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpnc")) name= "unc" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rppl")) name= "upl" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpsy")) name= "usy" * name (4, N (name)); + if (starts (name, "rptm")) name= "utm" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpzc")) name= "uzc" * name (4, N (name) - 4) * "8a.pfb"; + if (starts (name, "rpzd")) name= "uzd" * name (4, N (name)); + */ + url u= resolve_tex (name * ".pfb"); + bench_end ("tt_locate_pfb " * name, 10); + return u; } static url -tt_locate (string name) { - bench_start ("tt_locate " * name); - if (ends (name, ".pfb")) { - /* - if (starts (name, "rpag")) name= "uag" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpbk")) name= "ubk" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpcr")) name= "ucr" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rphv")) name= "uhv" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpnc")) name= "unc" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rppl")) name= "upl" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpsy")) name= "usy" * name (4, N (name)); - if (starts (name, "rptm")) name= "utm" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpzc")) name= "uzc" * name (4, N (name) - 4) * "8a.pfb"; - if (starts (name, "rpzd")) name= "uzd" * name (4, N (name)); - */ - url u= resolve_tex (name); - // cout << "tt_locate: " << name << " -> " << u << "\n"; - if (!is_none (u)) { - bench_end ("tt_locate " * name, 10); - return u; +tt_fast_locate (string name) { + array suffixes; + suffixes << string("ttf") + << string("ttc") + << string("otf") + << string("dfont"); + for (int i= 0; i < N (suffixes); i++) { + if (tt_font_locations->contains (name * "." * suffixes[i])) { + return tt_font_locations[name * "." * suffixes[i]]; } } - // cout << "Resolve " << name << " in " << tt_path << "\n"; - url tt_path= tt_font_path (); - url u = resolve (tt_path * name); - bench_end ("tt_locate " * name, 10); - return u; + return url_none (); } url tt_font_find_sub (string name) { - // cout << "tt_font_find " << name << "\n"; url u= tt_unpack (name); if (!is_none (u)) return u; - if (font_database_rev_contains (name * ".ttf")) { - u= tt_locate (name * ".ttf"); - if (!is_none (u)) return u; - } + // Init the fonts location at startup + int num_of_fonts= N (tt_font_locations); + if (num_of_fonts == 0) tt_locate_all (); - if (font_database_rev_contains (name * ".ttc")) { - u= tt_locate (name * ".ttc"); - if (!is_none (u)) return u; - } + u= tt_fast_locate (name); + if (!is_none (u)) return u; - if (font_database_rev_contains (name * ".otf")) { - u= tt_locate (name * ".otf"); + // Update the fonts location and search again + tt_locate_all (); + if (N (tt_font_locations) > num_of_fonts) { + debug_fonts << "New fonts detected and search " << name << " again" << LF; + url u= tt_fast_locate (name); if (!is_none (u)) return u; } - u= tt_locate (name * ".pfb"); - // if (!is_none (u)) cout << name << " -> " << u << "\n"; - if (!is_none (u)) return u; - u= tt_locate (name * ".ttf"); - // if (!is_none (u)) cout << name << " -> " << u << "\n"; - // else cout << name << " -> ???\n"; - if (!is_none (u)) return u; - u= tt_locate (name * ".ttc"); - if (!is_none (u)) return u; - u= tt_locate (name * ".otf"); - if (!is_none (u)) return u; - u= tt_locate (name * ".dfont"); + u= tt_locate_pfb (name); return u; } @@ -188,10 +228,10 @@ tt_font_find (string name) { bool tt_font_exists (string name) { // cout << "tt_font_exists? " << name << "\n"; - if (tt_fonts->contains (name)) return tt_fonts[name] == "yes"; + if (tt_fonts->contains (name)) return true; bench_start ("tt_font_exists " * name); - bool yes = !is_none (tt_font_find (name)); - tt_fonts (name)= yes ? string ("yes") : string ("no"); + bool yes= !is_none (tt_font_find (name)); + if (yes) tt_fonts->insert (name); bench_end ("tt_font_exists " * name, 10); return yes; } diff --git a/src/Plugins/Freetype/tt_file.hpp b/src/Plugins/Freetype/tt_file.hpp index 1dac7ce9c0..1905affeb1 100644 --- a/src/Plugins/Freetype/tt_file.hpp +++ b/src/Plugins/Freetype/tt_file.hpp @@ -15,11 +15,12 @@ #include "bitmap_font.hpp" #include "url.hpp" -url tt_font_path (); -void tt_extend_font_path (url u); -bool tt_font_exists (string name); -url tt_font_find (string name); -string tt_find_name (string name, int size); +url tt_font_path (); +array tt_font_paths (); +void tt_extend_font_path (url u); +bool tt_font_exists (string name); +url tt_font_find (string name); +string tt_find_name (string name, int size); #ifdef USE_FREETYPE font_glyphs tt_font_glyphs (string family, int size, int hdpi, int vdpi); diff --git a/src/System/Files/tm_file.cpp b/src/System/Files/tm_file.cpp index 7916195d5a..9add151919 100644 --- a/src/System/Files/tm_file.cpp +++ b/src/System/Files/tm_file.cpp @@ -158,20 +158,23 @@ grep (string what, url u) { static void search_sub_dirs (url& all, url root) { - if (is_none (root)); - else if (is_or (root)) { - search_sub_dirs (all, root[2]); - search_sub_dirs (all, root[1]); - } - else if (is_directory (root)) { + if (is_directory (root)) { + all= root | all; + bool err= false; array a= read_directory (root, err); if (!err) { - for (int i=N(a)-1; i>=0; i--) - if (N(a[i])>0 && a[i][0] != '.') - search_sub_dirs (all, root * a[i]); + for (int i=0; i