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)
93 SCM list = scm_list_n (ly_symbol2scm ("text"), text, SCM_UNDEFINED);
94 list = fontify_atom (fm, list);
96 return Molecule (fm->text_dimension (ly_scm2string (text)), list);
105 MARKUP_TEXT must be compound (may not be simple string.)
109 Text_item::markup_text2molecule (Grob *me, SCM markup_text,
112 SCM sheet = me->paper_l ()->style_sheet_;
113 SCM f = ly_cdr (scm_assoc (ly_symbol2scm ("markup-to-properties"), sheet));
115 SCM markup = ly_car (markup_text);
116 SCM text = ly_cdr (markup_text);
118 SCM p = gh_cons (gh_call2 (f, sheet, markup), alist_chain);
120 Real staff_space = Staff_symbol_referencer::staff_space (me);
123 Line mode is default.
127 SCM a = ly_assoc_chain (ly_symbol2scm ("axis"), p);
128 if (gh_pair_p (a) && ly_axis_p (ly_cdr (a)))
129 axis = (Axis)gh_scm2int (ly_cdr (a));
131 Real baseline_skip = 0;
132 SCM b = ly_assoc_chain (ly_symbol2scm ("baseline-skip"), p);
133 if (gh_pair_p (b) && gh_number_p (ly_cdr (b)))
134 baseline_skip = gh_scm2double (ly_cdr (b)) * staff_space;
136 Real kern[2] = {0,0};
138 SCM k = ly_assoc_chain (ly_symbol2scm ("kern"), p);
139 if (gh_pair_p (k) && gh_number_p (ly_cdr (k)))
140 kern[axis] = gh_scm2double (ly_cdr (k)) * staff_space;
143 SCM r = ly_assoc_chain (ly_symbol2scm ("raise"), p);
144 if (gh_pair_p (r) && gh_number_p (ly_cdr (r)))
145 raise = gh_scm2double (ly_cdr (r)) * staff_space;
148 bool extent_b = false;
149 SCM e = ly_assoc_chain (ly_symbol2scm ("extent"), p);
150 if (gh_pair_p (e) && ly_number_pair_p (ly_cdr (e)))
152 extent = Interval (gh_scm2double (ly_cadr (e)) * staff_space,
153 gh_scm2double (ly_cddr (e)) * staff_space);
157 Offset o (0, (axis == Y_AXIS ? - kern[axis] : 0));
160 while (gh_pair_p (text))
163 Molecule m = text2molecule (me, ly_car (text), p);
166 TODO: look at padding?
168 Look ahead here for kern and raise.
170 (cols "foo" ((raise . 1) "bar"))
171 (cols "foo" ((bold (raise . 1)) "bar"))
173 When constructing the molecule for bar, all normal extra
174 properties found, such as bold, are used for the construction
175 of bar's molecule. But for kern or raise, it seems that we're
176 too late then, translating bar's molecule has no effect (or
177 maybe the effect of translating gets nullified when bar's
178 molecule is `added_to_edge' of the molecule for foo?)
180 So, while constructing foo's molecule, we look ahead for the
181 raise of bar. The HEAD of the description of bar may be a
182 single property, or a list, so we must check that too.
185 SCM next_p = SCM_EOL;
186 if (gh_pair_p (ly_car (text)))
187 next_p = scm_list_n (gh_call2 (f, sheet, ly_caar (text)), SCM_UNDEFINED);
188 SCM next_k = ly_assoc_chain (ly_symbol2scm ("kern"), next_p);
189 Real next_kern = kern[axis];
190 if (gh_pair_p (next_k) && gh_number_p (ly_cdr (next_k)))
191 next_kern = gh_scm2double (ly_cdr (next_k)) * staff_space;
193 SCM next_r = ly_assoc_chain (ly_symbol2scm ("raise"), next_p);
195 if (gh_pair_p (next_r) && gh_number_p (ly_cdr (next_r)))
196 next_raise = gh_scm2double (ly_cdr (next_r)) * staff_space;
198 o[Y_AXIS] = next_raise;
207 if (axis == Y_AXIS && baseline_skip)
208 next_kern += baseline_skip - m.extent (Y_AXIS)[UP];
209 mol.add_at_edge (axis, axis == X_AXIS ? RIGHT : DOWN, m, next_kern);
212 text = ly_cdr (text);
217 /* we're not setting extents for unknown reasons. */
218 Box b = mol.extent_box ();
219 SCM expr = mol.get_expr ();
222 mol = Molecule (b, expr);
227 MAKE_SCHEME_CALLBACK (Text_item, brew_molecule, 1);
229 Text_item::brew_molecule (SCM smob)
231 Grob *me = unsmob_grob (smob);
233 SCM text = me->get_grob_property ("text");
235 SCM properties = Font_interface::font_alist_chain (me);
236 Molecule mol = Text_item::text2molecule (me, text, properties);
238 SCM space = me->get_grob_property ("word-space");
239 if (gh_number_p (space))
243 mol.add_at_edge (X_AXIS, RIGHT, m, gh_scm2double (space)
244 * Staff_symbol_referencer::staff_space (me));
246 return mol.smobbed_copy ();
252 ADD_INTERFACE (Text_item,"text-interface",
253 "A scheme markup text",
254 "text align baseline-skip lookup raise kern word-space magnify");