]> git.donarmstrong.com Git - lilypond.git/blob - lily/all-font-metrics.cc
9dc7691c6a9fdfa363eb7a6408d9032d37cfb9d9
[lilypond.git] / lily / all-font-metrics.cc
1 /*
2   all-font-metrics.cc -- implement All_font_metrics
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "all-font-metrics.hh"
10
11 #include "open-type-font.hh"
12 #include "main.hh"
13 #include "warn.hh"
14 #include "tfm.hh"
15 #include "scm-hash.hh"
16 #include "pango-font.hh"
17
18 static char const *default_font_str0_ = "cmr10";
19
20 All_font_metrics::All_font_metrics (String path)
21 {
22   tfm_dict_ = new Scheme_hash_table;
23   otf_dict_ = new Scheme_hash_table;
24
25 #if HAVE_PANGO_FT2
26   PangoFontMap *pfm = pango_ft2_font_map_new ();
27
28   pango_ft2_fontmap_
29     = G_TYPE_CHECK_INSTANCE_CAST (pfm,
30                                   PANGO_TYPE_FT2_FONT_MAP,
31                                   PangoFT2FontMap);
32   pango_dpi_ = 1200;
33   pango_ft2_font_map_set_resolution (pango_ft2_fontmap_,
34                                      pango_dpi_, pango_dpi_);
35
36   pango_dict_ = new Scheme_hash_table;
37 #endif
38
39   search_path_.parse_path (path);
40 }
41
42 All_font_metrics::~All_font_metrics ()
43 {
44   tfm_dict_->unprotect ();
45   otf_dict_->unprotect ();
46
47 #if HAVE_PANGO_FT2
48   pango_dict_->unprotect ();
49   g_object_unref (pango_ft2_fontmap_);
50 #endif
51 }
52
53 All_font_metrics::All_font_metrics (All_font_metrics const &)
54 {
55 }
56
57 #if HAVE_PANGO_FT2
58
59 Pango_font *
60 All_font_metrics::find_pango_font (PangoFontDescription *description,
61                                    Real magnification,
62                                    Real output_scale
63                                    )
64 {
65   pango_font_description_set_size (description,
66                                    gint (magnification *
67                                          pango_font_description_get_size (description)));
68
69   gchar *pango_fn = pango_font_description_to_filename (description);
70   SCM key = ly_symbol2scm (pango_fn);
71
72   SCM val;
73   if (!pango_dict_->try_retrieve (key, &val))
74     {
75       if (be_verbose_global)
76         progress_indication ("[" + String (pango_fn));
77
78       Pango_font *pf = new Pango_font (pango_ft2_fontmap_,
79                                        description,
80                                        output_scale
81                                        );
82       
83       val = pf->self_scm ();
84       pango_dict_->set (key, val);
85       pf->unprotect ();
86
87       if (be_verbose_global)
88         progress_indication ("]");
89
90       pf->description_ = scm_cons (SCM_BOOL_F,
91                                    scm_from_double (1.0));
92     }
93   g_free (pango_fn);
94   return dynamic_cast<Pango_font *> (unsmob_metrics (val));
95 }
96
97 #endif
98
99 String
100 kpathsea_find_file (String name, String ext)
101 {
102   name += "." + ext;
103   String path = global_path.find (name);
104   if (path.length () > 0)
105     return path;
106
107   static SCM proc;
108   if (!proc)
109     {
110       SCM module = scm_c_resolve_module ("scm kpathsea");
111       proc = scm_c_module_lookup (module, "ly:kpathsea-find-file");
112       proc = scm_variable_ref (proc);
113     }
114
115   if (ly_is_procedure (proc))
116     {
117       SCM kp_result = scm_call_1 (proc, scm_makfrom0str (name.c_str ()));
118       if (scm_is_string (kp_result))
119         return ly_scm2string (kp_result);
120     }
121
122   return "";
123 }
124
125 Open_type_font *
126 All_font_metrics::find_otf (String name)
127 {
128   SCM sname = ly_symbol2scm (name.c_str ());
129   SCM name_string = scm_makfrom0str (name.c_str ());
130   SCM val;
131   if (!otf_dict_->try_retrieve (sname, &val))
132     {
133       String file_name;
134
135       if (file_name.empty ())
136         file_name = search_path_.find (name + ".otf");
137       if (file_name.empty ())
138         return 0;
139
140       if (be_verbose_global)
141         progress_indication ("[" + file_name);
142
143       val = Open_type_font::make_otf (file_name);
144
145       if (be_verbose_global)
146         progress_indication ("]");
147
148       unsmob_metrics (val)->file_name_ = file_name;
149       unsmob_metrics (val)->description_ = scm_cons (name_string,
150                                                      scm_from_double (1.0));
151       otf_dict_->set (sname, val);
152       unsmob_metrics (val)->unprotect ();
153     }
154
155   return dynamic_cast<Open_type_font *> (unsmob_metrics (val));
156 }
157
158 Tex_font_metric *
159 All_font_metrics::find_tfm (String name)
160 {
161   SCM sname = ly_symbol2scm (name.c_str ());
162   SCM name_string = scm_makfrom0str (name.c_str ());
163   SCM val;
164   if (!tfm_dict_->try_retrieve (sname, &val))
165     {
166       String file_name;
167
168       if (file_name.empty ())
169         {
170           /* FIXME: should add "cork-" prefix to lm* fonts.  How to do
171              that, cleanly?  */
172           String p = kpathsea_find_file (name, "tfm");
173           if (p.length ())
174             file_name = p;
175         }
176
177       if (file_name.empty ())
178         file_name = search_path_.find (name + ".tfm");
179       if (file_name.empty ())
180         return 0;
181
182       if (be_verbose_global)
183         progress_indication ("[" + file_name);
184
185       val = Tex_font_metric::make_tfm (file_name);
186
187       if (be_verbose_global)
188         progress_indication ("]");
189
190       unsmob_metrics (val)->file_name_ = file_name;
191       unsmob_metrics (val)->description_ = scm_cons (name_string,
192                                                      scm_from_double (1.0));
193       tfm_dict_->set (sname, val);
194       unsmob_metrics (val)->unprotect ();
195     }
196
197   return dynamic_cast<Tex_font_metric *> (unsmob_metrics (val));
198 }
199
200 Font_metric *
201 All_font_metrics::find_font (String name)
202 {
203   Font_metric *f = find_otf (name);
204
205   if (!f)
206     {
207       f = find_tfm (name);
208     }
209
210   if (!f)
211     {
212       warning (_f ("can't find font: `%s'", name.c_str ()));
213       warning (_ ("loading default font"));
214     }
215
216   String def_name = default_font_str0_;
217
218   if (!f)
219     f = find_tfm (def_name);
220
221   if (!f)
222     {
223       error (_f ("can't find default font: `%s'", def_name.c_str ()));
224       error (_f ("(search path: `%s')", search_path_.to_string ()));
225       error (_ ("giving up"));
226     }
227
228   return f;
229 }
230
231 All_font_metrics *all_fonts_global;
232
233 LY_DEFINE (ly_font_load, "ly:font-load", 1, 0, 0,
234            (SCM name),
235            "Load the font @var{name}. ")
236 {
237   SCM_ASSERT_TYPE (scm_is_string (name), name, SCM_ARG1, __FUNCTION__, "string");
238
239   Font_metric *fm = all_fonts_global->find_font (ly_scm2string (name));
240
241   return fm->self_scm ();
242 }
243