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>
17 #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"
30 #include "lily-guile.hh"
38 Lookup::Lookup (Lookup
const& s
)
40 font_name_
= s
.font_name_
;
48 Lookup::afm_find (String s
, bool warn
) const
52 Lookup
* me
= (Lookup
*)(this);
53 me
->afm_l_
= all_fonts_global_p
->find_afm (font_name_
);
56 warning (_f ("Can't find font: `%s'", font_name_
));
57 warning (_f ("(search path `%s')", global_path
.str ().ch_C()));
58 error (_ ("Aborting"));
61 AFM_CharMetricInfo
const *cm
= afm_l_
->find_char_metric (s
, warn
);
69 SCM at
= (gh_list (ly_symbol2scm ("char"),
70 gh_int2scm (cm
->code
),
73 at
= fontify_atom (afm_l_
,at
);
74 m
.dim_
= afm_bbox_to_box (cm
->charBBox
);
80 Lookup::simple_bar (String type
, Real h
, Paper_def
* paper_l
) const
82 SCM thick
= ly_symbol2scm (("barthick_" + type
).ch_C());
85 if (paper_l
->scope_p_
->elem_b (thick
))
87 w
= paper_l
->get_realvar (thick
);
91 programming_error ("No bar thickness set ! ");
94 return filledbox (Box (Interval(0,w
), Interval(-h
/2, h
/2)));
99 Lookup::bar (String str
, Real h
, Paper_def
*paper_l
) const
101 if (str
== "bracket")
102 return staff_bracket (h
, paper_l
);
103 else if (str
== "brace")
105 Real staffht
= paper_l
->get_var ("staffheight");
106 return staff_brace (h
,staffht
);
108 Real kern
= paper_l
->get_var ("bar_kern");
109 Real thinkern
= paper_l
->get_var ("bar_thinkern");
111 Molecule thin
= simple_bar ("thin", h
, paper_l
);
112 Molecule thick
= simple_bar ("thick", h
, paper_l
);
113 Molecule colon
= afm_find ("dots-repeatcolon", paper_l
);
119 return fill (Box (Interval(0, 0), Interval (-h
/2, h
/2)));
121 if (str
== "scorepostbreak")
123 return simple_bar ("score", h
, paper_l
);
129 else if (str
== "|.")
131 m
.add_at_edge (X_AXIS
, LEFT
, thick
, 0);
132 m
.add_at_edge (X_AXIS
, LEFT
, thin
, kern
);
134 else if (str
== ".|")
136 m
.add_at_edge (X_AXIS
, RIGHT
, thick
, 0);
137 m
.add_at_edge (X_AXIS
, RIGHT
, thin
, kern
);
139 else if (str
== ":|")
141 m
.add_at_edge (X_AXIS
, LEFT
, thick
, 0);
142 m
.add_at_edge (X_AXIS
, LEFT
, thin
, kern
);
143 m
.add_at_edge (X_AXIS
, LEFT
, colon
, kern
);
145 else if (str
== "|:")
147 m
.add_at_edge (X_AXIS
, RIGHT
, thick
, 0);
148 m
.add_at_edge (X_AXIS
, RIGHT
, thin
, kern
);
149 m
.add_at_edge (X_AXIS
, RIGHT
, colon
, kern
);
151 else if (str
== ":|:")
153 m
.add_at_edge (X_AXIS
, LEFT
, thick
, thinkern
);
154 m
.add_at_edge (X_AXIS
, LEFT
, colon
, kern
);
155 m
.add_at_edge (X_AXIS
, RIGHT
, thick
, kern
);
156 m
.add_at_edge (X_AXIS
, RIGHT
, colon
, kern
);
158 else if (str
== ".|.")
160 m
.add_at_edge (X_AXIS
, LEFT
, thick
, thinkern
);
161 m
.add_at_edge (X_AXIS
, RIGHT
, thick
, kern
);
163 else if (str
== "||")
165 m
.add_at_edge (X_AXIS
, RIGHT
, thin
, 0);
166 m
.add_at_edge (X_AXIS
, RIGHT
, thin
, thinkern
);
173 Lookup::beam (Real slope
, Real width
, Real thick
)
175 Real height
= slope
* width
;
176 Real min_y
= (0 <? height
) - thick
/2;
177 Real max_y
= (0 >? height
) + thick
/2;
181 m
.dim_
[X_AXIS
] = Interval (0, width
);
182 m
.dim_
[Y_AXIS
] = Interval (min_y
, max_y
);
185 SCM at
= (gh_list (ly_symbol2scm ("beam"),
186 gh_double2scm (width
),
187 gh_double2scm (slope
),
188 gh_double2scm (thick
),
198 Lookup::dashed_slur (Bezier b
, Real thick
, Real dash
)
201 for (int i
= 4; i
-- ;)
203 l
= gh_cons (ly_offset2scm (b
.control_
[i
]), l
);
206 SCM at
= (gh_list (ly_symbol2scm ("dashed-slur"),
207 gh_double2scm (thick
),
208 gh_double2scm (dash
),
229 Lookup::filledbox (Box b
)
233 SCM at
= (gh_list (ly_symbol2scm ("filledbox"),
234 gh_double2scm (-b
[X_AXIS
][LEFT
]),
235 gh_double2scm (b
[X_AXIS
][RIGHT
]),
236 gh_double2scm (-b
[Y_AXIS
][DOWN
]),
237 gh_double2scm (b
[Y_AXIS
][UP
]),
246 Lookup::frame (Box b
, Real thick
)
255 Axis o
= Axis ((a
+1)%NO_AXES
);
258 edges
[a
] = b
[a
][d
] + 0.5 * thick
* Interval (-1, 1);
259 edges
[o
][DOWN
] = b
[o
][DOWN
] - thick
/2;
260 edges
[o
][UP
] = b
[o
][UP
] + thick
/2;
263 m
.add_molecule (filledbox (edges
));
265 while (flip (&d
) != LEFT
);
273 TODO: THIS IS UGLY. Since the user has direct access to TeX
274 strings, we try some halfbaked attempt to detect TeX trickery.
277 sanitise_TeX_string (String text
)
280 for (int i
= 0; i
< text
.length_i (); i
++)
287 else if (text
[i
] == '}')
293 warning (_f ("Non-matching braces in text `%s', adding braces", text
.ch_C()));
297 text
= to_str ('{', -brace_count
) + text
;
301 text
= text
+ to_str ('}', brace_count
);
312 sanitise_PS_string (String t
)
321 Lookup::text (String style
, String text
, Paper_def
*paper_l
)
324 if (style
.empty_b ())
328 Real font_h
= paper_l
->get_var ("font_normal");
329 if (paper_l
->scope_p_
->elem_b ("font_" + style
))
331 font_h
= paper_l
->get_var ("font_" + style
);
335 if (paper_l
->scope_p_
->elem_b ("magnification_" + style
))
337 font_mag
= (int)paper_l
->get_var ("magnification_" + style
);
343 SCM l
= ly_eval_str (("(style-to-cmr \"" + style
+ "\")").ch_C());
346 style
= ly_scm2string (gh_cdr(l
)) +to_str ((int)font_h
);
351 Font_metric
* metric_l
= 0;
354 metric_l
= all_fonts_global_p
->find_scaled (style
, font_mag
);
356 metric_l
= all_fonts_global_p
->find_font (style
);
359 if (output_global_ch
== "tex")
360 text
= sanitise_TeX_string (text
);
361 else if (output_global_ch
== "ps")
362 text
= sanitise_PS_string (text
);
364 m
.dim_
= metric_l
->text_dimension (text
);
366 SCM at
= (gh_list (ly_symbol2scm ("text"),
367 ly_str02scm (text
.ch_C()),
369 at
= fontify_atom (metric_l
,at
);
378 Lookup::staff_brace (Real y
, int staff_size
)
384 int minht
= 2 * staff_size
;
385 int maxht
= 7 * minht
;
386 int idx
= int (((maxht
- step
) <? y
- minht
) / step
);
389 SCM l
= ly_eval_str ("(style-to-cmr \"brace\")");
390 String nm
= "feta-braces";
392 nm
= ly_scm2string (gh_cdr (l
));
393 nm
+= to_str (staff_size
);
394 SCM e
=gh_list (ly_symbol2scm ("char"), gh_int2scm (idx
), SCM_UNDEFINED
);
397 at
= fontify_atom (all_fonts_global_p
->find_font (nm
), at
);
399 m
.dim_
[Y_AXIS
] = Interval (-y
/2,y
/2);
400 m
.dim_
[X_AXIS
] = Interval (0,0);
407 Make a smooth curve along the points
410 Lookup::slur (Bezier curve
, Real curvethick
, Real linethick
)
412 Real alpha
= (curve
.control_
[3] - curve
.control_
[0]).arg ();
416 back
.control_
[1] += curvethick
* complex_exp (Offset (0, alpha
+ M_PI
/2));
417 back
.control_
[2] += curvethick
* complex_exp (Offset (0, alpha
+ M_PI
/2));
421 scontrols
[ i
] = ly_offset2scm (back
.control_
[i
]);
423 scontrols
[i
+4] = ly_offset2scm (curve
.control_
[i
]);
426 Need the weird order b.o. the way PS want its arguments
428 int indices
[]= {5, 6, 7, 4, 1, 2, 3, 0};
430 for (int i
= 8; i
--; )
432 list
= gh_cons (scontrols
[indices
[i
]], list
);
436 SCM at
= (gh_list (ly_symbol2scm ("bezier-sandwich"),
438 gh_double2scm (linethick
),
442 m
.dim_
[X_AXIS
] = curve
.extent (X_AXIS
);
443 m
.dim_
[Y_AXIS
] = curve
.extent (Y_AXIS
);
449 Lookup::staff_bracket (Real height
, Paper_def
* paper_l
)
452 SCM at
= ( gh_list (ly_symbol2scm ("bracket"),
453 gh_double2scm (paper_l
->get_var("bracket_arch_angle")),
454 gh_double2scm (paper_l
->get_var("bracket_arch_width")),
455 gh_double2scm (paper_l
->get_var("bracket_arch_height")),
456 gh_double2scm (paper_l
->get_var("bracket_width")),
457 gh_double2scm (height
),
458 gh_double2scm (paper_l
->get_var("bracket_arch_thick")),
459 gh_double2scm (paper_l
->get_var("bracket_thick")),
463 m
.dim_
[Y_AXIS
] = Interval (-height
/2,height
/2);
464 m
.dim_
[X_AXIS
] = Interval (0,4 PT
);
466 m
.translate_axis (- 4. / 3. * m
.dim_
[X_AXIS
].length (), X_AXIS
);
472 Lookup::accordion (SCM s
, Real staff_space
) const
475 String sym
= ly_scm2string(gh_car (s
));
476 String reg
= ly_scm2string(gh_car (gh_cdr(s
)));
478 if (sym
== "Discant")
480 Molecule r
= afm_find("scripts-accDiscant");
482 if (reg
.left_str(1) == "F")
484 Molecule d
= afm_find("scripts-accDot");
485 d
.translate_axis(staff_space
* 2.5 PT
, Y_AXIS
);
487 reg
= reg
.right_str(reg
.length_i()-1);
490 if (reg
.left_str(3) == "EEE")
493 reg
= reg
.right_str(reg
.length_i()-3);
495 else if (reg
.left_str(2) == "EE")
498 reg
= reg
.right_str(reg
.length_i()-2);
500 else if (reg
.left_str(2) == "Eh")
503 reg
= reg
.right_str(reg
.length_i()-2);
505 else if (reg
.left_str(1) == "E")
508 reg
= reg
.right_str(reg
.length_i()-1);
512 Molecule d
= afm_find("scripts-accDot");
513 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
518 Molecule d
= afm_find("scripts-accDot");
519 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
520 d
.translate_axis(0.8 * staff_space PT
, X_AXIS
);
525 Molecule d
= afm_find("scripts-accDot");
526 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
527 d
.translate_axis(-0.8 * staff_space PT
, X_AXIS
);
530 if (reg
.left_str(2) == "SS")
532 Molecule d
= afm_find("scripts-accDot");
533 d
.translate_axis(0.5 * staff_space PT
, Y_AXIS
);
534 d
.translate_axis(0.4 * staff_space PT
, X_AXIS
);
536 d
.translate_axis(-0.8 * staff_space PT
, X_AXIS
);
538 reg
= reg
.right_str(reg
.length_i()-2);
540 if (reg
.left_str(1) == "S")
542 Molecule d
= afm_find("scripts-accDot");
543 d
.translate_axis(0.5 * staff_space PT
, Y_AXIS
);
545 reg
= reg
.right_str(reg
.length_i()-1);
548 else if (sym
== "Freebase")
550 Molecule r
= afm_find("scripts-accFreebase");
552 if (reg
.left_str(1) == "F")
554 Molecule d
= afm_find("scripts-accDot");
555 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
557 reg
= reg
.right_str(reg
.length_i()-1);
561 Molecule d
= afm_find("scripts-accDot");
562 d
.translate_axis(staff_space
* 0.5 PT
, Y_AXIS
);
566 else if (sym
== "Bayanbase")
568 Molecule r
= afm_find("scripts-accBayanbase");
570 if (reg
.left_str(1) == "T")
572 Molecule d
= afm_find("scripts-accDot");
573 d
.translate_axis(staff_space
* 2.5 PT
, Y_AXIS
);
575 reg
= reg
.right_str(reg
.length_i()-1);
577 /* include 4' reed just for completeness. You don't want to use this. */
578 if (reg
.left_str(1) == "F")
580 Molecule d
= afm_find("scripts-accDot");
581 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
583 reg
= reg
.right_str(reg
.length_i()-1);
585 if (reg
.left_str(2) == "EE")
587 Molecule d
= afm_find("scripts-accDot");
588 d
.translate_axis(staff_space
* 0.5 PT
, Y_AXIS
);
589 d
.translate_axis(0.4 * staff_space PT
, X_AXIS
);
591 d
.translate_axis(-0.8 * staff_space PT
, X_AXIS
);
593 reg
= reg
.right_str(reg
.length_i()-2);
595 if (reg
.left_str(1) == "E")
597 Molecule d
= afm_find("scripts-accDot");
598 d
.translate_axis(staff_space
* 0.5 PT
, Y_AXIS
);
600 reg
= reg
.right_str(reg
.length_i()-1);
603 else if (sym
== "Stdbase")
605 Molecule r
= afm_find("scripts-accStdbase");
607 if (reg
.left_str(1) == "T")
609 Molecule d
= afm_find("scripts-accDot");
610 d
.translate_axis(staff_space
* 3.5 PT
, Y_AXIS
);
612 reg
= reg
.right_str(reg
.length_i()-1);
614 if (reg
.left_str(1) == "F")
616 Molecule d
= afm_find("scripts-accDot");
617 d
.translate_axis(staff_space
* 2.5 PT
, Y_AXIS
);
619 reg
= reg
.right_str(reg
.length_i()-1);
621 if (reg
.left_str(1) == "M")
623 Molecule d
= afm_find("scripts-accDot");
624 d
.translate_axis(staff_space
* 2 PT
, Y_AXIS
);
625 d
.translate_axis(staff_space PT
, X_AXIS
);
627 reg
= reg
.right_str(reg
.length_i()-1);
629 if (reg
.left_str(1) == "E")
631 Molecule d
= afm_find("scripts-accDot");
632 d
.translate_axis(staff_space
* 1.5 PT
, Y_AXIS
);
634 reg
= reg
.right_str(reg
.length_i()-1);
636 if (reg
.left_str(1) == "S")
638 Molecule d
= afm_find("scripts-accDot");
639 d
.translate_axis(staff_space
* 0.5 PT
, Y_AXIS
);
641 reg
= reg
.right_str(reg
.length_i()-1);
644 /* ugh maybe try to use regular font for S.B. and B.B and only use one font
646 else if (sym
== "SB")
648 Molecule r
= afm_find("scripts-accSB");
651 else if (sym
== "BB")
653 Molecule r
= afm_find("scripts-accBB");
656 else if (sym
== "OldEE")
658 Molecule r
= afm_find("scripts-accOldEE");
661 else if (sym
== "OldEES")
663 Molecule r
= afm_find("scripts-accOldEES");