1 
2 /******************************************************************************
3 * MODULE     : tt_file.cpp
4 * DESCRIPTION: Finding a True Type font
5 * COPYRIGHT  : (C) 2003  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "tt_file.hpp"
13 #include "tt_tools.hpp"
14 #include "file.hpp"
15 #include "boot.hpp"
16 #include "analyze.hpp"
17 #include "hashmap.hpp"
18 #include "Metafont/tex_files.hpp"
19 #include "timer.hpp"
20 #include "data_cache.hpp"
21 
22 static hashmap<string,string> tt_fonts ("no");
23 
24 url
tt_font_path()25 tt_font_path () {
26   string xtt= get_env ("TEXMACS_FONT_PATH");
27   url xu= url_none ();
28   if (xtt != "") xu= search_sub_dirs (xtt);
29   return
30     xu |
31     search_sub_dirs ("$TEXMACS_HOME_PATH/fonts/truetype") |
32     search_sub_dirs ("$TEXMACS_PATH/fonts/truetype") |
33 #if defined __MINGW32__
34     search_sub_dirs ("$windir/Fonts");
35 #elif defined OS_MACOS
36     search_sub_dirs ("$HOME/Library/Fonts") |
37     search_sub_dirs ("/Library/Fonts") |
38     search_sub_dirs ("/System/Library/Fonts") |
39     search_sub_dirs ("/opt/local/share/texmf-texlive-dist/fonts/truetype");
40 #else
41     search_sub_dirs ("$HOME/.fonts") |
42     search_sub_dirs ("/usr/share/fonts/truetype") |
43     search_sub_dirs ("/usr/local/share/fonts/truetype");
44 #endif
45 }
46 
47 static url
tt_locate(string name)48 tt_locate (string name) {
49   if (ends (name, ".pfb")) {
50     /*
51     if (starts (name, "rpag")) name= "uag" * name (4, N (name) - 4) * "8a.pfb";
52     if (starts (name, "rpbk")) name= "ubk" * name (4, N (name) - 4) * "8a.pfb";
53     if (starts (name, "rpcr")) name= "ucr" * name (4, N (name) - 4) * "8a.pfb";
54     if (starts (name, "rphv")) name= "uhv" * name (4, N (name) - 4) * "8a.pfb";
55     if (starts (name, "rpnc")) name= "unc" * name (4, N (name) - 4) * "8a.pfb";
56     if (starts (name, "rppl")) name= "upl" * name (4, N (name) - 4) * "8a.pfb";
57     if (starts (name, "rpsy")) name= "usy" * name (4, N (name));
58     if (starts (name, "rptm")) name= "utm" * name (4, N (name) - 4) * "8a.pfb";
59     if (starts (name, "rpzc")) name= "uzc" * name (4, N (name) - 4) * "8a.pfb";
60     if (starts (name, "rpzd")) name= "uzd" * name (4, N (name));
61     */
62     url u= resolve_tex (name);
63     //cout << "tt_locate: " << name << " -> " << u << "\n";
64     if (!is_none (u)) return u;
65   }
66   else if (use_locate &&
67 	   // NOTE: avoiding unnecessary locates can greatly improve timings
68 	   !starts (name, "ec") &&
69 	   !starts (name, "la") &&
70 	   !starts (name, "cm") &&
71 	   !starts (name, "msam") &&
72 	   !starts (name, "msbm") &&
73 	   !starts (name, "bbm") &&
74 	   !starts (name, "stmary") &&
75 	   !starts (name, "rsfs") &&
76 	   !starts (name, "grmn") &&
77 	   !starts (name, "mac-")
78 	   // FIXME: better caching of missed tt_locates would be better
79 	   )
80     {
81       string s= eval_system ("locate", "/" * name);
82       //cout << "locate " << name << " -> " << s << "\n";
83       int start, i, n= N(s);
84       for (start=0, i=0; i<n; i++)
85 	if (s[i]=='\n') {
86 	  if (ends (s (start, i), name))
87 	    return url (s (start, i));
88 	  start= i+1;
89 	}
90     }
91 
92   url tt_path= tt_font_path ();
93   //cout << "Resolve " << name << " in " << tt_path << "\n";
94   return resolve (tt_path * name);
95 }
96 
97 url
tt_font_find_sub(string name)98 tt_font_find_sub (string name) {
99   //cout << "tt_font_find " << name << "\n";
100   url u= tt_unpack (name);
101   if (!is_none (u)) return u;
102   u= tt_locate (name * ".pfb");
103   //if (!is_none (u)) cout << name << " -> " << u << "\n";
104   if (!is_none (u)) return u;
105   u= tt_locate (name * ".ttf");
106   //if (!is_none (u)) cout << name << " -> " << u << "\n";
107   //else cout << name << " -> ???\n";
108   if (!is_none (u)) return u;
109   u= tt_locate (name * ".ttc");
110   if (!is_none (u)) return u;
111   u= tt_locate (name * ".otf");
112   if (!is_none (u)) return u;
113   u= tt_locate (name * ".dfont");
114   return u;
115 }
116 
117 url
tt_font_find(string name)118 tt_font_find (string name) {
119   string s= "ttf:" * name;
120   if (is_cached ("font_cache.scm", s)) {
121     string r= cache_get ("font_cache.scm", s) -> label;
122     if (r == "") return url_none ();
123     url u= url_system (r);
124     if (exists (u)) return u;
125     cache_reset ("font_cache.scm", s);
126   }
127 
128   url r= tt_font_find_sub (name);
129   if (is_none (r)) cache_set ("font_cache.scm", s, "");
130   else cache_set ("font_cache.scm", s, as_string (r));
131   return r;
132 }
133 
134 bool
tt_font_exists(string name)135 tt_font_exists (string name) {
136   //cout << "tt_font_exists? " << name << "\n";
137   if (tt_fonts->contains (name)) return tt_fonts[name] == "yes";
138   bool yes= !is_none (tt_font_find (name));
139   tt_fonts (name)= yes? string ("yes"): string ("no");
140   return yes;
141 }
142 
143 string
tt_find_name_sub(string name,int size)144 tt_find_name_sub (string name, int size) {
145   if (size == 0) {
146     if (tt_font_exists (name)) return name;
147     else return "";
148   }
149   if (tt_font_exists (name * as_string (size)))
150     return name * as_string (size);
151   if (size > 333) size= (size+50)/100;
152   if (tt_font_exists (name * as_string (size)))
153     return name * as_string (size);
154 
155   if ((size >= 15) && tt_font_exists (name * "17")) return name * "17";
156   if ((size >  12) && tt_font_exists (name * "12")) return name * "12";
157   if ((size <  5 ) && tt_font_exists (name * "5" )) return name * "5" ;
158   if ((size <  6 ) && tt_font_exists (name * "6" )) return name * "6" ;
159   if ((size <  7 ) && tt_font_exists (name * "7" )) return name * "7" ;
160   if ((size <  8 ) && tt_font_exists (name * "8" )) return name * "8" ;
161   if ((size <  9 ) && tt_font_exists (name * "9" )) return name * "9" ;
162   if ((size <  9 ) && tt_font_exists (name * "7" )) return name * "7" ;
163   if (tt_font_exists (name * "10")) return name * "10";
164   if ((size <  9 ) && tt_font_exists (name * "700" )) return name * "700" ;
165   if ((size >= 15) && tt_font_exists (name * "1700")) return name * "1700";
166   if (tt_font_exists (name * "1000")) return name * "1000";
167   if (tt_font_exists (name)) return name;
168   return "";
169 }
170 
171 string
tt_find_name(string name,int size)172 tt_find_name (string name, int size) {
173   string s= "tt:" * name * as_string (size);
174   if (is_cached ("font_cache.scm", s)) {
175     string r= cache_get ("font_cache.scm", s) -> label;
176     if (tt_font_exists (r)) return r;
177     cache_reset ("font_cache.scm", s);
178   }
179 
180   bench_start ("tt find name");
181   string r= tt_find_name_sub (name, size);
182   //cout << name << size << " -> " << r << "\n";
183   bench_cumul ("tt find name");
184 
185   if (r != "") cache_set ("font_cache.scm", s, r);
186   return r;
187 }
188