]> git.donarmstrong.com Git - lilypond.git/blob - lily/font-select.cc
* lily/general-scheme.cc: new file.
[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 #include <math.h>
10
11 #include "dimensions.hh"
12 #include "all-font-metrics.hh"
13 #include "output-def.hh"
14 #include "font-interface.hh"
15 #include "warn.hh"
16 #include "pango-font.hh"
17
18 LY_DEFINE (ly_paper_get_font, "ly:paper-get-font", 2, 0, 0,
19            (SCM paper_smob, SCM chain),
20
21            "Return a font metric satisfying the font-qualifiers "
22            "in the alist chain @var{chain}.\n"
23            "(An alist chain is a list of alists, "
24            "containing grob properties).\n")
25 {
26   Output_def *paper = unsmob_output_def (paper_smob);
27   SCM_ASSERT_TYPE (paper, paper_smob, SCM_ARG1,
28                    __FUNCTION__, "paper definition");
29   
30   Font_metric *fm = select_font (paper, chain);
31   return fm->self_scm ();
32 }
33
34 LY_DEFINE (ly_paper_get_number, "ly:paper-get-number", 2, 0, 0,
35            (SCM layout_smob, SCM name),
36            "Return the layout variable @var{name}.")
37 {
38   Output_def *layout = unsmob_output_def (layout_smob);
39   SCM_ASSERT_TYPE (layout, layout_smob, SCM_ARG1,
40                    __FUNCTION__, "layout definition");
41   return scm_make_real (layout->get_dimension (name));
42 }
43
44 bool
45 wild_compare (SCM field_val, SCM val)
46 {
47   return (val == SCM_BOOL_F
48           || field_val == ly_symbol2scm ("*")
49           || field_val == val);
50 }
51
52 Font_metric *
53 get_font_by_design_size (Output_def *layout, 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   String pango_description_string;
62   for (; i < n; i++)
63     {
64       SCM entry = SCM_VECTOR_REF (font_vector, i);
65       
66       if (scm_promise_p (entry) == SCM_BOOL_T)
67         {
68           Font_metric *fm = unsmob_metrics (scm_force (entry));
69           size = fm->design_size ();
70         }
71 #if HAVE_PANGO_FT2
72       else if (scm_is_pair (entry)
73                && scm_is_number (scm_car (entry))
74                && scm_is_string (scm_cdr (entry)))
75         {
76           size = scm_to_double (scm_car (entry));
77           pango_description_string
78             = ly_scm2string (scm_cdr (entry));
79         }
80 #endif
81       
82       if (size > requested)
83         break;
84       last_size = size;
85     }
86
87   if (i == n)
88     i = n - 1;
89   else if (i > 0)
90     {
91       if ((requested / last_size) < (size / requested))
92         {
93           i--;
94           size = last_size;
95         }
96     }
97   
98   Font_metric *fm = 0;
99   if (pango_description_string != "")
100     {
101 #if HAVE_PANGO_FT2
102       PangoFontDescription *description
103         = pango_font_description_from_string (pango_description_string.to_str0 ());
104       fm = all_fonts_global->find_pango_font (description);
105 #else
106       error ("Trying to retrieve pango font without HAVE_PANGO_FT2."); 
107 #endif
108     }
109   else
110     {
111       fm = unsmob_metrics (scm_force (SCM_VECTOR_REF (font_vector, i)));
112     }
113
114   return find_scaled_font (layout, fm, requested / size);
115 }
116
117 Font_metric *
118 get_font_by_mag_step (Output_def *layout, Real requested_step,
119                       SCM font_vector, Real default_size)
120 {
121   return get_font_by_design_size (layout, default_size
122                                   * pow (2.0, requested_step / 6.0),
123                                   font_vector);
124 }
125
126 SCM
127 properties_to_font_size_family (SCM fonts, SCM alist_chain)
128 {
129   return scm_call_2 (ly_lily_module_constant ("lookup-font"), fonts, alist_chain);
130 }
131
132 Font_metric *
133 select_encoded_font (Output_def *layout, SCM chain)
134 {
135   SCM name = ly_chain_assoc (ly_symbol2scm ("font-name"), chain);
136
137   if (!scm_is_pair (name) || !scm_is_string (scm_cdr (name)))
138     {
139       SCM fonts = layout->lookup_variable (ly_symbol2scm ("fonts"));
140       name = properties_to_font_size_family (fonts, chain);
141     }
142   else
143     name = scm_cdr (name);
144
145   if (scm_is_string (name))
146     {
147       SCM mag = ly_chain_assoc (ly_symbol2scm ("font-magnification"), chain);
148       Real rmag = (scm_is_pair (mag)
149                    ? robust_scm2double (scm_cdr (mag), 1.0)
150                    : 1);
151       Font_metric *fm = all_fonts_global->find_font (ly_scm2string (name));
152                 
153       return find_scaled_font (layout, fm, rmag);
154     }
155   else if (scm_instance_p (name))
156     {
157       SCM base_size  = scm_slot_ref (name, ly_symbol2scm ("default-size"));
158       SCM vec = scm_slot_ref (name, ly_symbol2scm ("size-vector"));
159
160       SCM font_size = ly_chain_assoc (ly_symbol2scm ("font-size"), chain);
161       Real req = 0;
162       if (scm_is_pair (font_size))
163         req = scm_to_double (scm_cdr (font_size));
164
165       return get_font_by_mag_step (layout, req, vec,
166                                    scm_to_double (base_size));
167     }
168
169   assert (0);
170   return 0;
171 }
172
173 Font_metric *
174 select_font (Output_def *layout, SCM chain)
175 {
176   return select_encoded_font (layout, chain);
177 }