]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-info.cc
* flower/include/std-string.hh:
[lilypond.git] / lily / beaming-info.cc
1 /*
2   beaming-info.cc -- implement Beaming_info, Beaming_info_list
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "beaming.hh"
10
11 Beaming_info::Beaming_info ()
12 {
13   start_mom_ = 0;
14   beams_i_drul_[LEFT] = 0;
15   beams_i_drul_[RIGHT] = 0;
16 }
17
18 Beaming_info::Beaming_info (Moment m, int i)
19 {
20   start_mom_ = m;
21   beams_i_drul_[LEFT] = i;
22   beams_i_drul_[RIGHT] = i;
23 }
24
25 const int at_beat = 1 << 15;
26
27 int
28 Beaming_info_list::best_splitpoint_index (Moment &beat_length, bool subdivide) const
29 {
30   int minden = INT_MAX;
31   int minidx = -1;
32   Moment beat_pos;
33
34   for (vsize i = 1; i < infos_.size (); i++)
35     {
36       beat_pos = infos_[i].start_mom_ / beat_length;
37       int den = beat_pos.den ();
38       if (infos_[i].beams_i_drul_[LEFT] == infos_[i - 1].beams_i_drul_[RIGHT] && !subdivide)
39         den *= 2;
40       if (den < minden)
41         {
42           minidx = i;
43           minden = den;
44         }
45     }
46
47   return minidx | (minden == 1 && subdivide ? at_beat : 0);
48 }
49
50 int
51 Beaming_info_list::beam_extend_count (Direction d) const
52 {
53   if (infos_.size () == 1)
54     return infos_[0].beams_i_drul_[d];
55
56   Beaming_info thisbeam = boundary (infos_, d, 0);
57   Beaming_info next = boundary (infos_, d, 1);
58
59   return min (thisbeam.beams_i_drul_[-d], next.beams_i_drul_[d]);
60 }
61
62 void
63 Beaming_info_list::beamify (Moment &beat_length, bool subdivide)
64 {
65   if (infos_.size () <= 1)
66     return;
67
68   Drul_array<Beaming_info_list> splits;
69   int m = best_splitpoint_index (beat_length, subdivide);
70   bool split = subdivide && (m & at_beat); m = m & ~at_beat;
71   splits[LEFT].infos_ = vector<Beaming_info> (infos_.begin (),
72                                                    infos_.begin () + m);
73   splits[RIGHT].infos_ = vector<Beaming_info> (infos_.begin () + m,
74                                                     infos_.end ());
75
76   Direction d = LEFT;
77
78   do
79     splits[d].beamify (beat_length, subdivide);
80   while (flip (&d) != LEFT);
81
82   int middle_beams = (split ? 1
83                       : min (splits[RIGHT].beam_extend_count (LEFT),
84                              splits[LEFT].beam_extend_count (RIGHT)));
85
86   do
87     {
88       if (splits[d].infos_.size () != 1)
89         boundary (splits[d].infos_, -d, 0).beams_i_drul_[-d] = middle_beams;
90     }
91   while (flip (&d) != LEFT);
92
93   infos_ = splits[LEFT].infos_;
94   infos_.insert (infos_.end (), splits[RIGHT].infos_.begin (), splits[RIGHT].infos_.end ());
95
96   clip_edges ();
97 }
98
99 void
100 Beaming_info_list::add_stem (Moment m, int b)
101 {
102   infos_.push_back (Beaming_info (m, b));
103 }
104
105 void
106 Beaming_info_list::clip_edges ()
107 {
108   if (infos_.size ())
109     {
110       infos_[0].beams_i_drul_[LEFT] = 0;
111       infos_.back ().beams_i_drul_[RIGHT] = 0;
112     }
113 }