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)
109 for (int i= 4; i -- ;)
111 l = gh_cons (ly_offset2scm (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 = scm_eval (gh_list (ly_symbol2scm ("style-to-cmr"),
250 ly_str02scm (style.ch_C()),
255 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
260 Font_metric* metric_l = 0;
263 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
265 metric_l = all_fonts_global_p->find_font (style);
270 int i = text.index_i ("\\n");
273 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
274 i = text.index_i ("\\n");
277 Array<String> lines = String_convert::split_arr (text, '\n');
279 Real kern = paper_l->get_var ("line_kern");
281 for (int i=0; i < lines.size (); i++)
283 String str (lines[i]);
284 if (output_global_ch == "tex")
285 str = sanitise_TeX_string (str);
286 else if (output_global_ch == "ps")
287 str = sanitise_PS_string (str);
294 SCM first = gh_list (ly_symbol2scm ("text"),
295 ly_str02scm (lines[0].ch_C()),
297 first = fontify_atom (metric_l, first);
301 Molecule mol (metric_l->text_dimension (lines[0]), first);
303 for (i = 1; i < lines.size (); i++)
305 SCM line = (gh_list (ly_symbol2scm ("text"),
306 ly_str02scm (lines[i].ch_C ()),
308 line = fontify_atom (metric_l, line);
309 mol.add_at_edge (Y_AXIS, DOWN,
310 Molecule (metric_l->text_dimension (lines[i]), line),
320 Make a smooth curve along the points
323 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
325 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
329 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
330 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
335 scontrols[ i ] = ly_offset2scm(back.control_[i]);
337 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
340 Need the weird order b.o. the way PS want its arguments
342 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
344 for (int i= 8; i--; )
346 list = gh_cons (scontrols[indices[i]], list);
350 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
352 gh_double2scm (linethick),
355 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
356 return Molecule (b, at);
360 Lookup::accordion (SCM s, Real staff_space) const
363 String sym = ly_scm2string(gh_car (s));
364 String reg = ly_scm2string(gh_car (gh_cdr(s)));
366 if (sym == "Discant")
368 Molecule r = afm_find("accordion-accDiscant");
370 if (reg.left_str(1) == "F")
372 Molecule d = afm_find("accordion-accDot");
373 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
375 reg = reg.right_str(reg.length_i()-1);
378 if (reg.left_str(3) == "EEE")
381 reg = reg.right_str(reg.length_i()-3);
383 else if (reg.left_str(2) == "EE")
386 reg = reg.right_str(reg.length_i()-2);
388 else if (reg.left_str(2) == "Eh")
391 reg = reg.right_str(reg.length_i()-2);
393 else if (reg.left_str(1) == "E")
396 reg = reg.right_str(reg.length_i()-1);
400 Molecule d = afm_find("accordion-accDot");
401 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
406 Molecule d = afm_find("accordion-accDot");
407 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
408 d.translate_axis(0.8 * staff_space PT, X_AXIS);
413 Molecule d = afm_find("accordion-accDot");
414 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
415 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
418 if (reg.left_str(2) == "SS")
420 Molecule d = afm_find("accordion-accDot");
421 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
422 d.translate_axis(0.4 * staff_space PT, X_AXIS);
424 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
426 reg = reg.right_str(reg.length_i()-2);
428 if (reg.left_str(1) == "S")
430 Molecule d = afm_find("accordion-accDot");
431 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
433 reg = reg.right_str(reg.length_i()-1);
436 else if (sym == "Freebase")
438 Molecule r = afm_find("accordion-accFreebase");
440 if (reg.left_str(1) == "F")
442 Molecule d = afm_find("accordion-accDot");
443 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
445 reg = reg.right_str(reg.length_i()-1);
449 Molecule d = afm_find("accordion-accDot");
450 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
454 else if (sym == "Bayanbase")
456 Molecule r = afm_find("accordion-accBayanbase");
458 if (reg.left_str(1) == "T")
460 Molecule d = afm_find("accordion-accDot");
461 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
463 reg = reg.right_str(reg.length_i()-1);
465 /* include 4' reed just for completeness. You don't want to use this. */
466 if (reg.left_str(1) == "F")
468 Molecule d = afm_find("accordion-accDot");
469 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
471 reg = reg.right_str(reg.length_i()-1);
473 if (reg.left_str(2) == "EE")
475 Molecule d = afm_find("accordion-accDot");
476 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
477 d.translate_axis(0.4 * staff_space PT, X_AXIS);
479 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
481 reg = reg.right_str(reg.length_i()-2);
483 if (reg.left_str(1) == "E")
485 Molecule d = afm_find("accordion-accDot");
486 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
488 reg = reg.right_str(reg.length_i()-1);
491 else if (sym == "Stdbase")
493 Molecule r = afm_find("accordion-accStdbase");
495 if (reg.left_str(1) == "T")
497 Molecule d = afm_find("accordion-accDot");
498 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
500 reg = reg.right_str(reg.length_i()-1);
502 if (reg.left_str(1) == "F")
504 Molecule d = afm_find("accordion-accDot");
505 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
507 reg = reg.right_str(reg.length_i()-1);
509 if (reg.left_str(1) == "M")
511 Molecule d = afm_find("accordion-accDot");
512 d.translate_axis(staff_space * 2 PT, Y_AXIS);
513 d.translate_axis(staff_space PT, X_AXIS);
515 reg = reg.right_str(reg.length_i()-1);
517 if (reg.left_str(1) == "E")
519 Molecule d = afm_find("accordion-accDot");
520 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
522 reg = reg.right_str(reg.length_i()-1);
524 if (reg.left_str(1) == "S")
526 Molecule d = afm_find("accordion-accDot");
527 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
529 reg = reg.right_str(reg.length_i()-1);
532 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
534 else if (sym == "SB")
536 Molecule r = afm_find("accordion-accSB");
539 else if (sym == "BB")
541 Molecule r = afm_find("accordion-accBB");
544 else if (sym == "OldEE")
546 Molecule r = afm_find("accordion-accOldEE");
549 else if (sym == "OldEES")
551 Molecule r = afm_find("accordion-accOldEES");