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);
291 SCM first = gh_list (ly_symbol2scm ("text"),
292 ly_str02scm (lines[0].ch_C()),
294 first = fontify_atom (metric_l, first);
298 Molecule mol (metric_l->text_dimension (lines[0]), first);
300 for (i = 1; i < lines.size (); i++)
302 SCM line = (gh_list (ly_symbol2scm ("text"),
303 ly_str02scm (lines[i].ch_C ()),
305 line = fontify_atom (metric_l, line);
306 mol.add_at_edge (Y_AXIS, DOWN,
307 Molecule (metric_l->text_dimension (lines[i]), line),
317 Make a smooth curve along the points
320 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
322 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
326 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
327 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
330 // this is silly, we have array_to_scm
332 scontrols[ i ] = to_scm (back.control_[i]);
334 scontrols[i+4] = to_scm (curve.control_[i]);
337 Need the weird order b.o. the way PS want its arguments
339 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
341 for (int i= 8; i--; )
343 list = gh_cons (scontrols[indices[i]], list);
347 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
349 gh_double2scm (linethick),
352 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
353 return Molecule (b, at);
357 Lookup::accordion (SCM s, Real staff_space) const
360 String sym = ly_scm2string(gh_car (s));
361 String reg = ly_scm2string(gh_car (gh_cdr(s)));
363 if (sym == "Discant")
365 Molecule r = afm_find("scripts-accDiscant");
367 if (reg.left_str(1) == "F")
369 Molecule d = afm_find("scripts-accDot");
370 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
372 reg = reg.right_str(reg.length_i()-1);
375 if (reg.left_str(3) == "EEE")
378 reg = reg.right_str(reg.length_i()-3);
380 else if (reg.left_str(2) == "EE")
383 reg = reg.right_str(reg.length_i()-2);
385 else if (reg.left_str(2) == "Eh")
388 reg = reg.right_str(reg.length_i()-2);
390 else if (reg.left_str(1) == "E")
393 reg = reg.right_str(reg.length_i()-1);
397 Molecule d = afm_find("scripts-accDot");
398 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
403 Molecule d = afm_find("scripts-accDot");
404 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
405 d.translate_axis(0.8 * staff_space PT, X_AXIS);
410 Molecule d = afm_find("scripts-accDot");
411 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
412 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
415 if (reg.left_str(2) == "SS")
417 Molecule d = afm_find("scripts-accDot");
418 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
419 d.translate_axis(0.4 * staff_space PT, X_AXIS);
421 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
423 reg = reg.right_str(reg.length_i()-2);
425 if (reg.left_str(1) == "S")
427 Molecule d = afm_find("scripts-accDot");
428 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
430 reg = reg.right_str(reg.length_i()-1);
433 else if (sym == "Freebase")
435 Molecule r = afm_find("scripts-accFreebase");
437 if (reg.left_str(1) == "F")
439 Molecule d = afm_find("scripts-accDot");
440 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
442 reg = reg.right_str(reg.length_i()-1);
446 Molecule d = afm_find("scripts-accDot");
447 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
451 else if (sym == "Bayanbase")
453 Molecule r = afm_find("scripts-accBayanbase");
455 if (reg.left_str(1) == "T")
457 Molecule d = afm_find("scripts-accDot");
458 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
460 reg = reg.right_str(reg.length_i()-1);
462 /* include 4' reed just for completeness. You don't want to use this. */
463 if (reg.left_str(1) == "F")
465 Molecule d = afm_find("scripts-accDot");
466 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
468 reg = reg.right_str(reg.length_i()-1);
470 if (reg.left_str(2) == "EE")
472 Molecule d = afm_find("scripts-accDot");
473 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
474 d.translate_axis(0.4 * staff_space PT, X_AXIS);
476 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
478 reg = reg.right_str(reg.length_i()-2);
480 if (reg.left_str(1) == "E")
482 Molecule d = afm_find("scripts-accDot");
483 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
485 reg = reg.right_str(reg.length_i()-1);
488 else if (sym == "Stdbase")
490 Molecule r = afm_find("scripts-accStdbase");
492 if (reg.left_str(1) == "T")
494 Molecule d = afm_find("scripts-accDot");
495 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
497 reg = reg.right_str(reg.length_i()-1);
499 if (reg.left_str(1) == "F")
501 Molecule d = afm_find("scripts-accDot");
502 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
504 reg = reg.right_str(reg.length_i()-1);
506 if (reg.left_str(1) == "M")
508 Molecule d = afm_find("scripts-accDot");
509 d.translate_axis(staff_space * 2 PT, Y_AXIS);
510 d.translate_axis(staff_space PT, X_AXIS);
512 reg = reg.right_str(reg.length_i()-1);
514 if (reg.left_str(1) == "E")
516 Molecule d = afm_find("scripts-accDot");
517 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
519 reg = reg.right_str(reg.length_i()-1);
521 if (reg.left_str(1) == "S")
523 Molecule d = afm_find("scripts-accDot");
524 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
526 reg = reg.right_str(reg.length_i()-1);
529 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
531 else if (sym == "SB")
533 Molecule r = afm_find("scripts-accSB");
536 else if (sym == "BB")
538 Molecule r = afm_find("scripts-accBB");
541 else if (sym == "OldEE")
543 Molecule r = afm_find("scripts-accOldEE");
546 else if (sym == "OldEES")
548 Molecule r = afm_find("scripts-accOldEES");