Use scalar instead of embedded_scm for context mod overrides.
[lilypond/mpolesky.git] / lily / beaming-pattern.cc
blob5e6d29ca6816049d0005587be178c919294a43c3
1 /*
2 beaming-pattern.cc -- implement Beam_rhythmic_element, Beaming_pattern
4 A Beaming_pattern object takes a set of stems at given moments and calculates
5 the pattern of their beam. That is, it works out, for each stem, how many
6 beams should be connected to the right and left sides of that stem. In
7 calculating this, Beaming_pattern takes into account
8 - the rhythmic position of the stems
9 - the options that are defined in Beaming_options
11 source file of the GNU LilyPond music typesetter
13 (c) 1999--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
16 #include "context.hh"
17 #include "beam-settings.hh"
18 #include "beaming-pattern.hh"
21 Represents a stem belonging to a beam. Sometimes (for example, if the stem
22 belongs to a rest and stemlets aren't used) the stem will be invisible.
24 The rhythmic_importance_ of an element tells us the significance of the
25 moment at which this element occurs. For example, an element that occurs at
26 a beat is more significant than one that doesn't. Smaller number are
27 more important. The rhythmic_importance_ is decided and filled in by
28 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
29 significance: it represents the start of a beat and therefore beams may
30 need to be subdivided.
32 Beam_rhythmic_element::Beam_rhythmic_element ()
34 start_moment_ = 0;
35 rhythmic_importance_ = 0;
36 beam_count_drul_[LEFT] = 0;
37 beam_count_drul_[RIGHT] = 0;
38 invisible_ = false;
42 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
44 start_moment_ = m;
45 rhythmic_importance_ = 0;
46 beam_count_drul_[LEFT] = i;
47 beam_count_drul_[RIGHT] = i;
48 invisible_ = inv;
51 void
52 Beam_rhythmic_element::de_grace ()
54 if (start_moment_.grace_part_)
56 start_moment_.main_part_ = start_moment_.grace_part_;
57 start_moment_.grace_part_ = 0;
61 int
62 Beam_rhythmic_element::count (Direction d) const
64 return beam_count_drul_[d];
68 Finds the appropriate direction for the flags at the given index that
69 hang below the neighbouring flags. If
70 the stem has no more flags than either of its neighbours, this returns
71 CENTER.
73 Direction
74 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
76 // The extremal stems shouldn't be messed with, so it's appropriate to
77 // return CENTER here also.
78 if (i == 0 || i == infos_.size () - 1)
79 return CENTER;
81 int count = infos_[i].count (LEFT); // Both directions should still be the same
82 int left_count = infos_[i-1].count (RIGHT);
83 int right_count = infos_[i+1].count (LEFT);
85 // If we are told to subdivide beams and we are next to a beat, point the
86 // beamlet away from the beat.
87 if (options.subdivide_beams_)
89 if (infos_[i].rhythmic_importance_ < 0)
90 return RIGHT;
91 else if (infos_[i+1].rhythmic_importance_ < 0)
92 return LEFT;
95 if (count <= left_count && count <= right_count)
96 return CENTER;
98 // Try to avoid sticking-out flags as much as possible by pointing my flags
99 // at the neighbour with the most flags.
100 else if (right_count > left_count)
101 return RIGHT;
102 else if (left_count > right_count)
103 return LEFT;
105 // If all else fails, point the beamlet away from the important moment.
106 return (infos_[i].rhythmic_importance_ <= infos_[i+1].rhythmic_importance_) ? RIGHT : LEFT;
109 void
110 Beaming_pattern::de_grace ()
112 for (vsize i = 0; i < infos_.size (); i ++)
114 infos_[i].de_grace ();
118 void
119 Beaming_pattern::beamify (Beaming_options const &options)
121 unbeam_invisible_stems ();
123 if (infos_.size () <= 1)
124 return;
126 if (infos_[0].start_moment_.grace_part_)
127 de_grace ();
129 if (infos_[0].start_moment_ < Moment (0))
130 for (vsize i = 0; i < infos_.size (); i++)
131 infos_[i].start_moment_ += options.measure_length_;
133 find_rhythmic_importance (options);
135 for (vsize i = 1; i < infos_.size () - 1; i++)
137 Direction non_flag_dir = other_dir (flag_direction (options, i));
138 if (non_flag_dir)
140 int importance = (non_flag_dir == LEFT)
141 ? infos_[i].rhythmic_importance_ : infos_[i+1].rhythmic_importance_;
142 int count = (importance < 0 && options.subdivide_beams_)
143 ? 1 : min (infos_[i].count (non_flag_dir),
144 infos_[i+non_flag_dir].count (-non_flag_dir));
146 infos_[i].beam_count_drul_[non_flag_dir] = count;
151 void
152 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
154 Moment measure_pos (0);
155 SCM grouping = options.grouping_;
156 vsize i = 0;
158 // Mark the importance of stems that start at a beat or a beat group.
159 while (i < infos_.size ())
161 // If a beat grouping is not specified, default to 2 beats per group.
162 int count = 2;
163 if (scm_is_pair (grouping))
165 count = scm_to_int (scm_car (grouping));
166 grouping = scm_cdr (grouping);
169 // Mark the start of this beat group
170 if (infos_[i].start_moment_ == measure_pos)
171 infos_[i].rhythmic_importance_ = -2;
173 // Mark the start of each beat up to the end of this beat group.
174 for (int beat = 1; beat <= count; beat++)
176 Moment next_measure_pos = measure_pos + options.beat_length_;
178 while (i < infos_.size () && infos_[i].start_moment_ < next_measure_pos)
180 Moment dt = infos_[i].start_moment_ - measure_pos;
182 // The rhythmic importance of a stem between beats depends on its fraction
183 // of a beat: those stems with a lower denominator are deemed more
184 // important.
185 // FIXME: This is not the right way to do things for tuplets. For example,
186 // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
187 // more important than 1/2.
188 if (infos_[i].rhythmic_importance_ >= 0)
189 infos_[i].rhythmic_importance_ = (dt / options.beat_length_).den ();
191 i++;
194 measure_pos = next_measure_pos;
195 if (i < infos_.size () && infos_[i].start_moment_ == measure_pos)
196 infos_[i].rhythmic_importance_ = -1;
203 Invisible stems should be treated as though they have the same number of
204 beams as their least-beamed neighbour. Here we go through the stems and
205 modify the invisible stems to satisfy this requirement.
207 void
208 Beaming_pattern::unbeam_invisible_stems ()
210 for (vsize i = 1; i < infos_.size (); i++)
211 if (infos_[i].invisible_)
213 int b = min (infos_[i].count (LEFT), infos_[i-1].count (LEFT));
214 infos_[i].beam_count_drul_[LEFT] = b;
215 infos_[i].beam_count_drul_[RIGHT] = b;
218 for (vsize i = infos_.size (); i--;)
219 if (infos_[i].invisible_)
221 int b = min (infos_[i].count (LEFT), infos_[i+1].count (LEFT));
222 infos_[i].beam_count_drul_[LEFT] = b;
223 infos_[i].beam_count_drul_[RIGHT] = b;
228 void
229 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
231 infos_.push_back (Beam_rhythmic_element (m, b, invisible));
234 Beaming_pattern::Beaming_pattern ()
239 Beaming_pattern::beamlet_count (int i, Direction d) const
241 return infos_.at (i).beam_count_drul_[d];
244 void
245 Beaming_options::from_context (Context *context)
247 grouping_ = ly_beat_grouping (context->self_scm ());
248 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
249 beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
250 measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (4, 4));
253 Beaming_options::Beaming_options ()
255 grouping_ = SCM_EOL;
256 subdivide_beams_ = false;