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 Lookup::text (String style, String text, Paper_def *paper_l)
246 if (style.empty_b ())
250 Real font_h = paper_l->get_var ("font_normal");
251 if (paper_l->scope_p_->elem_b ("font_" + style))
253 font_h = paper_l->get_var ("font_" + style);
257 if (paper_l->scope_p_->elem_b ("magnification_" + style))
259 font_mag = (int)paper_l->get_var ("magnification_" + style);
266 SCM l = scm_assoc (ly_str02scm (style.ch_C()),
267 scm_eval2 (ly_symbol2scm ("cmr-alist"), SCM_EOL));
271 style = ly_scm2string (gh_cdr(l)) +to_str ((int)font_h);
274 Font_metric* metric_l = 0;
277 metric_l = all_fonts_global_p->find_scaled (style, font_mag);
279 metric_l = all_fonts_global_p->find_font (style);
284 int i = text.index_i ("\\n");
287 text = text.left_str (i) + "\n" + text.right_str (text.length_i () - i - 2);
288 i = text.index_i ("\\n");
291 Array<String> lines = String_convert::split_arr (text, '\n');
293 Real kern = paper_l->get_var ("line_kern");
295 for (int i=0; i < lines.size (); i++)
297 String str (lines[i]);
298 if (output_global_ch == "tex")
299 str = sanitise_TeX_string (str);
306 SCM first = gh_list (ly_symbol2scm ("text"),
307 ly_str02scm (lines[0].ch_C()),
309 first = fontify_atom (metric_l, first);
313 Molecule mol (metric_l->text_dimension (lines[0]), first);
315 for (i = 1; i < lines.size (); i++)
317 SCM line = (gh_list (ly_symbol2scm ("text"),
318 ly_str02scm (lines[i].ch_C ()),
320 line = fontify_atom (metric_l, line);
321 mol.add_at_edge (Y_AXIS, DOWN,
322 Molecule (metric_l->text_dimension (lines[i]), line),
332 Make a smooth curve along the points
335 Lookup::slur (Bezier curve, Real curvethick, Real linethick)
337 Real alpha = (curve.control_[3] - curve.control_[0]).arg ();
341 back.control_[1] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
342 back.control_[2] += curvethick * complex_exp (Offset (0, alpha + M_PI/2));
347 scontrols[ i ] = ly_offset2scm(back.control_[i]);
349 scontrols[i+4] = ly_offset2scm (curve.control_[i]);
352 Need the weird order b.o. the way PS want its arguments
354 int indices[]= {5, 6, 7, 4, 1, 2, 3, 0};
356 for (int i= 8; i--; )
358 list = gh_cons (scontrols[indices[i]], list);
362 SCM at = (gh_list (ly_symbol2scm ("bezier-sandwich"),
364 gh_double2scm (linethick),
367 Box b ( curve.extent (X_AXIS), curve.extent (Y_AXIS));
368 return Molecule (b, at);
372 Lookup::accordion (SCM s, Real staff_space) const
375 String sym = ly_scm2string(gh_car (s));
376 String reg = ly_scm2string(gh_car (gh_cdr(s)));
378 if (sym == "Discant")
380 Molecule r = afm_find("accordion-accDiscant");
382 if (reg.left_str(1) == "F")
384 Molecule d = afm_find("accordion-accDot");
385 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
387 reg = reg.right_str(reg.length_i()-1);
390 if (reg.left_str(3) == "EEE")
393 reg = reg.right_str(reg.length_i()-3);
395 else if (reg.left_str(2) == "EE")
398 reg = reg.right_str(reg.length_i()-2);
400 else if (reg.left_str(2) == "Eh")
403 reg = reg.right_str(reg.length_i()-2);
405 else if (reg.left_str(1) == "E")
408 reg = reg.right_str(reg.length_i()-1);
412 Molecule d = afm_find("accordion-accDot");
413 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
418 Molecule d = afm_find("accordion-accDot");
419 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
420 d.translate_axis(0.8 * staff_space PT, X_AXIS);
425 Molecule d = afm_find("accordion-accDot");
426 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
427 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
430 if (reg.left_str(2) == "SS")
432 Molecule d = afm_find("accordion-accDot");
433 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
434 d.translate_axis(0.4 * staff_space PT, X_AXIS);
436 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
438 reg = reg.right_str(reg.length_i()-2);
440 if (reg.left_str(1) == "S")
442 Molecule d = afm_find("accordion-accDot");
443 d.translate_axis(0.5 * staff_space PT, Y_AXIS);
445 reg = reg.right_str(reg.length_i()-1);
448 else if (sym == "Freebase")
450 Molecule r = afm_find("accordion-accFreebase");
452 if (reg.left_str(1) == "F")
454 Molecule d = afm_find("accordion-accDot");
455 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
457 reg = reg.right_str(reg.length_i()-1);
461 Molecule d = afm_find("accordion-accDot");
462 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
466 else if (sym == "Bayanbase")
468 Molecule r = afm_find("accordion-accBayanbase");
470 if (reg.left_str(1) == "T")
472 Molecule d = afm_find("accordion-accDot");
473 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
475 reg = reg.right_str(reg.length_i()-1);
477 /* include 4' reed just for completeness. You don't want to use this. */
478 if (reg.left_str(1) == "F")
480 Molecule d = afm_find("accordion-accDot");
481 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
483 reg = reg.right_str(reg.length_i()-1);
485 if (reg.left_str(2) == "EE")
487 Molecule d = afm_find("accordion-accDot");
488 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
489 d.translate_axis(0.4 * staff_space PT, X_AXIS);
491 d.translate_axis(-0.8 * staff_space PT, X_AXIS);
493 reg = reg.right_str(reg.length_i()-2);
495 if (reg.left_str(1) == "E")
497 Molecule d = afm_find("accordion-accDot");
498 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
500 reg = reg.right_str(reg.length_i()-1);
503 else if (sym == "Stdbase")
505 Molecule r = afm_find("accordion-accStdbase");
507 if (reg.left_str(1) == "T")
509 Molecule d = afm_find("accordion-accDot");
510 d.translate_axis(staff_space * 3.5 PT, Y_AXIS);
512 reg = reg.right_str(reg.length_i()-1);
514 if (reg.left_str(1) == "F")
516 Molecule d = afm_find("accordion-accDot");
517 d.translate_axis(staff_space * 2.5 PT, Y_AXIS);
519 reg = reg.right_str(reg.length_i()-1);
521 if (reg.left_str(1) == "M")
523 Molecule d = afm_find("accordion-accDot");
524 d.translate_axis(staff_space * 2 PT, Y_AXIS);
525 d.translate_axis(staff_space PT, X_AXIS);
527 reg = reg.right_str(reg.length_i()-1);
529 if (reg.left_str(1) == "E")
531 Molecule d = afm_find("accordion-accDot");
532 d.translate_axis(staff_space * 1.5 PT, Y_AXIS);
534 reg = reg.right_str(reg.length_i()-1);
536 if (reg.left_str(1) == "S")
538 Molecule d = afm_find("accordion-accDot");
539 d.translate_axis(staff_space * 0.5 PT, Y_AXIS);
541 reg = reg.right_str(reg.length_i()-1);
544 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
546 else if (sym == "SB")
548 Molecule r = afm_find("accordion-accSB");
551 else if (sym == "BB")
553 Molecule r = afm_find("accordion-accBB");
556 else if (sym == "OldEE")
558 Molecule r = afm_find("accordion-accOldEE");
561 else if (sym == "OldEES")
563 Molecule r = afm_find("accordion-accOldEES");