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);
273 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
274 scm_eval2 (ly_symbol2scm ("cmr-alist"), SCM_EOL));
278 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
281 Font_metric* metric_l = 0;
284 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
286 metric_l = all_fonts_global_p->find_font (style);
291 int i = text.index_i ("\\n");
294 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
295 i = text.index_i ("\\n");
298 Array<String> lines = String_convert::split_arr (text, '\n');
300 Real kern = paper_l->get_var ("line_kern");
302 for (int i=0; i < lines.size (); i++)
304 String str (lines[i]);
305 if (output_global_ch == "tex")
306 str = sanitise_TeX_string (str);
307 else if (output_global_ch == "ps")
308 str = sanitise_PS_string (str);
315 SCM first = gh_list (ly_symbol2scm ("text"),
316 ly_str02scm (lines[0].ch_C()),
318 first = fontify_atom (metric_l, first);
322 Molecule mol (metric_l->text_dimension (lines[0]), first);
324 for (i = 1; i < lines.size (); i++)
326 SCM line = (gh_list (ly_symbol2scm ("text"),
327 ly_str02scm (lines[i].ch_C ()),
329 line = fontify_atom (metric_l, line);
330 mol.add_at_edge (Y_AXIS, DOWN,
331 Molecule (metric_l->text_dimension (lines[i]), line),
341 Make a smooth curve along the points
344 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
346 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
350 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
351 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
356 scontrols[ i ] = ly_offset2scm(back.control_[i]);
358 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
361 Need the weird order b.o. the way PS want its arguments
363 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
365 for (int i= 8; i--; )
367 list = gh_cons (scontrols[indices[i]], list);
371 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
373 gh_double2scm (linethick),
376 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
377 return Molecule (b, at);
381 Lookup::accordion (SCM s, Real staff_space) const
384 String sym = ly_scm2string(gh_car (s));
385 String reg = ly_scm2string(gh_car (gh_cdr(s)));
387 if (sym == "Discant")
389 Molecule r = afm_find("accordion-accDiscant");
391 if (reg.left_str(1) == "F")
393 Molecule d = afm_find("accordion-accDot");
394 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
396 reg = reg.right_str(reg.length_i()-1);
399 if (reg.left_str(3) == "EEE")
402 reg = reg.right_str(reg.length_i()-3);
404 else if (reg.left_str(2) == "EE")
407 reg = reg.right_str(reg.length_i()-2);
409 else if (reg.left_str(2) == "Eh")
412 reg = reg.right_str(reg.length_i()-2);
414 else if (reg.left_str(1) == "E")
417 reg = reg.right_str(reg.length_i()-1);
421 Molecule d = afm_find("accordion-accDot");
422 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
427 Molecule d = afm_find("accordion-accDot");
428 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
429 d.translate_axis(0.8 * staff_space PT, X_AXIS);
434 Molecule d = afm_find("accordion-accDot");
435 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
436 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
439 if (reg.left_str(2) == "SS")
441 Molecule d = afm_find("accordion-accDot");
442 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
443 d.translate_axis(0.4 * staff_space PT, X_AXIS);
445 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
447 reg = reg.right_str(reg.length_i()-2);
449 if (reg.left_str(1) == "S")
451 Molecule d = afm_find("accordion-accDot");
452 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
454 reg = reg.right_str(reg.length_i()-1);
457 else if (sym == "Freebase")
459 Molecule r = afm_find("accordion-accFreebase");
461 if (reg.left_str(1) == "F")
463 Molecule d = afm_find("accordion-accDot");
464 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
466 reg = reg.right_str(reg.length_i()-1);
470 Molecule d = afm_find("accordion-accDot");
471 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
475 else if (sym == "Bayanbase")
477 Molecule r = afm_find("accordion-accBayanbase");
479 if (reg.left_str(1) == "T")
481 Molecule d = afm_find("accordion-accDot");
482 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
484 reg = reg.right_str(reg.length_i()-1);
486 /* include 4' reed just for completeness. You don't want to use this. */
487 if (reg.left_str(1) == "F")
489 Molecule d = afm_find("accordion-accDot");
490 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
492 reg = reg.right_str(reg.length_i()-1);
494 if (reg.left_str(2) == "EE")
496 Molecule d = afm_find("accordion-accDot");
497 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
498 d.translate_axis(0.4 * staff_space PT, X_AXIS);
500 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
502 reg = reg.right_str(reg.length_i()-2);
504 if (reg.left_str(1) == "E")
506 Molecule d = afm_find("accordion-accDot");
507 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
509 reg = reg.right_str(reg.length_i()-1);
512 else if (sym == "Stdbase")
514 Molecule r = afm_find("accordion-accStdbase");
516 if (reg.left_str(1) == "T")
518 Molecule d = afm_find("accordion-accDot");
519 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
521 reg = reg.right_str(reg.length_i()-1);
523 if (reg.left_str(1) == "F")
525 Molecule d = afm_find("accordion-accDot");
526 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
528 reg = reg.right_str(reg.length_i()-1);
530 if (reg.left_str(1) == "M")
532 Molecule d = afm_find("accordion-accDot");
533 d.translate_axis(staff_space * 2 PT, Y_AXIS);
534 d.translate_axis(staff_space PT, X_AXIS);
536 reg = reg.right_str(reg.length_i()-1);
538 if (reg.left_str(1) == "E")
540 Molecule d = afm_find("accordion-accDot");
541 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
543 reg = reg.right_str(reg.length_i()-1);
545 if (reg.left_str(1) == "S")
547 Molecule d = afm_find("accordion-accDot");
548 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
550 reg = reg.right_str(reg.length_i()-1);
553 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
555 else if (sym == "SB")
557 Molecule r = afm_find("accordion-accSB");
560 else if (sym == "BB")
562 Molecule r = afm_find("accordion-accBB");
565 else if (sym == "OldEE")
567 Molecule r = afm_find("accordion-accOldEE");
570 else if (sym == "OldEES")
572 Molecule r = afm_find("accordion-accOldEES");