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)
130 return Molecule (b, SCM_EOL);
135 Lookup::filledbox (Box b )
137 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
138 gh_double2scm (-b[X_AXIS][LEFT]),
139 gh_double2scm (b[X_AXIS][RIGHT]),
140 gh_double2scm (-b[Y_AXIS][DOWN]),
141 gh_double2scm (b[Y_AXIS][UP]),
144 return Molecule ( b,at);
148 Lookup::frame (Box b, Real thick)
157 Axis o = Axis ((a+1)%NO_AXES);
160 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
161 edges[o][DOWN] = b[o][DOWN] - thick/2;
162 edges[o][UP] = b[o][UP] + thick/2;
165 m.add_molecule (filledbox (edges));
167 while (flip (&d) != LEFT);
176 Since the user has direct access to TeX marcos,
177 that currently provide the only way to do
178 font selection, accents etc,
179 we try some halfbaked attempt to detect this TeX trickery.
182 sanitise_TeX_string (String text)
185 for (int i= 0; i < text.length_i (); i++)
192 else if (text[i] == '}')
198 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
202 text = to_str ('{', -brace_count) + text;
206 text = text + to_str ('}', brace_count);
217 sanitise_PS_string (String t)
226 Lookup::text (String style, String text, Paper_def *paper_l)
228 if (style.empty_b ())
232 Real font_h = paper_l->get_var ("font_normal");
233 if (paper_l->scope_p_->elem_b ("font_" + style))
235 font_h = paper_l->get_var ("font_" + style);
239 if (paper_l->scope_p_->elem_b ("magnification_" + style))
241 font_mag = (int)paper_l->get_var ("magnification_" + style);
244 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
245 scm_eval (ly_symbol2scm ("cmr-alist")));
249 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
252 Font_metric* metric_l = 0;
255 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
257 metric_l = all_fonts_global_p->find_font (style);
262 int i = text.index_i ("\\n");
265 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
266 i = text.index_i ("\\n");
269 Array<String> lines = String_convert::split_arr (text, '\n');
271 Real kern = paper_l->get_var ("line_kern");
273 for (int i=0; i < lines.size (); i++)
275 String str (lines[i]);
276 if (output_global_ch == "tex")
277 str = sanitise_TeX_string (str);
278 else if (output_global_ch == "ps")
279 str = sanitise_PS_string (str);
286 SCM first = gh_list (ly_symbol2scm ("text"),
287 ly_str02scm (lines[0].ch_C()),
289 first = fontify_atom (metric_l, first);
293 Molecule mol (metric_l->text_dimension (lines[0]), first);
295 for (i = 1; i < lines.size (); i++)
297 SCM line = (gh_list (ly_symbol2scm ("text"),
298 ly_str02scm (lines[i].ch_C ()),
300 line = fontify_atom (metric_l, line);
301 mol.add_at_edge (Y_AXIS, DOWN,
302 Molecule (metric_l->text_dimension (lines[i]), line),
312 Make a smooth curve along the points
315 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
317 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
321 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
322 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
327 scontrols[ i ] = ly_offset2scm(back.control_[i]);
329 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
332 Need the weird order b.o. the way PS want its arguments
334 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
336 for (int i= 8; i--; )
338 list = gh_cons (scontrols[indices[i]], list);
342 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
344 gh_double2scm (linethick),
347 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
348 return Molecule (b, at);
352 Lookup::accordion (SCM s, Real staff_space) const
355 String sym = ly_scm2string(gh_car (s));
356 String reg = ly_scm2string(gh_car (gh_cdr(s)));
358 if (sym == "Discant")
360 Molecule r = afm_find("accordion-accDiscant");
362 if (reg.left_str(1) == "F")
364 Molecule d = afm_find("accordion-accDot");
365 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
367 reg = reg.right_str(reg.length_i()-1);
370 if (reg.left_str(3) == "EEE")
373 reg = reg.right_str(reg.length_i()-3);
375 else if (reg.left_str(2) == "EE")
378 reg = reg.right_str(reg.length_i()-2);
380 else if (reg.left_str(2) == "Eh")
383 reg = reg.right_str(reg.length_i()-2);
385 else if (reg.left_str(1) == "E")
388 reg = reg.right_str(reg.length_i()-1);
392 Molecule d = afm_find("accordion-accDot");
393 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
398 Molecule d = afm_find("accordion-accDot");
399 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
400 d.translate_axis(0.8 * staff_space PT, X_AXIS);
405 Molecule d = afm_find("accordion-accDot");
406 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
407 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
410 if (reg.left_str(2) == "SS")
412 Molecule d = afm_find("accordion-accDot");
413 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
414 d.translate_axis(0.4 * staff_space PT, X_AXIS);
416 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
418 reg = reg.right_str(reg.length_i()-2);
420 if (reg.left_str(1) == "S")
422 Molecule d = afm_find("accordion-accDot");
423 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
425 reg = reg.right_str(reg.length_i()-1);
428 else if (sym == "Freebase")
430 Molecule r = afm_find("accordion-accFreebase");
432 if (reg.left_str(1) == "F")
434 Molecule d = afm_find("accordion-accDot");
435 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
437 reg = reg.right_str(reg.length_i()-1);
441 Molecule d = afm_find("accordion-accDot");
442 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
446 else if (sym == "Bayanbase")
448 Molecule r = afm_find("accordion-accBayanbase");
450 if (reg.left_str(1) == "T")
452 Molecule d = afm_find("accordion-accDot");
453 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
455 reg = reg.right_str(reg.length_i()-1);
457 /* include 4' reed just for completeness. You don't want to use this. */
458 if (reg.left_str(1) == "F")
460 Molecule d = afm_find("accordion-accDot");
461 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
463 reg = reg.right_str(reg.length_i()-1);
465 if (reg.left_str(2) == "EE")
467 Molecule d = afm_find("accordion-accDot");
468 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
469 d.translate_axis(0.4 * staff_space PT, X_AXIS);
471 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
473 reg = reg.right_str(reg.length_i()-2);
475 if (reg.left_str(1) == "E")
477 Molecule d = afm_find("accordion-accDot");
478 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
480 reg = reg.right_str(reg.length_i()-1);
483 else if (sym == "Stdbase")
485 Molecule r = afm_find("accordion-accStdbase");
487 if (reg.left_str(1) == "T")
489 Molecule d = afm_find("accordion-accDot");
490 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
492 reg = reg.right_str(reg.length_i()-1);
494 if (reg.left_str(1) == "F")
496 Molecule d = afm_find("accordion-accDot");
497 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
499 reg = reg.right_str(reg.length_i()-1);
501 if (reg.left_str(1) == "M")
503 Molecule d = afm_find("accordion-accDot");
504 d.translate_axis(staff_space * 2 PT, Y_AXIS);
505 d.translate_axis(staff_space PT, X_AXIS);
507 reg = reg.right_str(reg.length_i()-1);
509 if (reg.left_str(1) == "E")
511 Molecule d = afm_find("accordion-accDot");
512 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
514 reg = reg.right_str(reg.length_i()-1);
516 if (reg.left_str(1) == "S")
518 Molecule d = afm_find("accordion-accDot");
519 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
521 reg = reg.right_str(reg.length_i()-1);
524 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
526 else if (sym == "SB")
528 Molecule r = afm_find("accordion-accSB");
531 else if (sym == "BB")
533 Molecule r = afm_find("accordion-accBB");
536 else if (sym == "OldEE")
538 Molecule r = afm_find("accordion-accOldEE");
541 else if (sym == "OldEES")
543 Molecule r = afm_find("accordion-accOldEES");