]> git.donarmstrong.com Git - lilypond.git/blob - lily/font-select.cc
* lily/font-select.cc (properties_to_font_size_family): Fix
[lilypond.git] / lily / font-select.cc
1 /*   
2   font-select.cc -- implement property -> font_metric routines. 
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2003--2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8  */
9
10 #include <math.h>
11
12 #include "paper-def.hh"
13 #include "font-interface.hh"
14 #include "warn.hh"
15
16 LY_DEFINE (ly_paper_get_font, "ly:paper-get-font", 2, 0, 0,
17            (SCM paper, SCM chain),
18            "Return a font metric satisfying the font-qualifiers in the alist chain @var{chain}.\n"
19 "\n"
20 "The font object represents the metric information of a font. Every font\n"
21 "that is loaded into LilyPond can be accessed via Scheme. \n"
22 "\n"
23 "LilyPond only needs to know the dimension of glyph to be able to process\n"
24 "them. This information is stored in font metric files. LilyPond can read\n"
25 "two types of font-metrics: @TeX{} Font Metric files (TFM files) and\n"
26 "Adobe Font Metric files (AFM files).  LilyPond will always try to load\n"
27 "AFM files first since they are more versatile.\n"
28 "\n"
29 "An alist chain is a list of alists, containing grob properties.\n")
30 {
31   Paper_def *pap = unsmob_paper (paper);
32   SCM_ASSERT_TYPE (pap, paper, SCM_ARG1, __FUNCTION__, "paper definition");
33   
34   Font_metric *fm = select_font (pap, chain);
35   return fm->self_scm ();
36 }
37
38 LY_DEFINE (ly_paper_get_number, "ly:paper-get-number", 2, 0, 0,
39            (SCM paper, SCM name),
40            "Return the paper variable @var{name}.")
41 {
42   Paper_def *pap = unsmob_paper (paper);
43   SCM_ASSERT_TYPE (pap, paper, SCM_ARG1, __FUNCTION__, "paper definition");
44   return gh_double2scm (pap->get_realvar (name));
45 }
46
47 bool
48 wild_compare (SCM field_val, SCM val)
49 {
50   return (val == SCM_BOOL_F || field_val == ly_symbol2scm ("*") || field_val == val);
51 }
52 Font_metric*
53 get_font_by_design_size (Paper_def* paper, Real requested,
54                          SCM font_vector)
55 {
56   int n = SCM_VECTOR_LENGTH (font_vector);
57   Real size = 1e6;
58   Real last_size = -1e6;
59   int i = 0;
60   
61   for (; i < n; i++)
62     {
63       size = gh_scm2double (gh_car (SCM_VECTOR_REF (font_vector, i)));
64       if (size > requested)
65         break ;
66       last_size = size; 
67     }
68
69   if (i == n)
70     {
71       i = n-1;
72     }
73   else if (i > 0)
74     {
75       if ((requested / last_size) < (size / requested))
76         {
77           i -- ;
78           size = last_size;
79         }
80     }
81   
82   return paper->find_font (gh_cdr (SCM_VECTOR_REF (font_vector, i)),
83                            requested / size);
84 }
85
86
87 Font_metric*
88 get_font_by_mag_step (Paper_def* paper, Real requested_step,
89                       SCM font_vector, Real default_size)
90 {
91   return get_font_by_design_size (paper,
92                                   default_size * pow (2.0, requested_step / 6.0),
93                                   font_vector);
94 }
95
96
97
98 /*
99   We can probably get more efficiency points if we preprocess FONTS
100   to make lookup easier.
101  */
102 SCM
103 properties_to_font_size_family (SCM fonts, SCM alist_chain)
104 {
105   SCM shape = SCM_BOOL_F;
106   SCM family = SCM_BOOL_F;
107   SCM series = SCM_BOOL_F;
108   
109   shape = ly_assoc_chain (ly_symbol2scm ("font-shape"), alist_chain);
110   family = ly_assoc_chain (ly_symbol2scm ("font-family"), alist_chain);
111   series = ly_assoc_chain (ly_symbol2scm ("font-series"), alist_chain);
112
113   if (gh_pair_p (shape))
114     shape = ly_cdr (shape);
115   if (gh_pair_p (family))
116     family = ly_cdr (family);
117   if (gh_pair_p (series))
118     series = ly_cdr (series);
119
120
121   for (SCM s = fonts ; gh_pair_p (s); s = ly_cdr (s))
122     {
123       SCM qlist = ly_caar (s);
124
125       if (!wild_compare (SCM_VECTOR_REF (qlist, 0), series))
126         continue;
127       if (!wild_compare (SCM_VECTOR_REF (qlist, 1), shape))
128         continue;
129       if (!wild_compare (SCM_VECTOR_REF (qlist, 2), family))
130         continue;
131   
132       SCM qname = ly_cdar (s);
133       return qname;
134     }
135
136   warning (_f ("cannot find font for: (%s %s %s)",
137                ly_symbol2string (series).to_str0 (),
138                ly_symbol2string (shape).to_str0 (),
139                ly_symbol2string (family).to_str0 ()));
140   
141   scm_write (scm_list_n (shape, series , family, 
142                          SCM_UNDEFINED), scm_current_error_port ());
143   scm_flush (scm_current_error_port ());
144  
145   return scm_makfrom0str ("cmr10");
146 }
147
148
149 Font_metric *
150 select_font (Paper_def *paper, SCM chain)
151 {
152   SCM name = ly_assoc_chain (ly_symbol2scm  ("font-name"), chain);
153   
154   if (!gh_pair_p (name) || !gh_string_p (gh_cdr (name)))
155     {
156       SCM fonts = paper->lookup_variable (ly_symbol2scm ("fonts"));
157       name = properties_to_font_size_family (fonts, chain);
158     }
159   else
160     name  = gh_cdr (name);
161
162
163   if (gh_string_p (name))
164     {
165       SCM mag = ly_assoc_chain (ly_symbol2scm ("font-magnification"), chain);
166   
167       Real rmag = gh_pair_p (mag) ? robust_scm2double (gh_cdr (mag), 1.0) : 1;
168   
169       return paper->find_font (name, rmag);
170     }
171   else if (gh_pair_p (name)) // (DEFAULT . FONT-VEC) pair
172     {
173       SCM vec = gh_cdr (name);
174       SCM base_size = gh_car (name);
175       
176       SCM font_size = ly_assoc_chain (ly_symbol2scm ("font-size"), chain);
177       Real req = 0.0;
178       if (gh_pair_p (font_size))
179         req = gh_scm2double (ly_cdr (font_size));
180
181       return get_font_by_mag_step (paper, req,
182                                    vec, gh_scm2double (base_size));
183     }
184
185   assert (0);
186
187   return 0;
188 }
189
190