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