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);
247 SCM l = scm_eval (gh_list (ly_symbol2scm ("style-to-cmr"),
248 ly_str02scm (style.ch_C()),
253 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
258 Font_metric* metric_l = 0;
261 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
263 metric_l = all_fonts_global_p->find_font (style);
268 int i = text.index_i ("\\n");
271 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
272 i = text.index_i ("\\n");
275 Array<String> lines = String_convert::split_arr (text, '\n');
277 Real kern = paper_l->get_var ("line_kern");
279 for (int i=0; i < lines.size (); i++)
281 String str (lines[i]);
282 if (output_global_ch == "tex")
283 str = sanitise_TeX_string (str);
284 else if (output_global_ch == "ps")
285 str = sanitise_PS_string (str);
292 SCM first = gh_list (ly_symbol2scm ("text"),
293 ly_str02scm (lines[0].ch_C()),
295 first = fontify_atom (metric_l, first);
299 Molecule mol (metric_l->text_dimension (lines[0]), first);
301 for (i = 1; i < lines.size (); i++)
303 SCM line = (gh_list (ly_symbol2scm ("text"),
304 ly_str02scm (lines[i].ch_C ()),
306 line = fontify_atom (metric_l, line);
307 mol.add_at_edge (Y_AXIS, DOWN,
308 Molecule (metric_l->text_dimension (lines[i]), line),
318 Make a smooth curve along the points
321 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
323 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
327 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
328 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
333 scontrols[ i ] = ly_offset2scm(back.control_[i]);
335 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
338 Need the weird order b.o. the way PS want its arguments
340 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
342 for (int i= 8; i--; )
344 list = gh_cons (scontrols[indices[i]], list);
348 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
350 gh_double2scm (linethick),
353 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
354 return Molecule (b, at);
358 Lookup::accordion (SCM s, Real staff_space) const
361 String sym = ly_scm2string(gh_car (s));
362 String reg = ly_scm2string(gh_car (gh_cdr(s)));
364 if (sym == "Discant")
366 Molecule r = afm_find("accordion-accDiscant");
368 if (reg.left_str(1) == "F")
370 Molecule d = afm_find("accordion-accDot");
371 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
373 reg = reg.right_str(reg.length_i()-1);
376 if (reg.left_str(3) == "EEE")
379 reg = reg.right_str(reg.length_i()-3);
381 else if (reg.left_str(2) == "EE")
384 reg = reg.right_str(reg.length_i()-2);
386 else if (reg.left_str(2) == "Eh")
389 reg = reg.right_str(reg.length_i()-2);
391 else if (reg.left_str(1) == "E")
394 reg = reg.right_str(reg.length_i()-1);
398 Molecule d = afm_find("accordion-accDot");
399 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
404 Molecule d = afm_find("accordion-accDot");
405 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
406 d.translate_axis(0.8 * staff_space PT, X_AXIS);
411 Molecule d = afm_find("accordion-accDot");
412 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
413 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
416 if (reg.left_str(2) == "SS")
418 Molecule d = afm_find("accordion-accDot");
419 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
420 d.translate_axis(0.4 * staff_space PT, X_AXIS);
422 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
424 reg = reg.right_str(reg.length_i()-2);
426 if (reg.left_str(1) == "S")
428 Molecule d = afm_find("accordion-accDot");
429 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
431 reg = reg.right_str(reg.length_i()-1);
434 else if (sym == "Freebase")
436 Molecule r = afm_find("accordion-accFreebase");
438 if (reg.left_str(1) == "F")
440 Molecule d = afm_find("accordion-accDot");
441 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
443 reg = reg.right_str(reg.length_i()-1);
447 Molecule d = afm_find("accordion-accDot");
448 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
452 else if (sym == "Bayanbase")
454 Molecule r = afm_find("accordion-accBayanbase");
456 if (reg.left_str(1) == "T")
458 Molecule d = afm_find("accordion-accDot");
459 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
461 reg = reg.right_str(reg.length_i()-1);
463 /* include 4' reed just for completeness. You don't want to use this. */
464 if (reg.left_str(1) == "F")
466 Molecule d = afm_find("accordion-accDot");
467 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
469 reg = reg.right_str(reg.length_i()-1);
471 if (reg.left_str(2) == "EE")
473 Molecule d = afm_find("accordion-accDot");
474 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
475 d.translate_axis(0.4 * staff_space PT, X_AXIS);
477 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
479 reg = reg.right_str(reg.length_i()-2);
481 if (reg.left_str(1) == "E")
483 Molecule d = afm_find("accordion-accDot");
484 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
486 reg = reg.right_str(reg.length_i()-1);
489 else if (sym == "Stdbase")
491 Molecule r = afm_find("accordion-accStdbase");
493 if (reg.left_str(1) == "T")
495 Molecule d = afm_find("accordion-accDot");
496 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
498 reg = reg.right_str(reg.length_i()-1);
500 if (reg.left_str(1) == "F")
502 Molecule d = afm_find("accordion-accDot");
503 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
505 reg = reg.right_str(reg.length_i()-1);
507 if (reg.left_str(1) == "M")
509 Molecule d = afm_find("accordion-accDot");
510 d.translate_axis(staff_space * 2 PT, Y_AXIS);
511 d.translate_axis(staff_space PT, X_AXIS);
513 reg = reg.right_str(reg.length_i()-1);
515 if (reg.left_str(1) == "E")
517 Molecule d = afm_find("accordion-accDot");
518 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
520 reg = reg.right_str(reg.length_i()-1);
522 if (reg.left_str(1) == "S")
524 Molecule d = afm_find("accordion-accDot");
525 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
527 reg = reg.right_str(reg.length_i()-1);
530 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
532 else if (sym == "SB")
534 Molecule r = afm_find("accordion-accSB");
537 else if (sym == "BB")
539 Molecule r = afm_find("accordion-accBB");
542 else if (sym == "OldEE")
544 Molecule r = afm_find("accordion-accOldEE");
547 else if (sym == "OldEES")
549 Molecule r = afm_find("accordion-accOldEES");