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);
201 Since the user has direct access to TeX marcos,
202 that currently provide the only way to do
203 font selection, accents etc,
204 we try some halfbaked attempt to detect this TeX trickery.
207 sanitise_TeX_string (String text)
210 for (int i= 0; i < text.length_i (); i++)
217 else if (text[i] == '}')
223 warning (_f ("Non-matching braces in text `%s', adding braces", text.ch_C()));
227 text = to_str ('{', -brace_count) + text;
231 text = text + to_str ('}', brace_count);
242 sanitise_PS_string (String t)
248 TODO: move into Text_item. UGH: paper_l argument shoudl be junked.
251 Lookup::text (String style, String text, Paper_def *paper_l)
253 if (style.empty_b ())
257 Real font_h = paper_l->get_var ("font_normal");
258 if (paper_l->scope_p_->elem_b ("font_" + style))
260 font_h = paper_l->get_var ("font_" + style);
264 if (paper_l->scope_p_->elem_b ("magnification_" + style))
266 font_mag = (int)paper_l->get_var ("magnification_" + style);
269 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
270 scm_eval2 (ly_symbol2scm ("cmr-alist"), SCM_EOL));
274 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
277 Font_metric* metric_l = 0;
280 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
282 metric_l = all_fonts_global_p->find_font (style);
287 int i = text.index_i ("\\n");
290 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
291 i = text.index_i ("\\n");
294 Array<String> lines = String_convert::split_arr (text, '\n');
296 Real kern = paper_l->get_var ("line_kern");
298 for (int i=0; i < lines.size (); i++)
300 String str (lines[i]);
301 if (output_global_ch == "tex")
302 str = sanitise_TeX_string (str);
303 else if (output_global_ch == "ps")
304 str = sanitise_PS_string (str);
311 SCM first = gh_list (ly_symbol2scm ("text"),
312 ly_str02scm (lines[0].ch_C()),
314 first = fontify_atom (metric_l, first);
318 Molecule mol (metric_l->text_dimension (lines[0]), first);
320 for (i = 1; i < lines.size (); i++)
322 SCM line = (gh_list (ly_symbol2scm ("text"),
323 ly_str02scm (lines[i].ch_C ()),
325 line = fontify_atom (metric_l, line);
326 mol.add_at_edge (Y_AXIS, DOWN,
327 Molecule (metric_l->text_dimension (lines[i]), line),
337 Make a smooth curve along the points
340 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
342 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
346 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
347 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
352 scontrols[ i ] = ly_offset2scm(back.control_[i]);
354 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
357 Need the weird order b.o. the way PS want its arguments
359 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
361 for (int i= 8; i--; )
363 list = gh_cons (scontrols[indices[i]], list);
367 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
369 gh_double2scm (linethick),
372 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
373 return Molecule (b, at);
377 Lookup::accordion (SCM s, Real staff_space) const
380 String sym = ly_scm2string(gh_car (s));
381 String reg = ly_scm2string(gh_car (gh_cdr(s)));
383 if (sym == "Discant")
385 Molecule r = afm_find("accordion-accDiscant");
387 if (reg.left_str(1) == "F")
389 Molecule d = afm_find("accordion-accDot");
390 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
392 reg = reg.right_str(reg.length_i()-1);
395 if (reg.left_str(3) == "EEE")
398 reg = reg.right_str(reg.length_i()-3);
400 else if (reg.left_str(2) == "EE")
403 reg = reg.right_str(reg.length_i()-2);
405 else if (reg.left_str(2) == "Eh")
408 reg = reg.right_str(reg.length_i()-2);
410 else if (reg.left_str(1) == "E")
413 reg = reg.right_str(reg.length_i()-1);
417 Molecule d = afm_find("accordion-accDot");
418 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
423 Molecule d = afm_find("accordion-accDot");
424 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
425 d.translate_axis(0.8 * staff_space PT, X_AXIS);
430 Molecule d = afm_find("accordion-accDot");
431 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
432 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
435 if (reg.left_str(2) == "SS")
437 Molecule d = afm_find("accordion-accDot");
438 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
439 d.translate_axis(0.4 * staff_space PT, X_AXIS);
441 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
443 reg = reg.right_str(reg.length_i()-2);
445 if (reg.left_str(1) == "S")
447 Molecule d = afm_find("accordion-accDot");
448 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
450 reg = reg.right_str(reg.length_i()-1);
453 else if (sym == "Freebase")
455 Molecule r = afm_find("accordion-accFreebase");
457 if (reg.left_str(1) == "F")
459 Molecule d = afm_find("accordion-accDot");
460 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
462 reg = reg.right_str(reg.length_i()-1);
466 Molecule d = afm_find("accordion-accDot");
467 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
471 else if (sym == "Bayanbase")
473 Molecule r = afm_find("accordion-accBayanbase");
475 if (reg.left_str(1) == "T")
477 Molecule d = afm_find("accordion-accDot");
478 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
480 reg = reg.right_str(reg.length_i()-1);
482 /* include 4' reed just for completeness. You don't want to use this. */
483 if (reg.left_str(1) == "F")
485 Molecule d = afm_find("accordion-accDot");
486 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
488 reg = reg.right_str(reg.length_i()-1);
490 if (reg.left_str(2) == "EE")
492 Molecule d = afm_find("accordion-accDot");
493 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
494 d.translate_axis(0.4 * staff_space PT, X_AXIS);
496 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
498 reg = reg.right_str(reg.length_i()-2);
500 if (reg.left_str(1) == "E")
502 Molecule d = afm_find("accordion-accDot");
503 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
505 reg = reg.right_str(reg.length_i()-1);
508 else if (sym == "Stdbase")
510 Molecule r = afm_find("accordion-accStdbase");
512 if (reg.left_str(1) == "T")
514 Molecule d = afm_find("accordion-accDot");
515 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
517 reg = reg.right_str(reg.length_i()-1);
519 if (reg.left_str(1) == "F")
521 Molecule d = afm_find("accordion-accDot");
522 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
524 reg = reg.right_str(reg.length_i()-1);
526 if (reg.left_str(1) == "M")
528 Molecule d = afm_find("accordion-accDot");
529 d.translate_axis(staff_space * 2 PT, Y_AXIS);
530 d.translate_axis(staff_space PT, X_AXIS);
532 reg = reg.right_str(reg.length_i()-1);
534 if (reg.left_str(1) == "E")
536 Molecule d = afm_find("accordion-accDot");
537 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
539 reg = reg.right_str(reg.length_i()-1);
541 if (reg.left_str(1) == "S")
543 Molecule d = afm_find("accordion-accDot");
544 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
546 reg = reg.right_str(reg.length_i()-1);
549 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
551 else if (sym == "SB")
553 Molecule r = afm_find("accordion-accSB");
556 else if (sym == "BB")
558 Molecule r = afm_find("accordion-accBB");
561 else if (sym == "OldEE")
563 Molecule r = afm_find("accordion-accOldEE");
566 else if (sym == "OldEES")
568 Molecule r = afm_find("accordion-accOldEES");