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');
278 Real kern = paper_l->get_var ("line_kern");
280 for (i = 0; i< lines.size (); i++)
283 Huh? This way we'll still see \foo sequences in ps output.
285 String str = lines[i];
286 if (output_global_ch == "tex")
287 str = sanitise_TeX_string (str);
288 else if (output_global_ch == "ps")
289 str = sanitise_PS_string (str);
291 SCM line = (gh_list (ly_symbol2scm ("text"),
292 ly_str02scm (str.ch_C ()),
294 line = fontify_atom (metric_l, line);
295 mol.add_at_edge (Y_AXIS, DOWN,
296 Molecule (metric_l->text_dimension (str), line),
306 Make a smooth curve along the points
309 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
311 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
315 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
316 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
319 // this is silly, we have array_to_scm
321 scontrols[ i ] = to_scm (back.control_[i]);
323 scontrols[i+4] = to_scm (curve.control_[i]);
326 Need the weird order b.o. the way PS want its arguments
328 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
330 for (int i= 8; i--; )
332 list = gh_cons (scontrols[indices[i]], list);
336 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
338 gh_double2scm (linethick),
341 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
342 return Molecule (b, at);
346 Lookup::accordion (SCM s, Real staff_space) const
349 String sym = ly_scm2string(gh_car (s));
350 String reg = ly_scm2string(gh_car (gh_cdr(s)));
352 if (sym == "Discant")
354 Molecule r = afm_find("scripts-accDiscant");
356 if (reg.left_str(1) == "F")
358 Molecule d = afm_find("scripts-accDot");
359 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
361 reg = reg.right_str(reg.length_i()-1);
364 if (reg.left_str(3) == "EEE")
367 reg = reg.right_str(reg.length_i()-3);
369 else if (reg.left_str(2) == "EE")
372 reg = reg.right_str(reg.length_i()-2);
374 else if (reg.left_str(2) == "Eh")
377 reg = reg.right_str(reg.length_i()-2);
379 else if (reg.left_str(1) == "E")
382 reg = reg.right_str(reg.length_i()-1);
386 Molecule d = afm_find("scripts-accDot");
387 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
392 Molecule d = afm_find("scripts-accDot");
393 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
394 d.translate_axis(0.8 * staff_space PT, X_AXIS);
399 Molecule d = afm_find("scripts-accDot");
400 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
401 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
404 if (reg.left_str(2) == "SS")
406 Molecule d = afm_find("scripts-accDot");
407 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
408 d.translate_axis(0.4 * staff_space PT, X_AXIS);
410 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
412 reg = reg.right_str(reg.length_i()-2);
414 if (reg.left_str(1) == "S")
416 Molecule d = afm_find("scripts-accDot");
417 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
419 reg = reg.right_str(reg.length_i()-1);
422 else if (sym == "Freebase")
424 Molecule r = afm_find("scripts-accFreebase");
426 if (reg.left_str(1) == "F")
428 Molecule d = afm_find("scripts-accDot");
429 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
431 reg = reg.right_str(reg.length_i()-1);
435 Molecule d = afm_find("scripts-accDot");
436 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
440 else if (sym == "Bayanbase")
442 Molecule r = afm_find("scripts-accBayanbase");
444 if (reg.left_str(1) == "T")
446 Molecule d = afm_find("scripts-accDot");
447 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
449 reg = reg.right_str(reg.length_i()-1);
451 /* include 4' reed just for completeness. You don't want to use this. */
452 if (reg.left_str(1) == "F")
454 Molecule d = afm_find("scripts-accDot");
455 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
457 reg = reg.right_str(reg.length_i()-1);
459 if (reg.left_str(2) == "EE")
461 Molecule d = afm_find("scripts-accDot");
462 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
463 d.translate_axis(0.4 * staff_space PT, X_AXIS);
465 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
467 reg = reg.right_str(reg.length_i()-2);
469 if (reg.left_str(1) == "E")
471 Molecule d = afm_find("scripts-accDot");
472 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
474 reg = reg.right_str(reg.length_i()-1);
477 else if (sym == "Stdbase")
479 Molecule r = afm_find("scripts-accStdbase");
481 if (reg.left_str(1) == "T")
483 Molecule d = afm_find("scripts-accDot");
484 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
486 reg = reg.right_str(reg.length_i()-1);
488 if (reg.left_str(1) == "F")
490 Molecule d = afm_find("scripts-accDot");
491 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
493 reg = reg.right_str(reg.length_i()-1);
495 if (reg.left_str(1) == "M")
497 Molecule d = afm_find("scripts-accDot");
498 d.translate_axis(staff_space * 2 PT, Y_AXIS);
499 d.translate_axis(staff_space PT, X_AXIS);
501 reg = reg.right_str(reg.length_i()-1);
503 if (reg.left_str(1) == "E")
505 Molecule d = afm_find("scripts-accDot");
506 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
508 reg = reg.right_str(reg.length_i()-1);
510 if (reg.left_str(1) == "S")
512 Molecule d = afm_find("scripts-accDot");
513 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
515 reg = reg.right_str(reg.length_i()-1);
518 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
520 else if (sym == "SB")
522 Molecule r = afm_find("scripts-accSB");
525 else if (sym == "BB")
527 Molecule r = afm_find("scripts-accBB");
530 else if (sym == "OldEE")
532 Molecule r = afm_find("scripts-accOldEE");
535 else if (sym == "OldEES")
537 Molecule r = afm_find("scripts-accOldEES");