2 text-item.cc -- implement Text_item
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
12 #include "text-item.hh"
13 #include "paper-def.hh"
14 #include "font-interface.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "staff-symbol-referencer.hh"
18 #include "all-font-metrics.hh"
28 HEAD: MARKUP-ITEM | (MARKUP-ITEM+)
30 MARKUP-ITEM: PROPERTY | ABBREV | FONT-STYLE
31 PROPERTY: (key . value)
32 ABBREV: rows lines roman music bold italic named super sub text
37 Text_item::text2molecule (Grob *me, SCM text, SCM alist_chain)
39 if (gh_string_p (text))
40 return string2molecule (me, text, alist_chain);
41 else if (gh_pair_p (text))
43 /* urg, why not just do this in markup_text2molecule ? */
44 if (gh_string_p (ly_car (text)))
45 return markup_text2molecule (me,
46 gh_append2 (scm_list_n (SCM_EOL,
51 Allow (faulty) texts that are in an extra list:
54 else if (scm_ilength (text) <= 1)
55 return text2molecule (me, ly_car (text), alist_chain);
57 return markup_text2molecule (me, text, alist_chain);
63 Text_item::string2molecule (Grob *me, SCM text, SCM alist_chain)
65 SCM style = ly_assoc_chain (ly_symbol2scm ("font-style"),
67 if (gh_pair_p (style) && gh_symbol_p (ly_cdr (style)))
68 alist_chain = Font_interface::add_style (me, ly_cdr (style), alist_chain);
70 Font_metric *fm = Font_interface::get_font (me, alist_chain);
72 SCM lookup = ly_assoc_chain (ly_symbol2scm ("lookup"), alist_chain);
75 if (gh_pair_p (lookup) && ly_cdr (lookup) ==ly_symbol2scm ("name"))
76 mol = lookup_character (me, fm, text);
78 mol = lookup_text (me, fm, text);
84 Text_item::lookup_character (Grob *, Font_metric*fm, SCM char_name)
86 return fm->find_by_name (ly_scm2string (char_name));
91 Text_item::lookup_text (Grob *me, Font_metric*fm, SCM text)
95 Fixme; should be done differently, move to font-interface?
97 differently -- how/why?
100 SCM magnification = me->get_grob_property ("font-magnification");
102 Font_metric* metric = 0;
103 if (gh_number_p (magnification))
106 Real realmag = pow (1.2, gh_scm2int (magnification));
107 metric = all_fonts_global_p->find_scaled (ly_scm2string (font_name), realmag);
112 SCM magnification = me->get_grob_property ("font-magnification");
114 if (gh_number_p (magnification) && gh_scm2double (magnification) > 1)
115 programming_error ("font-magnification disabled");
119 SCM list = scm_list_n (ly_symbol2scm ("text"), text, SCM_UNDEFINED);
120 list = fontify_atom (fm, list);
122 return Molecule (fm->text_dimension (ly_scm2string (text)), list);
131 MARKUP_TEXT must be compound (may not be simple string.)
135 Text_item::markup_text2molecule (Grob *me, SCM markup_text,
138 SCM sheet = me->paper_l ()->style_sheet_;
139 SCM f = ly_cdr (scm_assoc (ly_symbol2scm ("markup-to-properties"), sheet));
141 SCM markup = ly_car (markup_text);
142 SCM text = ly_cdr (markup_text);
144 SCM p = gh_cons (gh_call2 (f, sheet, markup), alist_chain);
146 Real staff_space = Staff_symbol_referencer::staff_space (me);
149 Line mode is default.
153 SCM a = ly_assoc_chain (ly_symbol2scm ("axis"), p);
154 if (gh_pair_p (a) && isaxis_b (ly_cdr (a)))
155 axis = (Axis)gh_scm2int (ly_cdr (a));
157 Real baseline_skip = 0;
158 SCM b = ly_assoc_chain (ly_symbol2scm ("baseline-skip"), p);
159 if (gh_pair_p (b) && gh_number_p (ly_cdr (b)))
160 baseline_skip = gh_scm2double (ly_cdr (b)) * staff_space;
162 Real kern[2] = {0,0};
164 SCM k = ly_assoc_chain (ly_symbol2scm ("kern"), p);
165 if (gh_pair_p (k) && gh_number_p (ly_cdr (k)))
166 kern[axis] = gh_scm2double (ly_cdr (k)) * staff_space;
169 SCM r = ly_assoc_chain (ly_symbol2scm ("raise"), p);
170 if (gh_pair_p (r) && gh_number_p (ly_cdr (r)))
171 raise = gh_scm2double (ly_cdr (r)) * staff_space;
174 bool extent_b = false;
175 SCM e = ly_assoc_chain (ly_symbol2scm ("extent"), p);
176 if (gh_pair_p (e) && ly_number_pair_p (ly_cdr (e)))
178 extent = Interval (gh_scm2double (ly_cadr (e)) * staff_space,
179 gh_scm2double (ly_cddr (e)) * staff_space);
183 Offset o (0, (axis == Y_AXIS ? - kern[axis] : 0));
186 while (gh_pair_p (text))
189 Molecule m = text2molecule (me, ly_car (text), p);
192 TODO: look at padding?
194 Look ahead here for kern and raise.
196 (cols "foo" ((raise . 1) "bar"))
197 (cols "foo" ((bold (raise . 1)) "bar"))
199 When constructing the molecule for bar, all normal extra
200 properties found, such as bold, are used for the construction
201 of bar's molecule. But for kern or raise, it seems that we're
202 too late then, translating bar's molecule has no effect (or
203 maybe the effect of translating gets nullified when bar's
204 molecule is `added_to_edge' of the molecule for foo?)
206 So, while constructing foo's molecule, we look ahead for the
207 raise of bar. The HEAD of the description of bar may be a
208 single property, or a list, so we must check that too.
211 SCM next_p = SCM_EOL;
212 if (gh_pair_p (ly_car (text)))
213 next_p = scm_list_n (gh_call2 (f, sheet, ly_caar (text)), SCM_UNDEFINED);
214 SCM next_k = ly_assoc_chain (ly_symbol2scm ("kern"), next_p);
215 Real next_kern = kern[axis];
216 if (gh_pair_p (next_k) && gh_number_p (ly_cdr (next_k)))
217 next_kern = gh_scm2double (ly_cdr (next_k)) * staff_space;
219 SCM next_r = ly_assoc_chain (ly_symbol2scm ("raise"), next_p);
221 if (gh_pair_p (next_r) && gh_number_p (ly_cdr (next_r)))
222 next_raise = gh_scm2double (ly_cdr (next_r)) * staff_space;
224 o[Y_AXIS] = next_raise;
233 if (axis == Y_AXIS && baseline_skip)
234 next_kern += baseline_skip - m.extent (Y_AXIS)[UP];
235 mol.add_at_edge (axis, axis == X_AXIS ? RIGHT : DOWN, m, next_kern);
238 text = ly_cdr (text);
244 /* Hmm, we're not allowed to change a Molecule's extent? */
245 mol.dim_[axis] = extent;
246 Molecule::ly_set_molecule_extent_x (mol.self_scm (), gh_int2scm (axis),
249 // burp: unpredictable names, these...
250 Box b = mol.extent_box ();
251 SCM expr = mol.get_expr ();
254 mol = Molecule (b, expr);
260 MAKE_SCHEME_CALLBACK (Text_item, brew_molecule, 1);
262 Text_item::brew_molecule (SCM smob)
264 Grob *me = unsmob_grob (smob);
266 SCM text = me->get_grob_property ("text");
268 SCM properties = Font_interface::font_alist_chain (me);
269 Molecule mol = Text_item::text2molecule (me, text, properties);
271 SCM space = me->get_grob_property ("word-space");
272 if (gh_number_p (space))
276 mol.add_at_edge (X_AXIS, RIGHT, m, gh_scm2double (space)
277 * Staff_symbol_referencer::staff_space (me));
279 return mol.smobbed_copy ();