]> git.donarmstrong.com Git - lilypond.git/blob - lily/melody-spanner.cc
* lily/beam.cc (calc_direction): use default-direction
[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 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
30   extract_grob_set (me, "stems", stems);
31
32   Array<Direction> dirs;
33   for (int i = 0; i < stems.size (); i++)
34     {
35       dirs.push (to_dir (stems[i]->get_property ("default-direction")));
36     }
37
38   int last_nonneutral = -1;
39   int next_nonneutral = 0;
40   while (next_nonneutral < dirs.size() &&  !dirs[next_nonneutral])
41     next_nonneutral ++;
42
43   while (last_nonneutral < dirs.size () - 1) 
44     {
45       Direction d1 = CENTER;
46       Direction d2 = CENTER;
47       if (last_nonneutral >= 0)
48         d1 = dirs[last_nonneutral];
49       if (next_nonneutral < dirs.size ())
50         d2 = dirs[next_nonneutral];
51
52       Direction total = CENTER;
53       if (d1 && d1 == d2)
54         total = d1;
55       else if (d1 && !d2)
56         total = d1;
57       else if (d2 && !d1)
58         total = d2;
59       else
60         total = to_dir (me->get_property ("neutral-direction"));
61       
62       for (int i = last_nonneutral + 1; i <  next_nonneutral; i++)
63         stems[i]->set_property ("neutral-direction", scm_from_int (total));
64
65
66       last_nonneutral = next_nonneutral;
67       while (last_nonneutral < dirs.size ()
68              && dirs[last_nonneutral])
69         last_nonneutral ++;
70       next_nonneutral = last_nonneutral;
71       last_nonneutral --;
72
73       while (next_nonneutral < dirs.size ()
74              && !dirs[next_nonneutral])
75         next_nonneutral ++;
76     }
77
78   me->suicide ();
79   return SCM_UNSPECIFIED;
80 }
81
82 void
83 Melody_spanner::add_stem (Grob *me, Grob *stem)
84 {
85   Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), stem);
86   stem->set_object ("melody-spanner", me->self_scm ());
87   stem->set_property ("neutral-direction", Melody_spanner::calc_neutral_stem_direction_proc);
88 }
89
90 ADD_INTERFACE (Melody_spanner, "melody-spanner-interface",
91                "Context dependent typesetting decisions.",
92
93                "stems "
94                "neutral-direction ");
95
96