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"
31 #include "ly-smobs.icc"
41 Lookup::Lookup (Lookup const& s)
43 font_name_ = s.font_name_;
50 Lookup::mark_smob (SCM s)
56 Lookup::print_smob (SCM s, SCM p, scm_print_state*)
58 scm_puts ("#<Lookup >#", p);
63 Lookup::equal_p (SCM a , SCM b)
65 return a == b ? SCM_BOOL_T : SCM_BOOL_F;
69 Lookup::do_smobify_self ()
74 IMPLEMENT_UNSMOB(Lookup, lookup);
75 IMPLEMENT_SMOBS(Lookup);
78 Lookup::make_lookup ()
80 Lookup * l = new Lookup;
81 SCM ls = l->self_scm_;
82 scm_unprotect_object (ls);
88 Lookup::afm_find (String s, bool warn) const
92 Lookup * me = (Lookup*)(this);
93 me->afm_l_ = all_fonts_global_p->find_afm (font_name_);
96 warning (_f ("can't find font: `%s'", font_name_));
97 warning (_f ("(search path: `%s')", global_path.str ().ch_C()));
98 error (_ ("Aborting"));
101 AFM_CharMetricInfo const *cm = afm_l_->find_char_metric (s, warn);
110 SCM at = (gh_list (ly_symbol2scm ("char"),
111 gh_int2scm (cm->code),
115 at= fontify_atom (afm_l_,at);
116 return Molecule ( afm_bbox_to_box (cm->charBBox), at);
123 Lookup::beam (Real slope, Real width, Real thick)
125 Real height = slope * width;
126 Real min_y = (0 <? height) - thick/2;
127 Real max_y = (0 >? height) + thick/2;
131 Box b( Interval (0, width),
132 Interval (min_y, max_y));
135 SCM at = gh_list (ly_symbol2scm ("beam"),
136 gh_double2scm (width),
137 gh_double2scm (slope),
138 gh_double2scm (thick),
140 return Molecule (b, at);
146 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
150 for (int i= 4; i -- ;)
152 l = gh_cons (ly_offset2scm (b.control_[i]), l);
155 SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
156 gh_double2scm (thick),
157 gh_double2scm (dash),
161 Box box (Interval(0,0),Interval( 0,0));
162 return Molecule (box, at);
169 Lookup::blank (Box b)
171 return Molecule (b, SCM_EOL);
176 Lookup::filledbox (Box b )
178 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
179 gh_double2scm (-b[X_AXIS][LEFT]),
180 gh_double2scm (b[X_AXIS][RIGHT]),
181 gh_double2scm (-b[Y_AXIS][DOWN]),
182 gh_double2scm (b[Y_AXIS][UP]),
185 return Molecule ( b,at);
189 Lookup::frame (Box b, Real thick)
198 Axis o = Axis ((a+1)%NO_AXES);
201 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
202 edges[o][DOWN] = b[o][DOWN] - thick/2;
203 edges[o][UP] = b[o][UP] + thick/2;
206 m.add_molecule (filledbox (edges));
208 while (flip (&d) != LEFT);
217 Since the user has direct access to TeX marcos,
218 that currently provide the only way to do
219 font selection, accents etc,
220 we try some halfbaked attempt to detect this TeX trickery.
223 sanitise_TeX_string (String text)
226 for (int i= 0; i < text.length_i (); i++)
233 else if (text[i] == '}')
239 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
243 text = to_str ('{', -brace_count) + text;
247 text = text + to_str ('}', brace_count);
258 sanitise_PS_string (String t)
264 TODO: move into Text_item. UGH: paper_l argument shoudl be junked.
267 Lookup::text (String style, String text, Paper_def *paper_l)
269 if (style.empty_b ())
273 Real font_h = paper_l->get_var ("font_normal");
274 if (paper_l->scope_p_->elem_b ("font_" + style))
276 font_h = paper_l->get_var ("font_" + style);
280 if (paper_l->scope_p_->elem_b ("magnification_" + style))
282 font_mag = (int)paper_l->get_var ("magnification_" + style);
285 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
286 scm_eval (ly_symbol2scm ("cmr-alist")));
290 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
293 Font_metric* metric_l = 0;
296 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
298 metric_l = all_fonts_global_p->find_font (style);
303 int i = text.index_i ("\\n");
306 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
307 i = text.index_i ("\\n");
310 Array<String> lines = String_convert::split_arr (text, '\n');
312 Real kern = paper_l->get_var ("line_kern");
314 for (int i=0; i < lines.size (); i++)
316 String str (lines[i]);
317 if (output_global_ch == "tex")
318 str = sanitise_TeX_string (str);
319 else if (output_global_ch == "ps")
320 str = sanitise_PS_string (str);
327 SCM first = gh_list (ly_symbol2scm ("text"),
328 ly_str02scm (lines[0].ch_C()),
330 first = fontify_atom (metric_l, first);
334 Molecule mol (metric_l->text_dimension (lines[0]), first);
336 for (i = 1; i < lines.size (); i++)
338 SCM line = (gh_list (ly_symbol2scm ("text"),
339 ly_str02scm (lines[i].ch_C ()),
341 line = fontify_atom (metric_l, line);
342 mol.add_at_edge (Y_AXIS, DOWN,
343 Molecule (metric_l->text_dimension (lines[i]), line),
353 Make a smooth curve along the points
356 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
358 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
362 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
363 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
368 scontrols[ i ] = ly_offset2scm(back.control_[i]);
370 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
373 Need the weird order b.o. the way PS want its arguments
375 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
377 for (int i= 8; i--; )
379 list = gh_cons (scontrols[indices[i]], list);
383 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
385 gh_double2scm (linethick),
388 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
389 return Molecule (b, at);
393 Lookup::accordion (SCM s, Real staff_space) const
396 String sym = ly_scm2string(gh_car (s));
397 String reg = ly_scm2string(gh_car (gh_cdr(s)));
399 if (sym == "Discant")
401 Molecule r = afm_find("accordion-accDiscant");
403 if (reg.left_str(1) == "F")
405 Molecule d = afm_find("accordion-accDot");
406 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
408 reg = reg.right_str(reg.length_i()-1);
411 if (reg.left_str(3) == "EEE")
414 reg = reg.right_str(reg.length_i()-3);
416 else if (reg.left_str(2) == "EE")
419 reg = reg.right_str(reg.length_i()-2);
421 else if (reg.left_str(2) == "Eh")
424 reg = reg.right_str(reg.length_i()-2);
426 else if (reg.left_str(1) == "E")
429 reg = reg.right_str(reg.length_i()-1);
433 Molecule d = afm_find("accordion-accDot");
434 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
439 Molecule d = afm_find("accordion-accDot");
440 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
441 d.translate_axis(0.8 * staff_space PT, X_AXIS);
446 Molecule d = afm_find("accordion-accDot");
447 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
448 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
451 if (reg.left_str(2) == "SS")
453 Molecule d = afm_find("accordion-accDot");
454 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
455 d.translate_axis(0.4 * staff_space PT, X_AXIS);
457 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
459 reg = reg.right_str(reg.length_i()-2);
461 if (reg.left_str(1) == "S")
463 Molecule d = afm_find("accordion-accDot");
464 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
466 reg = reg.right_str(reg.length_i()-1);
469 else if (sym == "Freebase")
471 Molecule r = afm_find("accordion-accFreebase");
473 if (reg.left_str(1) == "F")
475 Molecule d = afm_find("accordion-accDot");
476 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
478 reg = reg.right_str(reg.length_i()-1);
482 Molecule d = afm_find("accordion-accDot");
483 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
487 else if (sym == "Bayanbase")
489 Molecule r = afm_find("accordion-accBayanbase");
491 if (reg.left_str(1) == "T")
493 Molecule d = afm_find("accordion-accDot");
494 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
496 reg = reg.right_str(reg.length_i()-1);
498 /* include 4' reed just for completeness. You don't want to use this. */
499 if (reg.left_str(1) == "F")
501 Molecule d = afm_find("accordion-accDot");
502 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
504 reg = reg.right_str(reg.length_i()-1);
506 if (reg.left_str(2) == "EE")
508 Molecule d = afm_find("accordion-accDot");
509 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
510 d.translate_axis(0.4 * staff_space PT, X_AXIS);
512 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
514 reg = reg.right_str(reg.length_i()-2);
516 if (reg.left_str(1) == "E")
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 else if (sym == "Stdbase")
526 Molecule r = afm_find("accordion-accStdbase");
528 if (reg.left_str(1) == "T")
530 Molecule d = afm_find("accordion-accDot");
531 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
533 reg = reg.right_str(reg.length_i()-1);
535 if (reg.left_str(1) == "F")
537 Molecule d = afm_find("accordion-accDot");
538 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
540 reg = reg.right_str(reg.length_i()-1);
542 if (reg.left_str(1) == "M")
544 Molecule d = afm_find("accordion-accDot");
545 d.translate_axis(staff_space * 2 PT, Y_AXIS);
546 d.translate_axis(staff_space PT, X_AXIS);
548 reg = reg.right_str(reg.length_i()-1);
550 if (reg.left_str(1) == "E")
552 Molecule d = afm_find("accordion-accDot");
553 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
555 reg = reg.right_str(reg.length_i()-1);
557 if (reg.left_str(1) == "S")
559 Molecule d = afm_find("accordion-accDot");
560 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
562 reg = reg.right_str(reg.length_i()-1);
565 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
567 else if (sym == "SB")
569 Molecule r = afm_find("accordion-accSB");
572 else if (sym == "BB")
574 Molecule r = afm_find("accordion-accBB");
577 else if (sym == "OldEE")
579 Molecule r = afm_find("accordion-accOldEE");
582 else if (sym == "OldEES")
584 Molecule r = afm_find("accordion-accOldEES");