Skip to content

Commit

Permalink
[11_17] Use tt_font_locations to speedup
Browse files Browse the repository at this point in the history
Co-authored-by: jingkaimori <jingkaimori@gmail.com>
  • Loading branch information
da-liii and jingkaimori committed Dec 16, 2023
1 parent 133d188 commit a8c9a8d
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 126 deletions.
1 change: 0 additions & 1 deletion src/Graphics/Fonts/font.hpp
Expand Up @@ -251,7 +251,6 @@ array<string> font_database_search (string fam, string var, string series,
string shape);
array<string> 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<string> a);
Expand Down
29 changes: 10 additions & 19 deletions src/Graphics/Fonts/font_database.cpp
Expand Up @@ -79,9 +79,7 @@ struct font_less_eq_operator {
static bool fonts_loaded = false;
static bool fonts_global_loaded= false;
hashmap<tree, tree> font_table (UNINIT);
hashmap<string, tree> font_rev_table (UNINIT);
hashmap<tree, tree> font_global_table (UNINIT);
hashmap<string, tree> font_global_rev_table (UNINIT);
hashmap<tree, tree> font_features (UNINIT);
hashmap<tree, tree> font_variants (UNINIT);
hashmap<tree, tree> font_characteristics (UNINIT);
Expand All @@ -95,8 +93,7 @@ tuple_insert (tree& t, tree x) {
}

void
font_database_load_database (url u, hashmap<tree, tree>& ftab= font_table,
hashmap<string, tree>& frev= font_rev_table) {
font_database_load_database (url u, hashmap<tree, tree>& ftab= font_table) {
if (!exists (u)) return;
string s;
if (!load_string (u, s, false)) {
Expand All @@ -107,9 +104,6 @@ font_database_load_database (url u, hashmap<tree, tree>& 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;
}
}
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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))) {
Expand Down Expand Up @@ -512,7 +506,7 @@ font_database_collect (url u) {
string suf = suffix (a[i]);
array<string> allowed= array<string> ("ttf", "ttc", "otf", "tfm");
if (contains (suf, allowed)) {
font_collect (u, a[i]);
font_collect (u * a[i]);
}
}
}
Expand All @@ -526,7 +520,10 @@ font_database_filter () {
new_font_table = hashmap<tree, tree> (UNINIT);
back_font_table= hashmap<tree, tree> (UNINIT);
build_back_table ();
font_database_collect (tt_font_path ());
array<url> 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<tree, tree> (UNINIT);
Expand Down Expand Up @@ -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);
}
222 changes: 131 additions & 91 deletions src/Plugins/Freetype/tt_file.cpp
Expand Up @@ -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"
Expand All @@ -27,7 +28,8 @@
#include <fontconfig/fontconfig.h>
#endif

static hashmap<string, string> tt_fonts ("no");
static hashset<string> tt_fonts;
static hashmap<string, url> tt_font_locations;

url
add_to_path (url u, url d) {
Expand All @@ -50,121 +52,159 @@ 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);
FcChar8* fontdir = NULL;

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<url>
tt_font_paths () {
int num_of_fonts= N (tt_font_locations);
if (num_of_fonts == 0) {
tt_locate_all ();
}
array<url> ret;
iterator<string> 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<string> 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;
}

Expand All @@ -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;
}
Expand Down
11 changes: 6 additions & 5 deletions src/Plugins/Freetype/tt_file.hpp
Expand Up @@ -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<url> 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);
Expand Down

0 comments on commit a8c9a8d

Please sign in to comment.