Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 13 matching lines...) Expand all Loading... | |
24 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. | 24 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. |
25 */ | 25 */ |
26 | 26 |
27 /* | 27 /* |
28 Note that several internal functions have a calc_beam bool argument. | 28 Note that several internal functions have a calc_beam bool argument. |
29 This argument means: "If set, acknowledge the fact that there is a beam | 29 This argument means: "If set, acknowledge the fact that there is a beam |
30 and deal with it. If not, give me the measurements as if there is no beam." | 30 and deal with it. If not, give me the measurements as if there is no beam." |
31 Most pure functions are called WITHOUT calc_beam, whereas non-pure functions | 31 Most pure functions are called WITHOUT calc_beam, whereas non-pure functions |
32 are called WITH calc_beam. | 32 are called WITH calc_beam. |
33 ·· | 33 ·· |
34 The only exception to this is ::pure_height, whcih calls internal_pure_height | 34 The only exception to this is ::pure_height, which calls internal_pure_height |
Trevor Daniels
2011/08/14 20:33:36
which
| |
35 with "true" for calc_beam in order to trigger the calculations of other | 35 with "true" for calc_beam in order to trigger the calculations of other |
36 pure heights in case there is a beam. It passes false, however, to | 36 pure heights in case there is a beam. It passes false, however, to |
37 internal_height and internal_pure_height for all subsequent iterations. | 37 internal_height and internal_pure_height for all subsequent iterations. |
38 */ | 38 */ |
39 | 39 |
40 #include "stem.hh" | 40 #include "stem.hh" |
41 #include "spanner.hh" | 41 #include "spanner.hh" |
42 | 42 |
43 #include <cmath> // rint | 43 #include <cmath> // rint |
44 using namespace std; | 44 using namespace std; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 // todo: margins | 123 // todo: margins |
124 Direction d = get_grob_direction (me); | 124 Direction d = get_grob_direction (me); |
125 | 125 |
126 Grob *beam = unsmob_grob (me->get_object ("beam")); | 126 Grob *beam = unsmob_grob (me->get_object ("beam")); |
127 if (d && d * head_positions (me)[get_grob_direction (me)] >= se * d) | 127 if (d && d * head_positions (me)[get_grob_direction (me)] >= se * d) |
128 me->warning (_ ("weird stem size, check for narrow beams")); | 128 me->warning (_ ("weird stem size, check for narrow beams")); |
129 | 129 |
130 Interval height = me->pure_height (me, 0, INT_MAX); | 130 Interval height = me->pure_height (me, 0, INT_MAX); |
131 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | 131 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; |
132 | 132 |
133 height[d] = se * half_space; | 133 height[d] = se * half_space + beam_end_corrective (me); |
134 | 134 |
135 Real stemlet_length = robust_scm2double (me->get_property ("stemlet-length"), | 135 Real stemlet_length = robust_scm2double (me->get_property ("stemlet-length"), |
136 0.0); | 136 0.0); |
137 bool stemlet = stemlet_length > 0.0; | 137 bool stemlet = stemlet_length > 0.0; |
138 | 138 |
139 Grob *lh = get_reference_head (me); | 139 Grob *lh = get_reference_head (me); |
140 | 140 |
141 if (stemlet && !lh && beam) | 141 if (!lh) |
Trevor Daniels
2011/08/14 20:33:36
All three conditions include !lh; better test !lh
| |
142 { | 142 { |
143 Real beam_translation = Beam::get_beam_translation (beam); | 143 if (stemlet && beam) |
144 Real beam_thickness = Beam::get_beam_thickness (beam); | 144 { |
145 int beam_count = beam_multiplicity (me).length () + 1; | 145 Real beam_translation = Beam::get_beam_translation (beam); |
146 | 146 Real beam_thickness = Beam::get_beam_thickness (beam); |
147 height[-d] = height[d] - d | 147 int beam_count = beam_multiplicity (me).length () + 1; |
148 * (0.5 * beam_thickness | 148 |
149 + beam_translation * max (0, (beam_count - 1)) | 149 height[-d] = (height[d] - d |
Trevor Daniels
2011/08/14 20:33:36
indent
| |
150 + stemlet_length); | 150 * (0.5 * beam_thickness |
151 } | 151 + beam_translation * max (0, (beam_count - 1)) |
152 else if (!stemlet && !lh && beam) | 152 + stemlet_length)); |
153 height[-d] = height[d]; | 153 } |
154 else if (stemlet && !lh && !beam) | 154 else if (!stemlet && beam) |
155 { | 155 height[-d] = height[d]; |
156 me->programming_error ("Can't have a stemlet without a beam."); | 156 else if (stemlet && !beam) |
157 me->programming_error ("Can't have a stemlet without a beam."); | |
157 } | 158 } |
158 | 159 |
159 me->set_property ("Y-extent", ly_interval2scm (height)); | 160 me->set_property ("Y-extent", ly_interval2scm (height)); |
160 } | 161 } |
161 | 162 |
162 /* Note head that determines hshift for upstems | 163 /* Note head that determines hshift for upstems |
163 WARNING: triggers direction */ | 164 WARNING: triggers direction */ |
164 Grob * | 165 Grob * |
165 Stem::support_head (Grob *me) | 166 Stem::support_head (Grob *me) |
166 { | 167 { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 if (!beam) | 301 if (!beam) |
301 return iv; | 302 return iv; |
302 if (!to_boolean (me->get_property ("cross-staff")) && calc_beam) | 303 if (!to_boolean (me->get_property ("cross-staff")) && calc_beam) |
303 { | 304 { |
304 Interval overshoot; | 305 Interval overshoot; |
305 Direction dir = get_grob_direction (me); | 306 Direction dir = get_grob_direction (me); |
306 Direction d = DOWN; | 307 Direction d = DOWN; |
307 do | 308 do |
308 overshoot[d] = d == dir ? dir * infinity_f : iv[d]; | 309 overshoot[d] = d == dir ? dir * infinity_f : iv[d]; |
309 while (flip (&d) != DOWN); | 310 while (flip (&d) != DOWN); |
311 | |
312 vector<Interval> heights; | |
313 vector<Grob *> my_stems; | |
310 extract_grob_set (beam, "normal-stems", normal_stems); | 314 extract_grob_set (beam, "normal-stems", normal_stems); |
311 for (vsize i = 0; i < normal_stems.size (); i++) | 315 for (vsize i = 0; i < normal_stems.size (); i++) |
312 if (normal_stems[i] != me && get_grob_direction (normal_stems[i]) == dir ) | 316 if (normal_stems[i] != me && get_grob_direction (normal_stems[i]) == dir ) |
313 iv.unite (Stem::internal_pure_height (normal_stems[i], false)); | 317 { |
318 heights.push_back (Stem::internal_pure_height (normal_stems[i], fals e)); | |
319 my_stems.push_back (normal_stems[i]); | |
320 iv.unite (heights.back ()); | |
321 } | |
322 for (vsize i = 0; i < my_stems.size (); i++) | |
323 cache_pure_height (my_stems[i], iv, heights[i]); | |
314 iv.intersect (overshoot); | 324 iv.intersect (overshoot); |
315 } | 325 } |
316 | 326 |
317 return iv; | 327 return iv; |
328 } | |
329 | |
330 void | |
331 Stem::cache_pure_height (Grob *me, Interval iv, Interval my_iv) | |
332 { | |
333 Interval overshoot; | |
334 Direction dir = get_grob_direction (me); | |
335 Direction d = DOWN; | |
336 do | |
337 overshoot[d] = d == dir ? dir * infinity_f : my_iv[d]; | |
338 while (flip (&d) != DOWN); | |
339 | |
340 iv.intersect (overshoot); | |
341 dynamic_cast<Item *> (me)->cache_pure_height (iv); | |
318 } | 342 } |
319 | 343 |
320 MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1) | 344 MAKE_SCHEME_CALLBACK (Stem, calc_stem_end_position, 1) |
321 SCM | 345 SCM |
322 Stem::calc_stem_end_position (SCM smob) | 346 Stem::calc_stem_end_position (SCM smob) |
323 { | 347 { |
324 Grob *me = unsmob_grob (smob); | 348 Grob *me = unsmob_grob (smob); |
325 return scm_from_double (internal_calc_stem_end_position (me, true)); | 349 return scm_from_double (internal_calc_stem_end_position (me, true)); |
326 } | 350 } |
327 | 351 |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 } | 628 } |
605 | 629 |
606 Grob* | 630 Grob* |
607 Stem::get_reference_head (Grob *me) | 631 Stem::get_reference_head (Grob *me) |
608 { | 632 { |
609 return to_boolean (me->get_property ("avoid-note-head")) | 633 return to_boolean (me->get_property ("avoid-note-head")) |
610 ? last_head (me) | 634 ? last_head (me) |
611 : first_head (me); | 635 : first_head (me); |
612 } | 636 } |
613 | 637 |
614 Interval | 638 Real |
615 Stem::internal_height (Grob *me, bool calc_beam) | 639 Stem::beam_end_corrective (Grob *me) |
616 { | 640 { |
617 if (!is_valid_stem (me)) | 641 Grob *beam = unsmob_grob (me->get_object ("beam")); |
618 return Interval (); | |
619 ·· | |
620 Direction dir = get_grob_direction (me); | 642 Direction dir = get_grob_direction (me); |
621 | 643 if (beam) |
622 Grob *beam = get_beam (me); | |
623 if (beam && calc_beam) | |
624 { | |
625 /* trigger set-stem-lengths. */ | |
626 (void) beam->get_property ("quantized-positions"); | |
627 return me->extent (me, Y_AXIS); | |
628 } | |
629 | |
630 /* | |
631 Can't get_stencil (), since that would cache stencils too early. | |
632 This causes problems with beams. | |
633 */ | |
634 Real stemlet_length = robust_scm2double (me->get_property ("stemlet-length"), | |
635 0.0); | |
636 bool stemlet = stemlet_length > 0.0; | |
637 | |
638 Real y2 = internal_calc_stem_end_position (me, calc_beam); | |
639 Real y1 = internal_calc_stem_begin_position (me, calc_beam); | |
640 | |
641 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | |
642 | |
643 Interval stem_y = Interval (min (y1, y2), max (y2, y1)) * half_space; | |
644 if (beam && !stemlet) | |
645 { | 644 { |
646 if (dir == CENTER) | 645 if (dir == CENTER) |
647 { | 646 { |
648 programming_error ("no stem direction"); | 647 programming_error ("no stem direction"); |
649 dir = UP; | 648 dir = UP; |
650 } | 649 } |
651 stem_y[dir] += dir * Beam::get_beam_thickness (beam) * 0.5; | 650 return dir * Beam::get_beam_thickness (beam) * 0.5; |
652 } | 651 } |
652 return 0.0; | |
653 } | |
654 | |
655 Interval | |
656 Stem::internal_height (Grob *me, bool calc_beam) | |
657 { | |
658 if (!is_valid_stem (me)) | |
659 return Interval (); | |
660 ·· | |
661 Direction dir = get_grob_direction (me); | |
662 | |
663 Grob *beam = get_beam (me); | |
664 if (beam && calc_beam) | |
665 { | |
666 /* trigger set-stem-lengths. */ | |
667 (void) beam->get_property ("quantized-positions"); | |
668 return me->extent (me, Y_AXIS); | |
669 } | |
670 | |
671 Real y2 = internal_calc_stem_end_position (me, calc_beam); | |
672 Real y1 = internal_calc_stem_begin_position (me, calc_beam); | |
673 | |
674 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | |
675 | |
676 Interval stem_y = Interval (min (y1, y2), max (y2, y1)) * half_space; | |
677 stem_y[dir] += beam_end_corrective (me); | |
653 | 678 |
654 return stem_y; | 679 return stem_y; |
655 } | |
656 | |
657 MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1); | |
658 SCM | |
659 Stem::calc_flag (SCM smob) | |
660 { | |
661 Grob *me = unsmob_grob (smob); | |
662 | |
663 int log = duration_log (me); | |
664 /* | |
665 TODO: maybe property stroke-style should take different values, | |
666 e.g. "" (i.e. no stroke), "single" and "double" (currently, it's | |
667 '() or "grace"). */ | |
668 string flag_style; | |
669 | |
670 SCM flag_style_scm = me->get_property ("flag-style"); | |
671 if (scm_is_symbol (flag_style_scm)) | |
672 flag_style = ly_symbol2string (flag_style_scm); | |
673 | |
674 if (flag_style == "no-flag") | |
675 return Stencil ().smobbed_copy (); | |
676 | |
677 bool adjust = true; | |
678 | |
679 Direction d = get_grob_direction (me); | |
680 string staffline_offs; | |
681 if (flag_style == "mensural") | |
682 /* Mensural notation: For notes on staff lines, use different | |
683 flags than for notes between staff lines. The idea is that | |
684 flags are always vertically aligned with the staff lines, | |
685 regardless if the note head is on a staff line or between two | |
686 staff lines. In other words, the inner end of a flag always | |
687 touches a staff line. | |
688 */ | |
689 { | |
690 if (adjust) | |
691 { | |
692 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | |
693 int p = (int) (rint (me->extent (me, Y_AXIS)[d] / half_space)); | |
694 staffline_offs | |
695 = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; | |
696 } | |
697 else | |
698 staffline_offs = "2"; | |
699 } | |
700 else | |
701 staffline_offs = ""; | |
702 | |
703 char dir = (d == UP) ? 'u' : 'd'; | |
704 string font_char = flag_style | |
705 + to_string (dir) + staffline_offs + to_string (log); | |
706 Font_metric *fm = Font_interface::get_default_font (me); | |
707 Stencil flag = fm->find_by_name ("flags." + font_char); | |
708 if (flag.is_empty ()) | |
709 me->warning (_f ("flag `%s' not found", font_char)); | |
710 | |
711 SCM stroke_style_scm = me->get_property ("stroke-style"); | |
712 if (scm_is_string (stroke_style_scm)) | |
713 { | |
714 string stroke_style = ly_scm2string (stroke_style_scm); | |
715 if (!stroke_style.empty ()) | |
716 { | |
717 string font_char = flag_style + to_string (dir) + stroke_style; | |
718 Stencil stroke = fm->find_by_name ("flags." + font_char); | |
719 if (stroke.is_empty ()) | |
720 { | |
721 font_char = to_string (dir) + stroke_style; | |
722 stroke = fm->find_by_name ("flags." + font_char); | |
723 } | |
724 if (stroke.is_empty ()) | |
725 me->warning (_f ("flag stroke `%s' not found", font_char)); | |
726 else | |
727 flag.add_stencil (stroke); | |
728 } | |
729 } | |
730 | |
731 return flag.smobbed_copy (); | |
732 } | |
733 | |
734 Stencil | |
735 Stem::flag (Grob *me) | |
736 { | |
737 int log = duration_log (me); | |
738 if (log < 3 | |
739 || unsmob_grob (me->get_object ("beam"))) | |
740 return Stencil (); | |
741 | |
742 if (!is_normal_stem (me)) | |
743 return Stencil (); | |
744 | |
745 // This get_property call already evaluates the scheme function with | |
746 // the grob passed as argument! Thus, we only have to check if a valid | |
747 // stencil is returned. | |
748 SCM flag_style_scm = me->get_property ("flag"); | |
749 if (Stencil *flag = unsmob_stencil (flag_style_scm)) | |
750 { | |
751 return *flag; | |
752 } | |
753 else | |
754 { | |
755 return Stencil (); | |
756 } | |
757 } | 680 } |
758 | 681 |
759 MAKE_SCHEME_CALLBACK (Stem, width, 1); | 682 MAKE_SCHEME_CALLBACK (Stem, width, 1); |
760 SCM | 683 SCM |
761 Stem::width (SCM e) | 684 Stem::width (SCM e) |
762 { | 685 { |
763 Grob *me = unsmob_grob (e); | 686 Grob *me = unsmob_grob (e); |
764 | 687 |
765 Interval r; | 688 Interval r; |
766 | 689 |
767 if (is_invisible (me)) | 690 if (is_invisible (me)) |
768 r.set_empty (); | 691 r.set_empty (); |
769 else if (unsmob_grob (me->get_object ("beam")) | 692 else |
770 || abs (duration_log (me)) <= 2) | |
771 { | 693 { |
772 r = Interval (-1, 1); | 694 r = Interval (-1, 1); |
773 r *= thickness (me) / 2; | 695 r *= thickness (me) / 2; |
774 } | 696 } |
775 else | 697 |
776 { | |
777 r = Interval (-1, 1) * thickness (me) * 0.5; | |
778 r.unite (flag (me).extent (X_AXIS)); | |
779 } | |
780 return ly_interval2scm (r); | 698 return ly_interval2scm (r); |
781 } | 699 } |
782 | 700 |
783 Real | 701 Real |
784 Stem::thickness (Grob *me) | 702 Stem::thickness (Grob *me) |
785 { | 703 { |
786 return scm_to_double (me->get_property ("thickness")) | 704 return scm_to_double (me->get_property ("thickness")) |
787 * Staff_symbol_referencer::line_thickness (me); | 705 * Staff_symbol_referencer::line_thickness (me); |
788 } | 706 } |
789 | 707 |
(...skipping 20 matching lines...) Expand all Loading... | |
810 { | 728 { |
811 Grob *beam = get_beam (me); | 729 Grob *beam = get_beam (me); |
812 Real ss = Staff_symbol_referencer::staff_space (me); | 730 Real ss = Staff_symbol_referencer::staff_space (me); |
813 if (beam && calc_beam) | 731 if (beam && calc_beam) |
814 { | 732 { |
815 (void) beam->get_property ("quantized-positions"); | 733 (void) beam->get_property ("quantized-positions"); |
816 return me->extent (me, Y_AXIS)[-get_grob_direction (me)] * ss * 2; | 734 return me->extent (me, Y_AXIS)[-get_grob_direction (me)] * ss * 2; |
817 } | 735 } |
818 | 736 |
819 Direction d = get_grob_direction (me); | 737 Direction d = get_grob_direction (me); |
820 Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; | |
821 Grob *lh = get_reference_head (me); | 738 Grob *lh = get_reference_head (me); |
822 | 739 |
823 Real pos = Staff_symbol_referencer::get_position (lh); | 740 Real pos = Staff_symbol_referencer::get_position (lh); |
824 | 741 |
825 if (Grob *head = support_head (me)) | 742 if (Grob *head = support_head (me)) |
826 { | 743 { |
827 Interval head_height = head->extent (head, Y_AXIS); | 744 Interval head_height = head->extent (head, Y_AXIS); |
828 Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS); | 745 Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS); |
829 | 746 |
830 y_attach = head_height.linear_combination (y_attach); | 747 y_attach = head_height.linear_combination (y_attach); |
831 pos += d * y_attach / half_space; | 748 pos += d * y_attach * 2 / ss; |
832 } | 749 } |
833 | 750 |
834 return pos; | 751 return pos; |
835 } | 752 } |
836 | 753 |
837 bool | 754 bool |
838 Stem::is_valid_stem (Grob *me) | 755 Stem::is_valid_stem (Grob *me) |
839 { | 756 { |
840 /* TODO: make the stem start a direction ? | 757 /* TODO: make the stem start a direction ? |
841 This is required to avoid stems passing in tablature chords. */ | 758 This is required to avoid stems passing in tablature chords. */ |
(...skipping 21 matching lines...) Expand all Loading... | |
863 | 780 |
864 MAKE_SCHEME_CALLBACK (Stem, print, 1); | 781 MAKE_SCHEME_CALLBACK (Stem, print, 1); |
865 SCM | 782 SCM |
866 Stem::print (SCM smob) | 783 Stem::print (SCM smob) |
867 { | 784 { |
868 Grob *me = unsmob_grob (smob); | 785 Grob *me = unsmob_grob (smob); |
869 if (!is_valid_stem (me)) | 786 if (!is_valid_stem (me)) |
870 return SCM_EOL; | 787 return SCM_EOL; |
871 | 788 |
872 Interval stem_y = me->extent (me, Y_AXIS); | 789 Interval stem_y = me->extent (me, Y_AXIS); |
790 Direction dir = get_grob_direction (me); | |
791 | |
792 stem_y[dir] -= beam_end_corrective (me); | |
873 | 793 |
874 // URG | 794 // URG |
875 Real stem_width = thickness (me); | 795 Real stem_width = thickness (me); |
876 Real blot | 796 Real blot |
877 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); | 797 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); |
878 | 798 |
879 Box b = Box (Interval (-stem_width / 2, stem_width / 2), | 799 Box b = Box (Interval (-stem_width / 2, stem_width / 2), |
880 stem_y); | 800 stem_y); |
881 | 801 |
882 Stencil mol; | 802 Stencil mol; |
883 Stencil ss = Lookup::round_filled_box (b, blot); | 803 Stencil ss = Lookup::round_filled_box (b, blot); |
884 mol.add_stencil (ss); | 804 mol.add_stencil (ss); |
885 | 805 |
886 mol.add_stencil (get_translated_flag (me)); | |
887 | |
888 return mol.smobbed_copy (); | 806 return mol.smobbed_copy (); |
889 } | |
890 | |
891 Stencil | |
892 Stem::get_translated_flag (Grob *me) | |
893 { | |
894 Stencil fl = flag (me); | |
895 if (!fl.is_empty ()) | |
896 { | |
897 Direction d = get_grob_direction (me); | |
898 Real blot | |
899 = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); | |
900 Real stem_width = thickness (me); | |
901 Real y2 = me->extent (me, Y_AXIS)[d]; | |
902 fl.translate_axis (y2 - d * blot / 2, Y_AXIS); | |
903 fl.translate_axis (stem_width / 2, X_AXIS); | |
904 } | |
905 return fl; | |
906 } | 807 } |
907 | 808 |
908 /* | 809 /* |
909 move the stem to right of the notehead if it is up. | 810 move the stem to right of the notehead if it is up. |
910 */ | 811 */ |
911 MAKE_SCHEME_CALLBACK (Stem, offset_callback, 1); | 812 MAKE_SCHEME_CALLBACK (Stem, offset_callback, 1); |
912 SCM | 813 SCM |
913 Stem::offset_callback (SCM smob) | 814 Stem::offset_callback (SCM smob) |
914 { | 815 { |
915 Grob *me = unsmob_grob (smob); | 816 Grob *me = unsmob_grob (smob); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1123 { | 1024 { |
1124 Grob *beam = unsmob_grob (stem->get_object ("beam")); | 1025 Grob *beam = unsmob_grob (stem->get_object ("beam")); |
1125 return beam && Beam::is_cross_staff (beam); | 1026 return beam && Beam::is_cross_staff (beam); |
1126 } | 1027 } |
1127 | 1028 |
1128 MAKE_SCHEME_CALLBACK (Stem, calc_cross_staff, 1) | 1029 MAKE_SCHEME_CALLBACK (Stem, calc_cross_staff, 1) |
1129 SCM | 1030 SCM |
1130 Stem::calc_cross_staff (SCM smob) | 1031 Stem::calc_cross_staff (SCM smob) |
1131 { | 1032 { |
1132 return scm_from_bool (is_cross_staff (unsmob_grob (smob))); | 1033 return scm_from_bool (is_cross_staff (unsmob_grob (smob))); |
1034 } | |
1035 | |
1036 Grob* | |
1037 Stem::flag (Grob *me) | |
1038 { | |
1039 return unsmob_grob (me->get_object ("flag")); | |
1133 } | 1040 } |
1134 | 1041 |
1135 /* FIXME: Too many properties */ | 1042 /* FIXME: Too many properties */ |
1136 ADD_INTERFACE (Stem, | 1043 ADD_INTERFACE (Stem, |
1137 "The stem represents the graphical stem. In addition, it" | 1044 "The stem represents the graphical stem. In addition, it" |
1138 " internally connects note heads, beams, and tremolos. Rests" | 1045 " internally connects note heads, beams, and tremolos. Rests" |
1139 " and whole notes have invisible stems.\n" | 1046 " and whole notes have invisible stems.\n" |
1140 "\n" | 1047 "\n" |
1141 "The following properties may be set in the @code{details}" | 1048 "The following properties may be set in the @code{details}" |
1142 " list.\n" | 1049 " list.\n" |
(...skipping 20 matching lines...) Expand all Loading... | |
1163 "avoid-note-head " | 1070 "avoid-note-head " |
1164 "beam " | 1071 "beam " |
1165 "beaming " | 1072 "beaming " |
1166 "beamlet-default-length " | 1073 "beamlet-default-length " |
1167 "beamlet-max-length-proportion " | 1074 "beamlet-max-length-proportion " |
1168 "default-direction " | 1075 "default-direction " |
1169 "details " | 1076 "details " |
1170 "direction " | 1077 "direction " |
1171 "duration-log " | 1078 "duration-log " |
1172 "flag " | 1079 "flag " |
1173 "flag-style " | |
1174 "french-beaming " | 1080 "french-beaming " |
1175 "length-fraction " | 1081 "length-fraction " |
1176 "max-beam-connect " | 1082 "max-beam-connect " |
1177 "neutral-direction " | 1083 "neutral-direction " |
1178 "no-stem-extend " | 1084 "no-stem-extend " |
1179 "note-heads " | 1085 "note-heads " |
1180 "positioning-done " | 1086 "positioning-done " |
1181 "rests " | 1087 "rests " |
1182 "stem-info " | 1088 "stem-info " |
1183 "stemlet-length " | 1089 "stemlet-length " |
1184 "stroke-style " | |
1185 "thickness " | 1090 "thickness " |
1186 "tremolo-flag " | 1091 "tremolo-flag " |
1187 ); | 1092 ); |
1188 | 1093 |
1189 /****************************************************************/ | 1094 /****************************************************************/ |
1190 | 1095 |
1191 Stem_info::Stem_info () | 1096 Stem_info::Stem_info () |
1192 { | 1097 { |
1193 ideal_y_ = shortest_y_ = 0; | 1098 ideal_y_ = shortest_y_ = 0; |
1194 dir_ = CENTER; | 1099 dir_ = CENTER; |
1195 } | 1100 } |
1196 | 1101 |
1197 void | 1102 void |
1198 Stem_info::scale (Real x) | 1103 Stem_info::scale (Real x) |
1199 { | 1104 { |
1200 ideal_y_ *= x; | 1105 ideal_y_ *= x; |
1201 shortest_y_ *= x; | 1106 shortest_y_ *= x; |
1202 } | 1107 } |
LEFT | RIGHT |