]> git.donarmstrong.com Git - lilypond.git/blob - lily/font-select.cc
*** empty log message ***
[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 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
39 bool
40 wild_compare (SCM field_val, SCM val)
41 {
42   return (val == SCM_BOOL_F || field_val == ly_symbol2scm ("*") || field_val == val);
43 }
44 Font_metric*
45 get_font_by_design_size (Paper_def* paper, Real requested,
46                          SCM font_vector)
47 {
48   int n = SCM_VECTOR_LENGTH (font_vector);
49   Real size = 1e6;
50   Real last_size = -1e6;
51   int i = 0;
52   
53   for (; i < n; i++)
54     {
55       size = gh_scm2double (gh_car (SCM_VECTOR_REF (font_vector, i)));
56       if (size > requested)
57         break ;
58       last_size = size; 
59     }
60
61   if (i == n)
62     {
63       i = n-1;
64     }
65   else if (i > 0)
66     {
67       if ((requested / last_size) < (size / requested))
68         {
69           i -- ;
70           size = last_size;
71         }
72     }
73   
74   return paper->find_font (gh_cdr (SCM_VECTOR_REF (font_vector, i)),
75                            requested / size);
76 }
77
78
79 Font_metric*
80 get_font_by_mag_step (Paper_def* paper, Real requested_step,
81                       SCM font_vector, Real default_size)
82 {
83   return get_font_by_design_size (paper,
84                                   default_size * pow (2.0, requested_step / 6.0),
85                                   font_vector);
86 }
87
88
89
90 /*
91   We can probably get more efficiency points if we preprocess FONTS
92   to make lookup easier.
93  */
94 SCM
95 properties_to_font_size_family (SCM fonts, SCM alist_chain)
96 {
97   SCM shape = SCM_BOOL_F;
98   SCM family = SCM_BOOL_F;
99   SCM series = SCM_BOOL_F;
100   
101   shape = ly_assoc_chain (ly_symbol2scm ("font-shape"), alist_chain);
102   family = ly_assoc_chain (ly_symbol2scm ("font-family"), alist_chain);
103   series = ly_assoc_chain (ly_symbol2scm ("font-series"), alist_chain);
104
105   if (gh_pair_p (shape))
106     shape = ly_cdr (shape);
107   if (gh_pair_p (family))
108     family = ly_cdr (family);
109   if (gh_pair_p (series))
110     series = ly_cdr (series);
111
112
113   for (SCM s = fonts ; gh_pair_p (s); s = ly_cdr (s))
114     {
115       SCM qlist = ly_caar (s);
116
117       if (!wild_compare (SCM_VECTOR_REF (qlist, 0), series))
118         continue;
119       if (!wild_compare (SCM_VECTOR_REF (qlist, 1), shape))
120         continue;
121       if (!wild_compare (SCM_VECTOR_REF (qlist, 2), family))
122         continue;
123   
124       SCM qname = ly_cdar (s);
125       return qname;
126     }
127
128   warning (_ ("couldn't find any font size family satisfying "));
129   
130   scm_write (scm_list_n (shape, series , family, 
131                          SCM_UNDEFINED), scm_current_error_port ());
132   scm_flush (scm_current_error_port ());
133  
134   return scm_makfrom0str ("cmr10");
135 }
136
137
138 Font_metric *
139 select_font (Paper_def *paper, SCM chain)
140 {
141   SCM name = ly_assoc_chain (ly_symbol2scm  ("font-name"), chain);
142   
143   if (!gh_pair_p (name) || !gh_string_p (gh_cdr (name)))
144     {
145       SCM fonts = paper->lookup_variable (ly_symbol2scm ("fonts"));
146       name = properties_to_font_size_family (fonts, chain);
147     }
148   else
149     name  = gh_cdr (name);
150
151
152   if (gh_string_p (name))
153     {
154       SCM mag = ly_assoc_chain (ly_symbol2scm ("font-magnification"), chain);
155   
156       Real rmag = gh_pair_p (mag) && gh_number_p (gh_cdr (mag))
157         ? gh_scm2double (gh_cdr (mag)) : 1.0;
158   
159       return paper->find_font (name, rmag);
160     }
161   else if (gh_pair_p (name)) // (DEFAULT . FONT-VEC) pair
162     {
163       SCM vec = gh_cdr (name);
164       SCM base_size = gh_car (name);
165       
166       SCM font_size = ly_assoc_chain (ly_symbol2scm ("font-size"), chain);
167       Real req = 0.0;
168       if (gh_pair_p (font_size))
169         req = gh_scm2double (ly_cdr (font_size));
170
171       return get_font_by_mag_step (paper, req,
172                                    vec, gh_scm2double (base_size));
173     }
174
175   assert (0);
176
177   return 0;
178 }
179
180