2 lookup.cc -- implement simple Lookup methods.
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 Jan Nieuwenhuizen <janneke@gnu.org>
18 #include "dimensions.hh"
20 #include "paper-def.hh"
21 #include "string-convert.hh"
22 #include "file-path.hh"
24 #include "lily-guile.hh"
25 #include "all-font-metrics.hh"
28 #include "molecule.hh"
30 #include "lily-guile.hh"
38 Lookup::Lookup (Lookup const& s)
40 font_name_ = s.font_name_;
48 Lookup::afm_find (String s, bool warn) const
52 Lookup * me = (Lookup*)(this);
53 me->afm_l_ = all_fonts_global_p->find_afm (font_name_);
56 warning (_f ("Can't find font: `%s'", font_name_));
57 warning (_f ("(search path `%s')", global_path.str ().ch_C()));
58 error (_ ("Aborting"));
61 AFM_CharMetricInfo const *cm = afm_l_->find_char_metric (s, warn);
70 SCM at = (gh_list (ly_symbol2scm ("char"),
71 gh_int2scm (cm->code),
74 at= fontify_atom (afm_l_,at);
75 return Molecule ( afm_bbox_to_box (cm->charBBox), at);
82 Lookup::beam (Real slope, Real width, Real thick)
84 Real height = slope * width;
85 Real min_y = (0 <? height) - thick/2;
86 Real max_y = (0 >? height) + thick/2;
90 Box b( Interval (0, width),
91 Interval (min_y, max_y));
94 SCM at = gh_list (ly_symbol2scm ("beam"),
95 gh_double2scm (width),
96 gh_double2scm (slope),
97 gh_double2scm (thick),
99 return Molecule (b, at);
105 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
108 // this is silly, we have array_to_scm
109 for (int i= 4; i -- ;)
111 l = gh_cons (to_scm (b.control_[i]), l);
114 SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
115 gh_double2scm (thick),
116 gh_double2scm (dash),
120 Box box (Interval(0,0),Interval( 0,0));
121 return Molecule (box, at);
128 Lookup::blank (Box b)
137 Lookup::filledbox (Box b )
139 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
140 gh_double2scm (-b[X_AXIS][LEFT]),
141 gh_double2scm (b[X_AXIS][RIGHT]),
142 gh_double2scm (-b[Y_AXIS][DOWN]),
143 gh_double2scm (b[Y_AXIS][UP]),
146 return Molecule ( b,at);
150 Lookup::frame (Box b, Real thick)
159 Axis o = Axis ((a+1)%NO_AXES);
162 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
163 edges[o][DOWN] = b[o][DOWN] - thick/2;
164 edges[o][UP] = b[o][UP] + thick/2;
167 m.add_molecule (filledbox (edges));
169 while (flip (&d) != LEFT);
178 Since the user has direct access to TeX marcos,
179 that currently provide the only way to do
180 font selection, accents etc,
181 we try some halfbaked attempt to detect this TeX trickery.
184 sanitise_TeX_string (String text)
187 for (int i= 0; i < text.length_i (); i++)
194 else if (text[i] == '}')
200 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
204 text = to_str ('{', -brace_count) + text;
208 text = text + to_str ('}', brace_count);
219 sanitise_PS_string (String t)
228 Lookup::text (String style, String text, Paper_def *paper_l)
230 if (style.empty_b ())
234 Real font_h = paper_l->get_var ("font_normal");
235 if (paper_l->scope_p_->elem_b ("font_" + style))
237 font_h = paper_l->get_var ("font_" + style);
241 if (paper_l->scope_p_->elem_b ("magnification_" + style))
243 font_mag = (int)paper_l->get_var ("magnification_" + style);
249 SCM l = ly_eval_str (("(style-to-cmr \"" + style + "\")").ch_C());
252 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
257 Font_metric* metric_l = 0;
260 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
262 metric_l = all_fonts_global_p->find_font (style);
267 int i = text.index_i ("\\n");
270 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
271 i = text.index_i ("\\n");
274 Array<String> lines = String_convert::split_arr (text, '\n');
276 Real kern = paper_l->get_var ("line_kern");
278 for (int i=0; i < lines.size (); i++)
280 String str (lines[i]);
281 if (output_global_ch == "tex")
282 str = sanitise_TeX_string (str);
283 else if (output_global_ch == "ps")
284 str = sanitise_PS_string (str);
289 SCM first = gh_list (ly_symbol2scm ("text"),
290 ly_str02scm (lines[0].ch_C()),
292 first = fontify_atom (metric_l, first);
296 Molecule mol (metric_l->text_dimension (lines[0]), first);
298 for (i = 1; i < lines.size (); i++)
300 SCM line = (gh_list (ly_symbol2scm ("text"),
301 ly_str02scm (lines[i].ch_C ()),
303 line = fontify_atom (metric_l, line);
304 mol.add_at_edge (Y_AXIS, DOWN,
305 Molecule (metric_l->text_dimension (lines[i]), line),
315 Make a smooth curve along the points
318 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
320 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
324 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
325 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
328 // this is silly, we have array_to_scm
330 scontrols[ i ] = to_scm (back.control_[i]);
332 scontrols[i+4] = to_scm (curve.control_[i]);
335 Need the weird order b.o. the way PS want its arguments
337 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
339 for (int i= 8; i--; )
341 list = gh_cons (scontrols[indices[i]], list);
345 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
347 gh_double2scm (linethick),
350 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
351 return Molecule (b, at);
355 Lookup::accordion (SCM s, Real staff_space) const
358 String sym = ly_scm2string(gh_car (s));
359 String reg = ly_scm2string(gh_car (gh_cdr(s)));
361 if (sym == "Discant")
363 Molecule r = afm_find("scripts-accDiscant");
365 if (reg.left_str(1) == "F")
367 Molecule d = afm_find("scripts-accDot");
368 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
370 reg = reg.right_str(reg.length_i()-1);
373 if (reg.left_str(3) == "EEE")
376 reg = reg.right_str(reg.length_i()-3);
378 else if (reg.left_str(2) == "EE")
381 reg = reg.right_str(reg.length_i()-2);
383 else if (reg.left_str(2) == "Eh")
386 reg = reg.right_str(reg.length_i()-2);
388 else if (reg.left_str(1) == "E")
391 reg = reg.right_str(reg.length_i()-1);
395 Molecule d = afm_find("scripts-accDot");
396 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
401 Molecule d = afm_find("scripts-accDot");
402 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
403 d.translate_axis(0.8 * staff_space PT, X_AXIS);
408 Molecule d = afm_find("scripts-accDot");
409 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
410 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
413 if (reg.left_str(2) == "SS")
415 Molecule d = afm_find("scripts-accDot");
416 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
417 d.translate_axis(0.4 * staff_space PT, X_AXIS);
419 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
421 reg = reg.right_str(reg.length_i()-2);
423 if (reg.left_str(1) == "S")
425 Molecule d = afm_find("scripts-accDot");
426 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
428 reg = reg.right_str(reg.length_i()-1);
431 else if (sym == "Freebase")
433 Molecule r = afm_find("scripts-accFreebase");
435 if (reg.left_str(1) == "F")
437 Molecule d = afm_find("scripts-accDot");
438 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
440 reg = reg.right_str(reg.length_i()-1);
444 Molecule d = afm_find("scripts-accDot");
445 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
449 else if (sym == "Bayanbase")
451 Molecule r = afm_find("scripts-accBayanbase");
453 if (reg.left_str(1) == "T")
455 Molecule d = afm_find("scripts-accDot");
456 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
458 reg = reg.right_str(reg.length_i()-1);
460 /* include 4' reed just for completeness. You don't want to use this. */
461 if (reg.left_str(1) == "F")
463 Molecule d = afm_find("scripts-accDot");
464 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
466 reg = reg.right_str(reg.length_i()-1);
468 if (reg.left_str(2) == "EE")
470 Molecule d = afm_find("scripts-accDot");
471 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
472 d.translate_axis(0.4 * staff_space PT, X_AXIS);
474 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
476 reg = reg.right_str(reg.length_i()-2);
478 if (reg.left_str(1) == "E")
480 Molecule d = afm_find("scripts-accDot");
481 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
483 reg = reg.right_str(reg.length_i()-1);
486 else if (sym == "Stdbase")
488 Molecule r = afm_find("scripts-accStdbase");
490 if (reg.left_str(1) == "T")
492 Molecule d = afm_find("scripts-accDot");
493 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
495 reg = reg.right_str(reg.length_i()-1);
497 if (reg.left_str(1) == "F")
499 Molecule d = afm_find("scripts-accDot");
500 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
502 reg = reg.right_str(reg.length_i()-1);
504 if (reg.left_str(1) == "M")
506 Molecule d = afm_find("scripts-accDot");
507 d.translate_axis(staff_space * 2 PT, Y_AXIS);
508 d.translate_axis(staff_space PT, X_AXIS);
510 reg = reg.right_str(reg.length_i()-1);
512 if (reg.left_str(1) == "E")
514 Molecule d = afm_find("scripts-accDot");
515 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
517 reg = reg.right_str(reg.length_i()-1);
519 if (reg.left_str(1) == "S")
521 Molecule d = afm_find("scripts-accDot");
522 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
524 reg = reg.right_str(reg.length_i()-1);
527 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
529 else if (sym == "SB")
531 Molecule r = afm_find("scripts-accSB");
534 else if (sym == "BB")
536 Molecule r = afm_find("scripts-accBB");
539 else if (sym == "OldEE")
541 Molecule r = afm_find("scripts-accOldEE");
544 else if (sym == "OldEES")
546 Molecule r = afm_find("scripts-accOldEES");