OLD | NEW |
1 /* | 1 /* |
2 This file is part of LilyPond, the GNU music typesetter. | 2 This file is part of LilyPond, the GNU music typesetter. |
3 | 3 |
4 Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> |
5 Jan Nieuwenhuizen <janneke@gnu.org> | 5 Jan Nieuwenhuizen <janneke@gnu.org> |
6 | 6 |
7 TODO: This is way too hairy | 7 TODO: This is way too hairy |
8 | 8 |
9 TODO: fix naming. | 9 TODO: fix naming. |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include "stem.hh" | 27 #include "stem.hh" |
28 #include "spanner.hh" | 28 #include "spanner.hh" |
29 | 29 |
30 #include <cmath> // rint | 30 #include <cmath> // rint |
31 using namespace std; | 31 using namespace std; |
32 | 32 |
33 #include "beam.hh" | 33 #include "beam.hh" |
34 #include "directional-element-interface.hh" | 34 #include "directional-element-interface.hh" |
35 #include "dot-column.hh" | 35 #include "dot-column.hh" |
36 #include "font-interface.hh" | 36 #include "font-interface.hh" |
| 37 #include "glissando-stem.hh" |
37 #include "international.hh" | 38 #include "international.hh" |
38 #include "lookup.hh" | 39 #include "lookup.hh" |
39 #include "misc.hh" | 40 #include "misc.hh" |
40 #include "note-head.hh" | 41 #include "note-head.hh" |
41 #include "output-def.hh" | 42 #include "output-def.hh" |
42 #include "paper-column.hh" | 43 #include "paper-column.hh" |
43 #include "pointer-group-interface.hh" | 44 #include "pointer-group-interface.hh" |
44 #include "rest.hh" | 45 #include "rest.hh" |
45 #include "rhythmic-head.hh" | 46 #include "rhythmic-head.hh" |
46 #include "side-position-interface.hh" | 47 #include "side-position-interface.hh" |
(...skipping 28 matching lines...) Expand all Loading... |
75 SCM pair = me->get_property ("beaming"); | 76 SCM pair = me->get_property ("beaming"); |
76 if (!scm_is_pair (pair)) | 77 if (!scm_is_pair (pair)) |
77 return 0; | 78 return 0; |
78 | 79 |
79 SCM lst = index_get_cell (pair, d); | 80 SCM lst = index_get_cell (pair, d); |
80 | 81 |
81 int len = scm_ilength (lst); | 82 int len = scm_ilength (lst); |
82 return max (len, 0); | 83 return max (len, 0); |
83 } | 84 } |
84 | 85 |
| 86 MAKE_SCHEME_CALLBACK (Stem, calc_head_positions, 1) |
| 87 SCM |
| 88 Stem::calc_head_positions (SCM smob) |
| 89 { |
| 90 return ly_interval2scm (head_positions (unsmob_grob (smob))); |
| 91 } |
| 92 |
85 Interval | 93 Interval |
86 Stem::head_positions (Grob *me) | 94 Stem::head_positions (Grob *me) |
87 { | 95 { |
88 if (head_count (me)) | 96 if (head_count (me)) |
89 { | 97 { |
90 Drul_array<Grob *> e (extremal_heads (me)); | 98 Drul_array<Grob *> e (extremal_heads (me)); |
91 return Interval (Staff_symbol_referencer::get_position (e[DOWN]), | 99 return Interval (Staff_symbol_referencer::get_position (e[DOWN]), |
92 Staff_symbol_referencer::get_position (e[UP])); | 100 Staff_symbol_referencer::get_position (e[UP])); |
93 } | 101 } |
94 return Interval (); | 102 return Interval (); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 Stem::is_invisible (Grob *me) | 232 Stem::is_invisible (Grob *me) |
225 { | 233 { |
226 return !is_normal_stem (me) | 234 return !is_normal_stem (me) |
227 && (robust_scm2double (me->get_property ("stemlet-length"), | 235 && (robust_scm2double (me->get_property ("stemlet-length"), |
228 0.0) == 0.0); | 236 0.0) == 0.0); |
229 } | 237 } |
230 | 238 |
231 bool | 239 bool |
232 Stem::is_normal_stem (Grob *me) | 240 Stem::is_normal_stem (Grob *me) |
233 { | 241 { |
234 return head_count (me) && scm_to_int (me->get_property ("duration-log")) >= 1; | 242 return (Glissando_stem::has_interface (me) |
| 243 || (head_count (me) |
| 244 && scm_to_int (me->get_property ("duration-log")) >= 1)); |
235 } | 245 } |
236 | 246 |
237 MAKE_SCHEME_CALLBACK (Stem, pure_height, 3) | 247 MAKE_SCHEME_CALLBACK (Stem, pure_height, 3) |
238 SCM | 248 SCM |
239 Stem::pure_height (SCM smob, | 249 Stem::pure_height (SCM smob, |
240 SCM /* start */, | 250 SCM /* start */, |
241 SCM /* end */) | 251 SCM /* end */) |
242 { | 252 { |
243 Grob *me = unsmob_grob (smob); | 253 Grob *me = unsmob_grob (smob); |
244 Interval iv; | 254 Interval iv; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 | 293 |
284 return ly_interval2scm (iv); | 294 return ly_interval2scm (iv); |
285 } | 295 } |
286 | 296 |
287 MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1) | 297 MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1) |
288 SCM | 298 SCM |
289 Stem::calc_stem_end_position (SCM smob) | 299 Stem::calc_stem_end_position (SCM smob) |
290 { | 300 { |
291 Grob *me = unsmob_grob (smob); | 301 Grob *me = unsmob_grob (smob); |
292 | 302 |
293 if (!head_count (me)) | 303 if (!head_count (me) && !Glissando_stem::has_interface (me)) |
294 return scm_from_double (0.0); | 304 return scm_from_double (0.0); |
295 | 305 |
296 if (Grob *beam = get_beam (me)) | 306 if (Grob *beam = get_beam (me)) |
297 { | 307 { |
298 (void) beam->get_property ("quantized-positions"); | 308 (void) beam->get_property ("quantized-positions"); |
299 return me->get_property ("stem-end-position"); | 309 return me->get_property ("stem-end-position"); |
300 } | 310 } |
301 | 311 |
302 vector<Real> a; | 312 vector<Real> a; |
303 | 313 |
304 /* WARNING: IN HALF SPACES */ | 314 /* WARNING: IN HALF SPACES */ |
305 Real length = robust_scm2double (me->get_property ("length"), 7); | 315 Real length = robust_scm2double (me->get_property ("length"), 7); |
306 | 316 |
307 Direction dir = get_grob_direction (me); | 317 Direction dir = get_grob_direction (me); |
308 Interval hp = head_positions (me); | 318 Interval hp = robust_scm2interval (me->get_property ("head-positions"), Interv
al (0,0)); |
309 Real stem_end = dir ? hp[dir] + dir * length : 0; | 319 Real stem_end = dir ? hp[dir] + dir * length : 0; |
310 | 320 |
311 /* TODO: change name to extend-stems to staff/center/'() */ | 321 /* TODO: change name to extend-stems to staff/center/'() */ |
312 bool no_extend = to_boolean (me->get_property ("no-stem-extend")); | 322 bool no_extend = to_boolean (me->get_property ("no-stem-extend")); |
313 if (!no_extend && dir * stem_end < 0) | 323 if (!no_extend && dir * stem_end < 0) |
314 stem_end = 0.0; | 324 stem_end = 0.0; |
315 | 325 |
316 return scm_from_double (stem_end); | 326 return scm_from_double (stem_end); |
317 } | 327 } |
318 | 328 |
(...skipping 11 matching lines...) Expand all Loading... |
330 Real staff_rad = Staff_symbol_referencer::staff_radius (me); | 340 Real staff_rad = Staff_symbol_referencer::staff_radius (me); |
331 Real length = 7; | 341 Real length = 7; |
332 SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL); | 342 SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL); |
333 if (scm_is_pair (s)) | 343 if (scm_is_pair (s)) |
334 length = 2 * scm_to_double (robust_list_ref (durlog - 2, s)); | 344 length = 2 * scm_to_double (robust_list_ref (durlog - 2, s)); |
335 | 345 |
336 Direction dir = get_grob_direction (me); | 346 Direction dir = get_grob_direction (me); |
337 | 347 |
338 /* Stems in unnatural (forced) direction should be shortened, | 348 /* Stems in unnatural (forced) direction should be shortened, |
339 according to [Roush & Gourlay] */ | 349 according to [Roush & Gourlay] */ |
340 Interval hp = head_positions (me); | 350 Interval hp = robust_scm2interval (me->get_property ("head-positions"), Interv
al (0,0)); |
341 if (dir && dir * hp[dir] >= 0) | 351 if (dir && dir * hp[dir] >= 0) |
342 { | 352 { |
343 SCM sshorten = ly_assoc_get (ly_symbol2scm ("stem-shorten"), details, SCM_
EOL); | 353 SCM sshorten = ly_assoc_get (ly_symbol2scm ("stem-shorten"), details, SCM_
EOL); |
344 SCM scm_shorten = scm_is_pair (sshorten) | 354 SCM scm_shorten = scm_is_pair (sshorten) |
345 ? robust_list_ref (max (duration_log (me) - 2, 0), sshor
ten) : SCM_EOL; | 355 ? robust_list_ref (max (duration_log (me) - 2, 0), sshor
ten) : SCM_EOL; |
346 Real shorten_property = 2 * robust_scm2double (scm_shorten, 0); | 356 Real shorten_property = 2 * robust_scm2double (scm_shorten, 0); |
347 /* change in length between full-size and shortened stems is executed gra
dually. | 357 /* change in length between full-size and shortened stems is executed gra
dually. |
348 "transition area" = stems between full-sized and fully-shortened. | 358 "transition area" = stems between full-sized and fully-shortened. |
349 */ | 359 */ |
350 Real quarter_stem_length = 2 * scm_to_double (robust_list_ref (0, s)); | 360 Real quarter_stem_length = 2 * scm_to_double (robust_list_ref (0, s)); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 Stem::stem_end_position (Grob *me) | 607 Stem::stem_end_position (Grob *me) |
598 { | 608 { |
599 return robust_scm2double (me->get_property ("stem-end-position"), 0); | 609 return robust_scm2double (me->get_property ("stem-end-position"), 0); |
600 } | 610 } |
601 | 611 |
602 MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1); | 612 MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1); |
603 SCM | 613 SCM |
604 Stem::calc_flag (SCM smob) | 614 Stem::calc_flag (SCM smob) |
605 { | 615 { |
606 Grob *me = unsmob_grob (smob); | 616 Grob *me = unsmob_grob (smob); |
| 617 return internal_calc_flag (me, get_grob_direction (me)).smobbed_copy (); |
| 618 } |
| 619 · |
| 620 Stencil |
| 621 Stem::internal_calc_flag (Grob *me, Direction d) |
| 622 { |
607 | 623 |
608 int log = duration_log (me); | 624 int log = duration_log (me); |
609 /* | 625 /* |
610 TODO: maybe property stroke-style should take different values, | 626 TODO: maybe property stroke-style should take different values, |
611 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's | 627 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's |
612 '() or "grace"). */ | 628 '() or "grace"). */ |
613 string flag_style; | 629 string flag_style; |
614 | 630 |
615 SCM flag_style_scm = me->get_property ("flag-style"); | 631 SCM flag_style_scm = me->get_property ("flag-style"); |
616 if (scm_is_symbol (flag_style_scm)) | 632 if (scm_is_symbol (flag_style_scm)) |
617 flag_style = ly_symbol2string (flag_style_scm); | 633 flag_style = ly_symbol2string (flag_style_scm); |
618 | 634 |
619 if (flag_style == "no-flag") | 635 if (flag_style == "no-flag") |
620 return Stencil ().smobbed_copy (); | 636 return Stencil (); |
621 | 637 |
622 bool adjust = true; | 638 bool adjust = true; |
623 | 639 |
624 string staffline_offs; | 640 string staffline_offs; |
625 if (flag_style == "mensural") | 641 if (flag_style == "mensural") |
626 /* Mensural notation: For notes on staff lines, use different | 642 /* Mensural notation: For notes on staff lines, use different |
627 flags than for notes between staff lines. The idea is that | 643 flags than for notes between staff lines. The idea is that |
628 flags are always vertically aligned with the staff lines, | 644 flags are always vertically aligned with the staff lines, |
629 regardless if the note head is on a staff line or between two | 645 regardless if the note head is on a staff line or between two |
630 staff lines. In other words, the inner end of a flag always | 646 staff lines. In other words, the inner end of a flag always |
631 touches a staff line. | 647 touches a staff line. |
632 */ | 648 */ |
633 { | 649 { |
634 if (adjust) | 650 if (adjust) |
635 { | 651 { |
636 int p = (int) (rint (stem_end_position (me))); | 652 int p = (int) (rint (stem_end_position (me))); |
637 staffline_offs | 653 staffline_offs |
638 = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; | 654 = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; |
639 } | 655 } |
640 else | 656 else |
641 staffline_offs = "2"; | 657 staffline_offs = "2"; |
642 } | 658 } |
643 else | 659 else |
644 staffline_offs = ""; | 660 staffline_offs = ""; |
645 | 661 |
646 char dir = (get_grob_direction (me) == UP) ? 'u' : 'd'; | 662 char dir = (d == UP) ? 'u' : 'd'; |
647 string font_char = flag_style | 663 string font_char = flag_style |
648 + to_string (dir) + staffline_offs + to_string (log); | 664 + to_string (dir) + staffline_offs + to_string (log); |
649 Font_metric *fm = Font_interface::get_default_font (me); | 665 Font_metric *fm = Font_interface::get_default_font (me); |
650 Stencil flag = fm->find_by_name ("flags." + font_char); | 666 Stencil flag = fm->find_by_name ("flags." + font_char); |
651 if (flag.is_empty ()) | 667 if (flag.is_empty ()) |
652 me->warning (_f ("flag `%s' not found", font_char)); | 668 me->warning (_f ("flag `%s' not found", font_char)); |
653 | 669 |
654 SCM stroke_style_scm = me->get_property ("stroke-style"); | 670 SCM stroke_style_scm = me->get_property ("stroke-style"); |
655 if (scm_is_string (stroke_style_scm)) | 671 if (scm_is_string (stroke_style_scm)) |
656 { | 672 { |
657 string stroke_style = ly_scm2string (stroke_style_scm); | 673 string stroke_style = ly_scm2string (stroke_style_scm); |
658 if (!stroke_style.empty ()) | 674 if (!stroke_style.empty ()) |
659 { | 675 { |
660 string font_char = flag_style + to_string (dir) + stroke_style; | 676 string font_char = flag_style + to_string (dir) + stroke_style; |
661 Stencil stroke = fm->find_by_name ("flags." + font_char); | 677 Stencil stroke = fm->find_by_name ("flags." + font_char); |
662 if (stroke.is_empty ()) | 678 if (stroke.is_empty ()) |
663 { | 679 { |
664 font_char = to_string (dir) + stroke_style; | 680 font_char = to_string (dir) + stroke_style; |
665 stroke = fm->find_by_name ("flags." + font_char); | 681 stroke = fm->find_by_name ("flags." + font_char); |
666 } | 682 } |
667 if (stroke.is_empty ()) | 683 if (stroke.is_empty ()) |
668 me->warning (_f ("flag stroke `%s' not found", font_char)); | 684 me->warning (_f ("flag stroke `%s' not found", font_char)); |
669 else | 685 else |
670 flag.add_stencil (stroke); | 686 flag.add_stencil (stroke); |
671 } | 687 } |
672 } | 688 } |
673 | 689 |
674 return flag.smobbed_copy (); | 690 return flag; |
675 } | 691 } |
676 | 692 |
677 Stencil | 693 Stencil |
678 Stem::flag (Grob *me) | 694 Stem::flag (Grob *me) |
679 { | 695 { |
680 int log = duration_log (me); | 696 int log = duration_log (me); |
681 if (log < 3 | 697 if (log < 3 |
682 || unsmob_grob (me->get_object ("beam"))) | 698 || unsmob_grob (me->get_object ("beam"))) |
683 return Stencil (); | 699 return Stencil (); |
684 | 700 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 0.0); | 786 0.0); |
771 bool stemlet = stemlet_length > 0.0; | 787 bool stemlet = stemlet_length > 0.0; |
772 | 788 |
773 /* TODO: make the stem start a direction ? | 789 /* TODO: make the stem start a direction ? |
774 This is required to avoid stems passing in tablature chords. */ | 790 This is required to avoid stems passing in tablature chords. */ |
775 Grob *lh | 791 Grob *lh |
776 = to_boolean (me->get_property ("avoid-note-head")) | 792 = to_boolean (me->get_property ("avoid-note-head")) |
777 ? last_head (me) | 793 ? last_head (me) |
778 : first_head (me); | 794 : first_head (me); |
779 | 795 |
780 if (!lh && !stemlet) | 796 if (!lh && !stemlet && !Glissando_stem::has_interface (me)) |
781 return SCM_EOL; | 797 return SCM_EOL; |
782 | 798 |
783 if (!lh && stemlet && !beam) | 799 if (!lh && stemlet && !beam) |
784 return SCM_EOL; | 800 return SCM_EOL; |
785 | 801 |
786 if (lh && robust_scm2int (lh->get_property ("duration-log"), 0) < 1) | 802 if (lh && robust_scm2int (lh->get_property ("duration-log"), 0) < 1) |
787 return SCM_EOL; | 803 return SCM_EOL; |
788 | 804 |
789 if (is_invisible (me)) | 805 if (is_invisible (me)) |
790 return SCM_EOL; | 806 return SCM_EOL; |
791 | 807 |
792 Real y2 = robust_scm2double (me->get_property ("stem-end-position"), 0.0); | 808 Real y2 = robust_scm2double (me->get_property ("stem-end-position"), 0.0); |
793 Real y1 = y2; | 809 Real y1 = y2; |
794 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | 810 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; |
795 | 811 |
796 if (lh) | 812 if (lh || Glissando_stem::has_interface (me)) |
797 y2 = robust_scm2double (me->get_property ("stem-begin-position"), 0.0); | 813 y2 = robust_scm2double (me->get_property ("stem-begin-position"), 0.0); |
798 else if (stemlet) | 814 else if (stemlet) |
799 { | 815 { |
800 Real beam_translation = Beam::get_beam_translation (beam); | 816 Real beam_translation = Beam::get_beam_translation (beam); |
801 Real beam_thickness = Beam::get_beam_thickness (beam); | 817 Real beam_thickness = Beam::get_beam_thickness (beam); |
802 int beam_count = beam_multiplicity (me).length () + 1; | 818 int beam_count = beam_multiplicity (me).length () + 1; |
803 | 819 |
804 y2 -= d | 820 y2 -= d |
805 * (0.5 * beam_thickness | 821 * (0.5 * beam_thickness |
806 + beam_translation * max (0, (beam_count - 1)) | 822 + beam_translation * max (0, (beam_count - 1)) |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 + height_of_my_beams | 999 + height_of_my_beams |
984 + height_of_my_trem | 1000 + height_of_my_trem |
985 /* stem only extends to center of beam */ | 1001 /* stem only extends to center of beam */ |
986 - 0.5 * beam_thickness; | 1002 - 0.5 * beam_thickness; |
987 | 1003 |
988 ideal_length = max (ideal_length, ideal_minimum_length); | 1004 ideal_length = max (ideal_length, ideal_minimum_length); |
989 | 1005 |
990 /* Convert to Y position, calculate for dir == UP */ | 1006 /* Convert to Y position, calculate for dir == UP */ |
991 Real note_start | 1007 Real note_start |
992 = /* staff positions */ | 1008 = /* staff positions */ |
993 head_positions (me)[my_dir] * 0.5 | 1009 robust_scm2interval (me->get_property ("head-positions"), Interval (0,0))[
my_dir] * 0.5 |
994 * my_dir * staff_space; | 1010 * my_dir * staff_space; |
995 Real ideal_y = note_start + ideal_length; | 1011 Real ideal_y = note_start + ideal_length; |
996 | 1012 |
997 /* Conditions for Y position */ | 1013 /* Conditions for Y position */ |
998 | 1014 |
999 /* Lowest beam of (UP) beam must never be lower than second staffline | 1015 /* Lowest beam of (UP) beam must never be lower than second staffline |
1000 | 1016 |
1001 Reference? | 1017 Reference? |
1002 | 1018 |
1003 Although this (additional) rule is probably correct, | 1019 Although this (additional) rule is probably correct, |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 "beaming " | 1119 "beaming " |
1104 "beamlet-default-length " | 1120 "beamlet-default-length " |
1105 "beamlet-max-length-proportion " | 1121 "beamlet-max-length-proportion " |
1106 "default-direction " | 1122 "default-direction " |
1107 "details " | 1123 "details " |
1108 "direction " | 1124 "direction " |
1109 "duration-log " | 1125 "duration-log " |
1110 "flag " | 1126 "flag " |
1111 "flag-style " | 1127 "flag-style " |
1112 "french-beaming " | 1128 "french-beaming " |
| 1129 "head-positions " |
1113 "length " | 1130 "length " |
1114 "length-fraction " | 1131 "length-fraction " |
1115 "max-beam-connect " | 1132 "max-beam-connect " |
1116 "neutral-direction " | 1133 "neutral-direction " |
1117 "no-stem-extend " | 1134 "no-stem-extend " |
1118 "note-heads " | 1135 "note-heads " |
1119 "positioning-done " | 1136 "positioning-done " |
1120 "rests " | 1137 "rests " |
1121 "stem-begin-position " | 1138 "stem-begin-position " |
1122 "stem-end-position " | 1139 "stem-end-position " |
(...skipping 11 matching lines...) Expand all Loading... |
1134 ideal_y_ = shortest_y_ = 0; | 1151 ideal_y_ = shortest_y_ = 0; |
1135 dir_ = CENTER; | 1152 dir_ = CENTER; |
1136 } | 1153 } |
1137 | 1154 |
1138 void | 1155 void |
1139 Stem_info::scale (Real x) | 1156 Stem_info::scale (Real x) |
1140 { | 1157 { |
1141 ideal_y_ *= x; | 1158 ideal_y_ *= x; |
1142 shortest_y_ *= x; | 1159 shortest_y_ *= x; |
1143 } | 1160 } |
OLD | NEW |