]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-info.cc
417a20372c193de23bda8312f61b27930d7f9a94
[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_moment_ = 0;
14   beam_count_drul_[LEFT] = 0;
15   beam_count_drul_[RIGHT] = 0;
16 }
17
18 Beaming_info::Beaming_info (Moment m, int i)
19 {
20   start_moment_ = m;
21   beam_count_drul_[LEFT] = i;
22   beam_count_drul_[RIGHT] = i;
23 }
24
25 const int at_beat = 1 << 15;    //  WTF is this.
26
27 int
28 Beaming_info_list::best_splitpoint_index (Moment &beat_length,
29                                           bool subdivide) const
30 {
31   int min_denominator = INT_MAX;
32   int min_index = -1;
33   Moment beat_pos;
34
35   for (vsize i = 1; i < infos_.size (); i++)
36     {
37       beat_pos = infos_[i].start_moment_ / beat_length;
38       int den = beat_pos.den ();
39       if (infos_[i].beam_count_drul_[LEFT] == infos_[i - 1].beam_count_drul_[RIGHT]
40           && !subdivide)
41         den *= 2;
42       
43       if (den < min_denominator)
44         {
45           min_index = i;
46           min_denominator = den;
47         }
48     }
49
50   return min_index | (min_denominator == 1 && subdivide ? at_beat : 0);
51 }
52
53 int
54 Beaming_info_list::beam_extend_count (Direction d) const
55 {
56   if (infos_.size () == 1)
57     return infos_[0].beam_count_drul_[d];
58
59   Beaming_info thisbeam = boundary (infos_, d, 0);
60   Beaming_info next = boundary (infos_, d, 1);
61
62   return min (thisbeam.beam_count_drul_[-d], next.beam_count_drul_[d]);
63 }
64
65 void
66 Beaming_info_list::beamify (Moment &beat_length, bool subdivide)
67 {
68   if (infos_.size () <= 1)
69     return;
70
71   Drul_array<Beaming_info_list> splits;
72
73   int m = best_splitpoint_index (beat_length, subdivide);
74   bool split = subdivide && (m & at_beat);
75   m = m & ~at_beat;
76
77   splits[LEFT].infos_ = vector<Beaming_info> (infos_.begin (),
78                                               infos_.begin () + m);
79   splits[RIGHT].infos_ = vector<Beaming_info> (infos_.begin () + m,
80                                                infos_.end ());
81
82   Direction d = LEFT;
83
84   do
85     {
86       splits[d].beamify (beat_length, subdivide);
87     }
88   while (flip (&d) != LEFT);
89
90   int middle_beams = (split ? 1
91                       : min (splits[RIGHT].beam_extend_count (LEFT),
92                              splits[LEFT].beam_extend_count (RIGHT)));
93
94   do
95     {
96       if (splits[d].infos_.size () != 1)
97         boundary (splits[d].infos_, -d, 0).beam_count_drul_[-d] = middle_beams;
98     }
99   while (flip (&d) != LEFT);
100
101   infos_ = splits[LEFT].infos_;
102   infos_.insert (infos_.end (),
103                  splits[RIGHT].infos_.begin (),
104                  splits[RIGHT].infos_.end ());
105
106   clip_edges ();
107 }
108
109 void
110 Beaming_info_list::add_stem (Moment m, int b)
111 {
112   infos_.push_back (Beaming_info (m, b));
113 }
114
115 void
116 Beaming_info_list::clip_edges ()
117 {
118   if (infos_.size ())
119     {
120       infos_[0].beam_count_drul_[LEFT] = 0;
121       infos_.back ().beam_count_drul_[RIGHT] = 0;
122     }
123 }