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"
39 Lookup::Lookup (Lookup const& s)
41 font_name_ = s.font_name_;
46 Lookup::mark_smob (SCM s)
52 Lookup::print_smob (SCM s, SCM p, scm_print_state*)
54 scm_puts ("#<Lookup >#", p);
59 IMPLEMENT_UNSMOB(Lookup, lookup);
60 IMPLEMENT_SIMPLE_SMOBS(Lookup);
61 IMPLEMENT_DEFAULT_EQUAL_P(Lookup);
64 Lookup::make_lookup ()
66 Lookup * l = new Lookup;
67 return l->smobbed_self();
72 Lookup::afm_find (String s, bool warn) const
76 Lookup * me = (Lookup*)(this);
77 me->afm_l_ = all_fonts_global_p->find_afm (font_name_);
80 warning (_f ("can't find font: `%s'", font_name_));
81 warning (_f ("(search path: `%s')", global_path.str ().ch_C()));
82 error (_ ("Aborting"));
85 AFM_CharMetricInfo const *cm = afm_l_->find_char_metric (s, warn);
94 SCM at = (gh_list (ly_symbol2scm ("char"),
95 gh_int2scm (cm->code),
99 at= fontify_atom (afm_l_,at);
100 return Molecule ( afm_bbox_to_box (cm->charBBox), at);
107 Lookup::beam (Real slope, Real width, Real thick)
109 Real height = slope * width;
110 Real min_y = (0 <? height) - thick/2;
111 Real max_y = (0 >? height) + thick/2;
115 Box b( Interval (0, width),
116 Interval (min_y, max_y));
119 SCM at = gh_list (ly_symbol2scm ("beam"),
120 gh_double2scm (width),
121 gh_double2scm (slope),
122 gh_double2scm (thick),
124 return Molecule (b, at);
130 Lookup::dashed_slur (Bezier b, Real thick, Real dash)
134 for (int i= 4; i -- ;)
136 l = gh_cons (ly_offset2scm (b.control_[i]), l);
139 SCM at = (gh_list (ly_symbol2scm ("dashed-slur"),
140 gh_double2scm (thick),
141 gh_double2scm (dash),
145 Box box (Interval(0,0),Interval( 0,0));
146 return Molecule (box, at);
153 Lookup::blank (Box b)
155 return Molecule (b, SCM_EOL);
160 Lookup::filledbox (Box b )
162 SCM at = (gh_list (ly_symbol2scm ("filledbox"),
163 gh_double2scm (-b[X_AXIS][LEFT]),
164 gh_double2scm (b[X_AXIS][RIGHT]),
165 gh_double2scm (-b[Y_AXIS][DOWN]),
166 gh_double2scm (b[Y_AXIS][UP]),
169 return Molecule ( b,at);
173 Lookup::frame (Box b, Real thick)
182 Axis o = Axis ((a+1)%NO_AXES);
185 edges[a] = b[a][d] + 0.5 * thick * Interval (-1, 1);
186 edges[o][DOWN] = b[o][DOWN] - thick/2;
187 edges[o][UP] = b[o][UP] + thick/2;
190 m.add_molecule (filledbox (edges));
192 while (flip (&d) != LEFT);
203 Since the user has direct access to TeX marcos,
204 that currently provide the only way to do
205 font selection, accents etc,
206 we try some halfbaked attempt to detect this TeX trickery.
209 sanitise_TeX_string (String text)
212 for (int i= 0; i < text.length_i (); i++)
219 else if (text[i] == '}')
225 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
229 text = to_str ('{', -brace_count) + text;
233 text = text + to_str ('}', brace_count);
244 sanitise_PS_string (String t)
253 Lookup::text (String style, String text, Paper_def *paper_l)
255 if (style.empty_b ())
259 Real font_h = paper_l->get_var ("font_normal");
260 if (paper_l->scope_p_->elem_b ("font_" + style))
262 font_h = paper_l->get_var ("font_" + style);
266 if (paper_l->scope_p_->elem_b ("magnification_" + style))
268 font_mag = (int)paper_l->get_var ("magnification_" + style);
275 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
276 scm_eval2 (ly_symbol2scm ("cmr-alist"), SCM_EOL));
280 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
283 Font_metric* metric_l = 0;
286 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
288 metric_l = all_fonts_global_p->find_font (style);
293 int i = text.index_i ("\\n");
296 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
297 i = text.index_i ("\\n");
300 Array<String> lines = String_convert::split_arr (text, '\n');
302 Real kern = paper_l->get_var ("line_kern");
304 for (int i=0; i < lines.size (); i++)
306 String str (lines[i]);
307 if (output_global_ch == "tex")
308 str = sanitise_TeX_string (str);
309 else if (output_global_ch == "ps")
310 str = sanitise_PS_string (str);
317 SCM first = gh_list (ly_symbol2scm ("text"),
318 ly_str02scm (lines[0].ch_C()),
320 first = fontify_atom (metric_l, first);
324 Molecule mol (metric_l->text_dimension (lines[0]), first);
326 for (i = 1; i < lines.size (); i++)
328 SCM line = (gh_list (ly_symbol2scm ("text"),
329 ly_str02scm (lines[i].ch_C ()),
331 line = fontify_atom (metric_l, line);
332 mol.add_at_edge (Y_AXIS, DOWN,
333 Molecule (metric_l->text_dimension (lines[i]), line),
343 Make a smooth curve along the points
346 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
348 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
352 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
353 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
358 scontrols[ i ] = ly_offset2scm(back.control_[i]);
360 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
363 Need the weird order b.o. the way PS want its arguments
365 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
367 for (int i= 8; i--; )
369 list = gh_cons (scontrols[indices[i]], list);
373 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
375 gh_double2scm (linethick),
378 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
379 return Molecule (b, at);
383 Lookup::accordion (SCM s, Real staff_space) const
386 String sym = ly_scm2string(gh_car (s));
387 String reg = ly_scm2string(gh_car (gh_cdr(s)));
389 if (sym == "Discant")
391 Molecule r = afm_find("accordion-accDiscant");
393 if (reg.left_str(1) == "F")
395 Molecule d = afm_find("accordion-accDot");
396 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
398 reg = reg.right_str(reg.length_i()-1);
401 if (reg.left_str(3) == "EEE")
404 reg = reg.right_str(reg.length_i()-3);
406 else if (reg.left_str(2) == "EE")
409 reg = reg.right_str(reg.length_i()-2);
411 else if (reg.left_str(2) == "Eh")
414 reg = reg.right_str(reg.length_i()-2);
416 else if (reg.left_str(1) == "E")
419 reg = reg.right_str(reg.length_i()-1);
423 Molecule d = afm_find("accordion-accDot");
424 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
429 Molecule d = afm_find("accordion-accDot");
430 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
431 d.translate_axis(0.8 * staff_space PT, X_AXIS);
436 Molecule d = afm_find("accordion-accDot");
437 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
438 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
441 if (reg.left_str(2) == "SS")
443 Molecule d = afm_find("accordion-accDot");
444 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
445 d.translate_axis(0.4 * staff_space PT, X_AXIS);
447 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
449 reg = reg.right_str(reg.length_i()-2);
451 if (reg.left_str(1) == "S")
453 Molecule d = afm_find("accordion-accDot");
454 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
456 reg = reg.right_str(reg.length_i()-1);
459 else if (sym == "Freebase")
461 Molecule r = afm_find("accordion-accFreebase");
463 if (reg.left_str(1) == "F")
465 Molecule d = afm_find("accordion-accDot");
466 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
468 reg = reg.right_str(reg.length_i()-1);
472 Molecule d = afm_find("accordion-accDot");
473 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
477 else if (sym == "Bayanbase")
479 Molecule r = afm_find("accordion-accBayanbase");
481 if (reg.left_str(1) == "T")
483 Molecule d = afm_find("accordion-accDot");
484 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
486 reg = reg.right_str(reg.length_i()-1);
488 /* include 4' reed just for completeness. You don't want to use this. */
489 if (reg.left_str(1) == "F")
491 Molecule d = afm_find("accordion-accDot");
492 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
494 reg = reg.right_str(reg.length_i()-1);
496 if (reg.left_str(2) == "EE")
498 Molecule d = afm_find("accordion-accDot");
499 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
500 d.translate_axis(0.4 * staff_space PT, X_AXIS);
502 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
504 reg = reg.right_str(reg.length_i()-2);
506 if (reg.left_str(1) == "E")
508 Molecule d = afm_find("accordion-accDot");
509 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
511 reg = reg.right_str(reg.length_i()-1);
514 else if (sym == "Stdbase")
516 Molecule r = afm_find("accordion-accStdbase");
518 if (reg.left_str(1) == "T")
520 Molecule d = afm_find("accordion-accDot");
521 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
523 reg = reg.right_str(reg.length_i()-1);
525 if (reg.left_str(1) == "F")
527 Molecule d = afm_find("accordion-accDot");
528 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
530 reg = reg.right_str(reg.length_i()-1);
532 if (reg.left_str(1) == "M")
534 Molecule d = afm_find("accordion-accDot");
535 d.translate_axis(staff_space * 2 PT, Y_AXIS);
536 d.translate_axis(staff_space PT, X_AXIS);
538 reg = reg.right_str(reg.length_i()-1);
540 if (reg.left_str(1) == "E")
542 Molecule d = afm_find("accordion-accDot");
543 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
545 reg = reg.right_str(reg.length_i()-1);
547 if (reg.left_str(1) == "S")
549 Molecule d = afm_find("accordion-accDot");
550 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
552 reg = reg.right_str(reg.length_i()-1);
555 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
557 else if (sym == "SB")
559 Molecule r = afm_find("accordion-accSB");
562 else if (sym == "BB")
564 Molecule r = afm_find("accordion-accBB");
567 else if (sym == "OldEE")
569 Molecule r = afm_find("accordion-accOldEE");
572 else if (sym == "OldEES")
574 Molecule r = afm_find("accordion-accOldEES");