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>
17 #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);
79 Lookup::simple_bar (String type, Real h, Paper_def* paper_l) const
81 SCM thick = ly_symbol2scm (("barthick_" + type).ch_C());
84 if (paper_l->scope_p_->elem_b (thick))
86 w = paper_l->get_realvar (thick);
90 programming_error ("No bar thickness set ! ");
93 return filledbox (Box (Interval(0,w), Interval(-h/2, h/2)));
98 Lookup::bar (String str, Real h, Paper_def *paper_l) const
100 if (str == "bracket")
101 return staff_bracket (h, paper_l);
102 else if (str == "brace")
104 Real staffht = paper_l->get_var ("staffheight");
105 return staff_brace (h,staffht);
107 Real kern = paper_l->get_var ("bar_kern");
108 Real thinkern = paper_l->get_var ("bar_thinkern");
110 Molecule thin = simple_bar ("thin", h, paper_l);
111 Molecule thick = simple_bar ("thick", h, paper_l);
112 Molecule colon = afm_find ("dots-repeatcolon", paper_l);
118 return fill (Box (Interval(0, 0), Interval (-h/2, h/2)));
120 if (str == "scorepostbreak")
122 return simple_bar ("score", h, paper_l);
128 else if (str == "|.")
130 m.add_at_edge (X_AXIS, LEFT, thick, 0);
131 m.add_at_edge (X_AXIS, LEFT, thin, kern);
133 else if (str == ".|")
135 m.add_at_edge (X_AXIS, RIGHT, thick, 0);
136 m.add_at_edge (X_AXIS, RIGHT, thin, kern);
138 else if (str == ":|")
140 m.add_at_edge (X_AXIS, LEFT, thick, 0);
141 m.add_at_edge (X_AXIS, LEFT, thin, kern);
142 m.add_at_edge (X_AXIS, LEFT, colon, kern);
144 else if (str == "|:")
146 m.add_at_edge (X_AXIS, RIGHT, thick, 0);
147 m.add_at_edge (X_AXIS, RIGHT, thin, kern);
148 m.add_at_edge (X_AXIS, RIGHT, colon, kern);
150 else if (str == ":|:")
152 m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
153 m.add_at_edge (X_AXIS, LEFT, colon, kern);
154 m.add_at_edge (X_AXIS, RIGHT, thick, kern);
155 m.add_at_edge (X_AXIS, RIGHT, colon, kern);
157 else if (str == ".|.")
159 m.add_at_edge (X_AXIS, LEFT, thick, thinkern);
160 m.add_at_edge (X_AXIS, RIGHT, thick, kern);
162 else if (str == "||")
164 m.add_at_edge (X_AXIS, RIGHT, thin, 0);
165 m.add_at_edge (X_AXIS, RIGHT, thin, thinkern);
172 Lookup::beam (Real slope, Real width, Real thick)
174 Real height = slope * width;
175 Real min_y = (0 <? height) - thick/2;
176 Real max_y = (0 >? height) + thick/2;
180 Box b( Interval (0, width),
181 Interval (min_y, max_y));
184 SCM at = gh_list (ly_symbol2scm ("beam"),
185 gh_double2scm (width),
186 gh_double2scm (slope),
187 gh_double2scm (thick),
189 return Molecule (b, at);
195 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
198 // this is silly, we have array_to_scm
199 for (int i= 4; i -- ;)
201 l = gh_cons (to_scm (b.control_[i]), l);
204 SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
205 gh_double2scm (thick),
206 gh_double2scm (dash),
210 Box box (Interval(0,0),Interval( 0,0));
211 return Molecule (box, at);
227 Lookup::filledbox (Box b )
229 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
230 gh_double2scm (-b[X_AXIS][LEFT]),
231 gh_double2scm (b[X_AXIS][RIGHT]),
232 gh_double2scm (-b[Y_AXIS][DOWN]),
233 gh_double2scm (b[Y_AXIS][UP]),
236 return Molecule ( b,at);
240 Lookup::frame (Box b, Real thick)
249 Axis o = Axis ((a+1)%NO_AXES);
252 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
253 edges[o][DOWN] = b[o][DOWN] - thick/2;
254 edges[o][UP] = b[o][UP] + thick/2;
257 m.add_molecule (filledbox (edges));
259 while (flip (&d) != LEFT);
268 Since the user has direct access to TeX marcos,
269 that currently provide the only way to do
270 font selection, accents etc,
271 we try some halfbaked attempt to detect this TeX trickery.
274 sanitise_TeX_string (String text)
277 for (int i= 0; i < text.length_i (); i++)
284 else if (text[i] == '}')
290 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
294 text = to_str ('{', -brace_count) + text;
298 text = text + to_str ('}', brace_count);
309 sanitise_PS_string (String t)
318 Lookup::text (String style, String text, Paper_def *paper_l)
320 if (style.empty_b ())
324 Real font_h = paper_l->get_var ("font_normal");
325 if (paper_l->scope_p_->elem_b ("font_" + style))
327 font_h = paper_l->get_var ("font_" + style);
331 if (paper_l->scope_p_->elem_b ("magnification_" + style))
333 font_mag = (int)paper_l->get_var ("magnification_" + style);
339 SCM l = ly_eval_str (("(style-to-cmr \"" + style + "\")").ch_C());
342 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
347 Font_metric* metric_l = 0;
350 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
352 metric_l = all_fonts_global_p->find_font (style);
357 int i = text.index_i ("\\n");
360 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
361 i = text.index_i ("\\n");
364 Array<String> lines = String_convert::split_arr (text, '\n');
368 Real kern = paper_l->get_var ("line_kern");
370 for (i = 0; i< lines.size (); i++)
373 Huh? This way we'll still see \foo sequences in ps output.
375 String str = lines[i];
376 if (output_global_ch == "tex")
377 str = sanitise_TeX_string (str);
378 else if (output_global_ch == "ps")
379 str = sanitise_PS_string (str);
381 SCM line = (gh_list (ly_symbol2scm ("text"),
382 ly_str02scm (str.ch_C ()),
384 line = fontify_atom (metric_l, line);
385 mol.add_at_edge (Y_AXIS, DOWN,
386 Molecule (metric_l->text_dimension (str), line),
396 Lookup::staff_brace (Real y, int staff_size)
400 int minht = 2 * staff_size;
401 int maxht = 7 * minht;
402 int idx = int (((maxht - step) <? y - minht) / step);
405 SCM l = ly_eval_str ("(style-to-cmr \"brace\")");
406 String nm = "feta-braces";
408 nm = ly_scm2string (gh_cdr (l));
409 nm += to_str (staff_size);
410 SCM e =gh_list (ly_symbol2scm ("char"), gh_int2scm (idx), SCM_UNDEFINED);
413 at = fontify_atom (all_fonts_global_p->find_font (nm), at);
415 Box b ( Interval (-y/2,y/2),
417 return Molecule(b, at);
422 Make a smooth curve along the points
425 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
427 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
431 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
432 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
435 // this is silly, we have array_to_scm
437 scontrols[ i ] = to_scm (back.control_[i]);
439 scontrols[i+4] = to_scm (curve.control_[i]);
442 Need the weird order b.o. the way PS want its arguments
444 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
446 for (int i= 8; i--; )
448 list = gh_cons (scontrols[indices[i]], list);
452 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
454 gh_double2scm (linethick),
457 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
458 return Molecule (b, at);
462 Lookup::staff_bracket (Real height, Paper_def* paper_l)
464 SCM at = ( gh_list (ly_symbol2scm ("bracket"),
465 gh_double2scm (paper_l->get_var("bracket_arch_angle")),
466 gh_double2scm (paper_l->get_var("bracket_arch_width")),
467 gh_double2scm (paper_l->get_var("bracket_arch_height")),
468 gh_double2scm (paper_l->get_var("bracket_width")),
469 gh_double2scm (height),
470 gh_double2scm (paper_l->get_var("bracket_arch_thick")),
471 gh_double2scm (paper_l->get_var("bracket_thick")),
474 Real staff_space = paper_l->get_var ("interline");
475 Box b (Interval (0, 1.5 * staff_space), Interval (-height/2,height/2));
476 Molecule mol (b, at);
478 mol.translate_axis (- mol.dim_[X_AXIS].length () / 2, X_AXIS);
484 Lookup::accordion (SCM s, Real staff_space) const
487 String sym = ly_scm2string(gh_car (s));
488 String reg = ly_scm2string(gh_car (gh_cdr(s)));
490 if (sym == "Discant")
492 Molecule r = afm_find("scripts-accDiscant");
494 if (reg.left_str(1) == "F")
496 Molecule d = afm_find("scripts-accDot");
497 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
499 reg = reg.right_str(reg.length_i()-1);
502 if (reg.left_str(3) == "EEE")
505 reg = reg.right_str(reg.length_i()-3);
507 else if (reg.left_str(2) == "EE")
510 reg = reg.right_str(reg.length_i()-2);
512 else if (reg.left_str(2) == "Eh")
515 reg = reg.right_str(reg.length_i()-2);
517 else if (reg.left_str(1) == "E")
520 reg = reg.right_str(reg.length_i()-1);
524 Molecule d = afm_find("scripts-accDot");
525 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
530 Molecule d = afm_find("scripts-accDot");
531 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
532 d.translate_axis(0.8 * staff_space PT, X_AXIS);
537 Molecule d = afm_find("scripts-accDot");
538 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
539 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
542 if (reg.left_str(2) == "SS")
544 Molecule d = afm_find("scripts-accDot");
545 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
546 d.translate_axis(0.4 * staff_space PT, X_AXIS);
548 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
550 reg = reg.right_str(reg.length_i()-2);
552 if (reg.left_str(1) == "S")
554 Molecule d = afm_find("scripts-accDot");
555 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
557 reg = reg.right_str(reg.length_i()-1);
560 else if (sym == "Freebase")
562 Molecule r = afm_find("scripts-accFreebase");
564 if (reg.left_str(1) == "F")
566 Molecule d = afm_find("scripts-accDot");
567 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
569 reg = reg.right_str(reg.length_i()-1);
573 Molecule d = afm_find("scripts-accDot");
574 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
578 else if (sym == "Bayanbase")
580 Molecule r = afm_find("scripts-accBayanbase");
582 if (reg.left_str(1) == "T")
584 Molecule d = afm_find("scripts-accDot");
585 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
587 reg = reg.right_str(reg.length_i()-1);
589 /* include 4' reed just for completeness. You don't want to use this. */
590 if (reg.left_str(1) == "F")
592 Molecule d = afm_find("scripts-accDot");
593 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
595 reg = reg.right_str(reg.length_i()-1);
597 if (reg.left_str(2) == "EE")
599 Molecule d = afm_find("scripts-accDot");
600 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
601 d.translate_axis(0.4 * staff_space PT, X_AXIS);
603 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
605 reg = reg.right_str(reg.length_i()-2);
607 if (reg.left_str(1) == "E")
609 Molecule d = afm_find("scripts-accDot");
610 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
612 reg = reg.right_str(reg.length_i()-1);
615 else if (sym == "Stdbase")
617 Molecule r = afm_find("scripts-accStdbase");
619 if (reg.left_str(1) == "T")
621 Molecule d = afm_find("scripts-accDot");
622 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
624 reg = reg.right_str(reg.length_i()-1);
626 if (reg.left_str(1) == "F")
628 Molecule d = afm_find("scripts-accDot");
629 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
631 reg = reg.right_str(reg.length_i()-1);
633 if (reg.left_str(1) == "M")
635 Molecule d = afm_find("scripts-accDot");
636 d.translate_axis(staff_space * 2 PT, Y_AXIS);
637 d.translate_axis(staff_space PT, X_AXIS);
639 reg = reg.right_str(reg.length_i()-1);
641 if (reg.left_str(1) == "E")
643 Molecule d = afm_find("scripts-accDot");
644 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
646 reg = reg.right_str(reg.length_i()-1);
648 if (reg.left_str(1) == "S")
650 Molecule d = afm_find("scripts-accDot");
651 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
653 reg = reg.right_str(reg.length_i()-1);
656 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
658 else if (sym == "SB")
660 Molecule r = afm_find("scripts-accSB");
663 else if (sym == "BB")
665 Molecule r = afm_find("scripts-accBB");
668 else if (sym == "OldEE")
670 Molecule r = afm_find("scripts-accOldEE");
673 else if (sym == "OldEES")
675 Molecule r = afm_find("scripts-accOldEES");