Ensure scripts inside chords obey manual directions.
[lilypond/mpolesky.git] / lily / beaming-pattern.cc
blob3659525f115eb91c6e2b86973876cb1889c53469
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "context.hh"
21 #include "beam-settings.hh"
22 #include "beaming-pattern.hh"
25 Represents a stem belonging to a beam. Sometimes (for example, if the stem
26 belongs to a rest and stemlets aren't used) the stem will be invisible.
28 The rhythmic_importance_ of an element tells us the significance of the
29 moment at which this element occurs. For example, an element that occurs at
30 a beat is more significant than one that doesn't. Smaller number are
31 more important. The rhythmic_importance_ is decided and filled in by
32 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
33 significance: it represents the start of a beat and therefore beams may
34 need to be subdivided.
36 Beam_rhythmic_element::Beam_rhythmic_element ()
38 start_moment_ = 0;
39 rhythmic_importance_ = 0;
40 beam_count_drul_[LEFT] = 0;
41 beam_count_drul_[RIGHT] = 0;
42 invisible_ = false;
46 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
48 start_moment_ = m;
49 rhythmic_importance_ = 0;
50 beam_count_drul_[LEFT] = i;
51 beam_count_drul_[RIGHT] = i;
52 invisible_ = inv;
55 void
56 Beam_rhythmic_element::de_grace ()
58 if (start_moment_.grace_part_)
60 start_moment_.main_part_ = start_moment_.grace_part_;
61 start_moment_.grace_part_ = 0;
65 int
66 Beam_rhythmic_element::count (Direction d) const
68 return beam_count_drul_[d];
72 Finds the appropriate direction for the flags at the given index that
73 hang below the neighbouring flags. If
74 the stem has no more flags than either of its neighbours, this returns
75 CENTER.
77 Direction
78 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
80 // The extremal stems shouldn't be messed with, so it's appropriate to
81 // return CENTER here also.
82 if (i == 0 || i == infos_.size () - 1)
83 return CENTER;
85 int count = infos_[i].count (LEFT); // Both directions should still be the same
86 int left_count = infos_[i-1].count (RIGHT);
87 int right_count = infos_[i+1].count (LEFT);
89 // If we are told to subdivide beams and we are next to a beat, point the
90 // beamlet away from the beat.
91 if (options.subdivide_beams_)
93 if (infos_[i].rhythmic_importance_ < 0)
94 return RIGHT;
95 else if (infos_[i+1].rhythmic_importance_ < 0)
96 return LEFT;
99 if (count <= left_count && count <= right_count)
100 return CENTER;
102 // Try to avoid sticking-out flags as much as possible by pointing my flags
103 // at the neighbour with the most flags.
104 else if (right_count > left_count)
105 return RIGHT;
106 else if (left_count > right_count)
107 return LEFT;
109 // If all else fails, point the beamlet away from the important moment.
110 return (infos_[i].rhythmic_importance_ <= infos_[i+1].rhythmic_importance_) ? RIGHT : LEFT;
113 void
114 Beaming_pattern::de_grace ()
116 for (vsize i = 0; i < infos_.size (); i ++)
118 infos_[i].de_grace ();
122 void
123 Beaming_pattern::beamify (Beaming_options const &options)
125 unbeam_invisible_stems ();
127 if (infos_.size () <= 1)
128 return;
130 if (infos_[0].start_moment_.grace_part_)
131 de_grace ();
133 if (infos_[0].start_moment_ < Moment (0))
134 for (vsize i = 0; i < infos_.size (); i++)
135 infos_[i].start_moment_ += options.measure_length_;
137 find_rhythmic_importance (options);
139 for (vsize i = 1; i < infos_.size () - 1; i++)
141 Direction non_flag_dir = other_dir (flag_direction (options, i));
142 if (non_flag_dir)
144 int importance = (non_flag_dir == LEFT)
145 ? infos_[i].rhythmic_importance_ : infos_[i+1].rhythmic_importance_;
146 int count = (importance < 0 && options.subdivide_beams_)
147 ? 1 : min (infos_[i].count (non_flag_dir),
148 infos_[i+non_flag_dir].count (-non_flag_dir));
150 infos_[i].beam_count_drul_[non_flag_dir] = count;
155 void
156 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
158 Moment measure_pos (0);
159 SCM grouping = options.grouping_;
160 vsize i = 0;
162 // Mark the importance of stems that start at a beat or a beat group.
163 while (i < infos_.size ())
165 // If a beat grouping is not specified, default to 2 beats per group.
166 int count = 2;
167 if (scm_is_pair (grouping))
169 count = scm_to_int (scm_car (grouping));
170 grouping = scm_cdr (grouping);
173 // Mark the start of this beat group
174 if (infos_[i].start_moment_ == measure_pos)
175 infos_[i].rhythmic_importance_ = -2;
177 // Mark the start of each beat up to the end of this beat group.
178 for (int beat = 1; beat <= count; beat++)
180 Moment next_measure_pos = measure_pos + options.beat_length_;
182 while (i < infos_.size () && infos_[i].start_moment_ < next_measure_pos)
184 Moment dt = infos_[i].start_moment_ - measure_pos;
186 // The rhythmic importance of a stem between beats depends on its fraction
187 // of a beat: those stems with a lower denominator are deemed more
188 // important.
189 // FIXME: This is not the right way to do things for tuplets. For example,
190 // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
191 // more important than 1/2.
192 if (infos_[i].rhythmic_importance_ >= 0)
193 infos_[i].rhythmic_importance_ = (dt / options.beat_length_).den ();
195 i++;
198 measure_pos = next_measure_pos;
199 if (i < infos_.size () && infos_[i].start_moment_ == measure_pos)
200 infos_[i].rhythmic_importance_ = -1;
207 Invisible stems should be treated as though they have the same number of
208 beams as their least-beamed neighbour. Here we go through the stems and
209 modify the invisible stems to satisfy this requirement.
211 void
212 Beaming_pattern::unbeam_invisible_stems ()
214 for (vsize i = 1; i < infos_.size (); i++)
215 if (infos_[i].invisible_)
217 int b = min (infos_[i].count (LEFT), infos_[i-1].count (LEFT));
218 infos_[i].beam_count_drul_[LEFT] = b;
219 infos_[i].beam_count_drul_[RIGHT] = b;
222 for (vsize i = infos_.size (); i--;)
223 if (infos_[i].invisible_)
225 int b = min (infos_[i].count (LEFT), infos_[i+1].count (LEFT));
226 infos_[i].beam_count_drul_[LEFT] = b;
227 infos_[i].beam_count_drul_[RIGHT] = b;
232 void
233 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
235 infos_.push_back (Beam_rhythmic_element (m, b, invisible));
238 Beaming_pattern::Beaming_pattern ()
243 Beaming_pattern::beamlet_count (int i, Direction d) const
245 return infos_.at (i).beam_count_drul_[d];
248 Moment
249 Beaming_pattern::start_moment (int i) const
251 return infos_.at (i).start_moment_;
254 Moment
255 Beaming_pattern::end_moment (int i) const
257 Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
258 beamlet_count (i, RIGHT)),
261 return infos_.at (i).start_moment_ + dur->get_length();
264 bool
265 Beaming_pattern::invisibility (int i) const
267 return infos_.at (i).invisible_;
271 Split a beamin pattern at index i and return a new
272 Beaming_pattern containing the removed elements
274 Beaming_pattern *
275 Beaming_pattern::split_pattern (int i)
277 Beaming_pattern* new_pattern=0;
278 int count;
280 new_pattern = new Beaming_pattern ();
281 for (vsize j=i+1; j<infos_.size (); j++)
283 count = max(beamlet_count (j, LEFT), beamlet_count(j, RIGHT));
284 new_pattern->add_stem (start_moment (j),
285 count,
286 invisibility (j));
288 for (vsize j=i+1; j<infos_.size (); )
289 infos_.pop_back ();
290 return (new_pattern);
293 void
294 Beaming_options::from_context (Context *context)
296 grouping_ = ly_beat_grouping (context->self_scm ());
297 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
298 beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
299 measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (4, 4));
302 Beaming_options::Beaming_options ()
304 grouping_ = SCM_EOL;
305 subdivide_beams_ = false;