]> git.donarmstrong.com Git - lilypond.git/blob - lily/melody-spanner.cc
4d1cc67ae9a4368d12277867ae96dc3d41919384
[lilypond.git] / lily / melody-spanner.cc
1 /*
2   melody-spanner.cc -- implement Melody_spanner
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7
8 */
9
10 #include "melody-spanner.hh"
11 #include "grob.hh"
12 #include "pointer-group-interface.hh"
13
14 /*
15   TODO: this could be either item or spanner. For efficiency reasons,
16   let's take item for now.
17 */
18
19                  
20 /*
21   Interpolate stem directions for neutral stems.
22  */
23 MAKE_SCHEME_CALLBACK (Melody_spanner, calc_neutral_stem_direction, 1);
24 SCM
25 Melody_spanner::calc_neutral_stem_direction (SCM smob)
26 {
27   Grob *stem = unsmob_grob (smob);
28   Grob *me =  unsmob_grob (stem->get_object ("melody-spanner"));
29   if (!me || !me->is_live ())
30     return scm_from_int (DOWN);
31   
32   extract_grob_set (me, "stems", stems);
33
34   vector<Direction> dirs;
35   for (vsize i = 0; i < stems.size (); i++)
36     dirs.push_back (to_dir (stems[i]->get_property ("default-direction")));
37
38   vsize last_nonneutral = VPOS;
39   vsize next_nonneutral = 0;
40   while (next_nonneutral != VPOS && next_nonneutral < dirs.size ()
41          &&  !dirs[next_nonneutral])
42     next_nonneutral++;
43
44   SCM retval = SCM_EOL;
45   while (last_nonneutral == VPOS || last_nonneutral + 1 < dirs.size ()) 
46     {
47       Direction d1 = CENTER;
48       Direction d2 = CENTER;
49       if (last_nonneutral != VPOS)
50         d1 = dirs[last_nonneutral];
51       if (next_nonneutral < dirs.size ())
52         d2 = dirs[next_nonneutral];
53
54       Direction total = CENTER;
55       if (d1 && d1 == d2)
56         total = d1;
57       else if (d1 && !d2)
58         total = d1;
59       else if (d2 && !d1)
60         total = d2;
61       else
62         total = to_dir (me->get_property ("neutral-direction"));
63       
64       for (vsize i = last_nonneutral + 1; i <  next_nonneutral; i++)
65         {
66           if (stems[i] == stem)
67             retval = scm_from_int (total);
68           else
69             stems[i]->set_property ("neutral-direction", scm_from_int (total));
70         }
71
72       last_nonneutral = next_nonneutral;
73       while (last_nonneutral < dirs.size ()
74              && dirs[last_nonneutral])
75         last_nonneutral++;
76       next_nonneutral = last_nonneutral;
77       last_nonneutral--;
78
79       while (next_nonneutral < dirs.size ()
80              && !dirs[next_nonneutral])
81         next_nonneutral++;
82     }
83
84   return retval;
85 }
86
87 void
88 Melody_spanner::add_stem (Grob *me, Grob *stem)
89 {
90   Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), stem);
91   stem->set_object ("melody-spanner", me->self_scm ());
92   stem->set_property ("neutral-direction", Melody_spanner::calc_neutral_stem_direction_proc);
93 }
94
95 ADD_INTERFACE (Melody_spanner,
96                "Context dependent typesetting decisions.",
97
98                /* properties */
99                "stems "
100                "neutral-direction "
101                );
102
103