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),
114 at= fontify_atom (afm_l_,at);
115 return Molecule ( afm_bbox_to_box (cm->charBBox), at);
122 Lookup::beam (Real slope, Real width, Real thick)
124 Real height = slope * width;
125 Real min_y = (0 <? height) - thick/2;
126 Real max_y = (0 >? height) + thick/2;
130 Box b( Interval (0, width),
131 Interval (min_y, max_y));
134 SCM at = gh_list (ly_symbol2scm ("beam"),
135 gh_double2scm (width),
136 gh_double2scm (slope),
137 gh_double2scm (thick),
139 return Molecule (b, at);
145 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
149 for (int i= 4; i -- ;)
151 l = gh_cons (ly_offset2scm (b.control_[i]), l);
154 SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
155 gh_double2scm (thick),
156 gh_double2scm (dash),
160 Box box (Interval(0,0),Interval( 0,0));
161 return Molecule (box, at);
168 Lookup::blank (Box b)
170 return Molecule (b, SCM_EOL);
175 Lookup::filledbox (Box b )
177 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
178 gh_double2scm (-b[X_AXIS][LEFT]),
179 gh_double2scm (b[X_AXIS][RIGHT]),
180 gh_double2scm (-b[Y_AXIS][DOWN]),
181 gh_double2scm (b[Y_AXIS][UP]),
184 return Molecule ( b,at);
188 Lookup::frame (Box b, Real thick)
197 Axis o = Axis ((a+1)%NO_AXES);
200 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
201 edges[o][DOWN] = b[o][DOWN] - thick/2;
202 edges[o][UP] = b[o][UP] + thick/2;
205 m.add_molecule (filledbox (edges));
207 while (flip (&d) != LEFT);
216 Since the user has direct access to TeX marcos,
217 that currently provide the only way to do
218 font selection, accents etc,
219 we try some halfbaked attempt to detect this TeX trickery.
222 sanitise_TeX_string (String text)
225 for (int i= 0; i < text.length_i (); i++)
232 else if (text[i] == '}')
238 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
242 text = to_str ('{', -brace_count) + text;
246 text = text + to_str ('}', brace_count);
257 sanitise_PS_string (String t)
263 TODO: move into Text_item. UGH: paper_l argument shoudl be junked.
266 Lookup::text (String style, String text, Paper_def *paper_l)
268 if (style.empty_b ())
272 Real font_h = paper_l->get_var ("font_normal");
273 if (paper_l->scope_p_->elem_b ("font_" + style))
275 font_h = paper_l->get_var ("font_" + style);
279 if (paper_l->scope_p_->elem_b ("magnification_" + style))
281 font_mag = (int)paper_l->get_var ("magnification_" + style);
284 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
285 scm_eval (ly_symbol2scm ("cmr-alist")));
289 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
292 Font_metric* metric_l = 0;
295 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
297 metric_l = all_fonts_global_p->find_font (style);
302 int i = text.index_i ("\\n");
305 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
306 i = text.index_i ("\\n");
309 Array<String> lines = String_convert::split_arr (text, '\n');
311 Real kern = paper_l->get_var ("line_kern");
313 for (int i=0; i < lines.size (); i++)
315 String str (lines[i]);
316 if (output_global_ch == "tex")
317 str = sanitise_TeX_string (str);
318 else if (output_global_ch == "ps")
319 str = sanitise_PS_string (str);
326 SCM first = gh_list (ly_symbol2scm ("text"),
327 ly_str02scm (lines[0].ch_C()),
329 first = fontify_atom (metric_l, first);
333 Molecule mol (metric_l->text_dimension (lines[0]), first);
335 for (i = 1; i < lines.size (); i++)
337 SCM line = (gh_list (ly_symbol2scm ("text"),
338 ly_str02scm (lines[i].ch_C ()),
340 line = fontify_atom (metric_l, line);
341 mol.add_at_edge (Y_AXIS, DOWN,
342 Molecule (metric_l->text_dimension (lines[i]), line),
352 Make a smooth curve along the points
355 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
357 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
361 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
362 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
367 scontrols[ i ] = ly_offset2scm(back.control_[i]);
369 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
372 Need the weird order b.o. the way PS want its arguments
374 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
376 for (int i= 8; i--; )
378 list = gh_cons (scontrols[indices[i]], list);
382 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
384 gh_double2scm (linethick),
387 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
388 return Molecule (b, at);
392 Lookup::accordion (SCM s, Real staff_space) const
395 String sym = ly_scm2string(gh_car (s));
396 String reg = ly_scm2string(gh_car (gh_cdr(s)));
398 if (sym == "Discant")
400 Molecule r = afm_find("accordion-accDiscant");
402 if (reg.left_str(1) == "F")
404 Molecule d = afm_find("accordion-accDot");
405 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
407 reg = reg.right_str(reg.length_i()-1);
410 if (reg.left_str(3) == "EEE")
413 reg = reg.right_str(reg.length_i()-3);
415 else if (reg.left_str(2) == "EE")
418 reg = reg.right_str(reg.length_i()-2);
420 else if (reg.left_str(2) == "Eh")
423 reg = reg.right_str(reg.length_i()-2);
425 else if (reg.left_str(1) == "E")
428 reg = reg.right_str(reg.length_i()-1);
432 Molecule d = afm_find("accordion-accDot");
433 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
438 Molecule d = afm_find("accordion-accDot");
439 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
440 d.translate_axis(0.8 * staff_space PT, X_AXIS);
445 Molecule d = afm_find("accordion-accDot");
446 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
447 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
450 if (reg.left_str(2) == "SS")
452 Molecule d = afm_find("accordion-accDot");
453 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
454 d.translate_axis(0.4 * staff_space PT, X_AXIS);
456 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
458 reg = reg.right_str(reg.length_i()-2);
460 if (reg.left_str(1) == "S")
462 Molecule d = afm_find("accordion-accDot");
463 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
465 reg = reg.right_str(reg.length_i()-1);
468 else if (sym == "Freebase")
470 Molecule r = afm_find("accordion-accFreebase");
472 if (reg.left_str(1) == "F")
474 Molecule d = afm_find("accordion-accDot");
475 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
477 reg = reg.right_str(reg.length_i()-1);
481 Molecule d = afm_find("accordion-accDot");
482 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
486 else if (sym == "Bayanbase")
488 Molecule r = afm_find("accordion-accBayanbase");
490 if (reg.left_str(1) == "T")
492 Molecule d = afm_find("accordion-accDot");
493 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
495 reg = reg.right_str(reg.length_i()-1);
497 /* include 4' reed just for completeness. You don't want to use this. */
498 if (reg.left_str(1) == "F")
500 Molecule d = afm_find("accordion-accDot");
501 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
503 reg = reg.right_str(reg.length_i()-1);
505 if (reg.left_str(2) == "EE")
507 Molecule d = afm_find("accordion-accDot");
508 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
509 d.translate_axis(0.4 * staff_space PT, X_AXIS);
511 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
513 reg = reg.right_str(reg.length_i()-2);
515 if (reg.left_str(1) == "E")
517 Molecule d = afm_find("accordion-accDot");
518 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
520 reg = reg.right_str(reg.length_i()-1);
523 else if (sym == "Stdbase")
525 Molecule r = afm_find("accordion-accStdbase");
527 if (reg.left_str(1) == "T")
529 Molecule d = afm_find("accordion-accDot");
530 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
532 reg = reg.right_str(reg.length_i()-1);
534 if (reg.left_str(1) == "F")
536 Molecule d = afm_find("accordion-accDot");
537 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
539 reg = reg.right_str(reg.length_i()-1);
541 if (reg.left_str(1) == "M")
543 Molecule d = afm_find("accordion-accDot");
544 d.translate_axis(staff_space * 2 PT, Y_AXIS);
545 d.translate_axis(staff_space PT, X_AXIS);
547 reg = reg.right_str(reg.length_i()-1);
549 if (reg.left_str(1) == "E")
551 Molecule d = afm_find("accordion-accDot");
552 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
554 reg = reg.right_str(reg.length_i()-1);
556 if (reg.left_str(1) == "S")
558 Molecule d = afm_find("accordion-accDot");
559 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
561 reg = reg.right_str(reg.length_i()-1);
564 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
566 else if (sym == "SB")
568 Molecule r = afm_find("accordion-accSB");
571 else if (sym == "BB")
573 Molecule r = afm_find("accordion-accBB");
576 else if (sym == "OldEE")
578 Molecule r = afm_find("accordion-accOldEE");
581 else if (sym == "OldEES")
583 Molecule r = afm_find("accordion-accOldEES");