Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / melody-spanner.cc
blob8a96a2feb7de7ec0b35c90f16a44dcca4ebae6fc
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "melody-spanner.hh"
22 #include "grob.hh"
23 #include "pointer-group-interface.hh"
26 TODO: this could be either item or spanner. For efficiency reasons,
27 let's take item for now.
32 Interpolate stem directions for neutral stems.
34 MAKE_SCHEME_CALLBACK (Melody_spanner, calc_neutral_stem_direction, 1);
35 SCM
36 Melody_spanner::calc_neutral_stem_direction (SCM smob)
38 Grob *stem = unsmob_grob (smob);
39 Grob *me = unsmob_grob (stem->get_object ("melody-spanner"));
40 if (!me || !me->is_live ())
41 return scm_from_int (DOWN);
43 extract_grob_set (me, "stems", stems);
45 vector<Direction> dirs;
46 for (vsize i = 0; i < stems.size (); i++)
47 dirs.push_back (to_dir (stems[i]->get_property ("default-direction")));
49 vsize last_nonneutral = VPOS;
50 vsize next_nonneutral = 0;
51 while (next_nonneutral != VPOS && next_nonneutral < dirs.size ()
52 && !dirs[next_nonneutral])
53 next_nonneutral++;
55 SCM retval = SCM_EOL;
56 while (last_nonneutral == VPOS || last_nonneutral + 1 < dirs.size ())
58 Direction d1 = CENTER;
59 Direction d2 = CENTER;
60 if (last_nonneutral != VPOS)
61 d1 = dirs[last_nonneutral];
62 if (next_nonneutral < dirs.size ())
63 d2 = dirs[next_nonneutral];
65 Direction total = CENTER;
66 if (d1 && d1 == d2)
67 total = d1;
68 else if (d1 && !d2)
69 total = d1;
70 else if (d2 && !d1)
71 total = d2;
72 else
73 total = to_dir (me->get_property ("neutral-direction"));
75 for (vsize i = last_nonneutral + 1; i < next_nonneutral; i++)
77 if (stems[i] == stem)
78 retval = scm_from_int (total);
79 else
80 stems[i]->set_property ("neutral-direction", scm_from_int (total));
83 last_nonneutral = next_nonneutral;
84 while (last_nonneutral < dirs.size ()
85 && dirs[last_nonneutral])
86 last_nonneutral++;
87 next_nonneutral = last_nonneutral;
88 last_nonneutral--;
90 while (next_nonneutral < dirs.size ()
91 && !dirs[next_nonneutral])
92 next_nonneutral++;
95 return retval;
98 void
99 Melody_spanner::add_stem (Grob *me, Grob *stem)
101 Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), stem);
102 stem->set_object ("melody-spanner", me->self_scm ());
103 stem->set_property ("neutral-direction", Melody_spanner::calc_neutral_stem_direction_proc);
106 ADD_INTERFACE (Melody_spanner,
107 "Context dependent typesetting decisions.",
109 /* properties */
110 "stems "
111 "neutral-direction "