]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-info.cc
d66a452814a29523a866835aca1fef38a7d645ef
[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--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "beaming.hh"
11
12 Beaming_info::Beaming_info ()
13 {
14   start_mom_ = 0;
15   beams_i_drul_[LEFT] = 0;
16   beams_i_drul_[RIGHT] = 0;  
17 }
18
19 Beaming_info::Beaming_info (Moment m, int i)
20 {
21   start_mom_ = m;
22   beams_i_drul_[LEFT] = i;
23   beams_i_drul_[RIGHT] = i;  
24 }
25
26 const int infinity_i = INT_MAX; // guh.
27 const int at_beat = 1<<15;
28
29 int
30 Beaming_info_list::best_splitpoint_index (Moment &beat_length,bool subdivide) const
31 {
32   int minden = infinity_i;
33   int minidx = -1;
34   Moment beat_pos;
35
36   for (int i=1; i < infos_.size (); i++)
37     {
38       beat_pos = infos_[i].start_mom_ / beat_length;
39       int den = beat_pos.den ();
40       if (infos_[i].beams_i_drul_[LEFT] == infos_[i-1].beams_i_drul_[RIGHT] && !subdivide)
41         den *= 2;
42       if (den < minden)
43         {
44           minidx = i;
45           minden = den;
46         }
47     }
48
49   return minidx|(minden==1 && subdivide ? at_beat : 0);
50 }
51
52 int
53 Beaming_info_list::beam_extend_count (Direction d) const
54 {
55   if (infos_.size () == 1)
56     return infos_[0].beams_i_drul_[d];
57
58   Beaming_info thisbeam  = infos_.boundary (d, 0);
59   Beaming_info next  = infos_.boundary (d, 1);
60   
61   return thisbeam.beams_i_drul_[-d] <? next.beams_i_drul_[d];
62 }
63
64 void
65 Beaming_info_list::beamify (Moment &beat_length,bool subdivide)
66 {
67   if (infos_.size () <= 1)
68     return;
69       
70   Drul_array<Beaming_info_list> splits;
71   int m = best_splitpoint_index (beat_length,subdivide);
72   bool split = subdivide && (m & at_beat);  m = m & ~at_beat;
73   splits[LEFT].infos_ = infos_.slice (0,m);
74   splits[RIGHT].infos_ = infos_.slice (m, infos_.size ());
75
76   Direction d = LEFT;
77  
78   do
79     {
80       splits[d].beamify (beat_length,subdivide);
81     }
82   while (flip (&d) != LEFT);
83
84   int middle_beams = (split ? 1 :
85                       splits[RIGHT].beam_extend_count (LEFT) <?
86                       splits[LEFT].beam_extend_count (RIGHT));
87
88   do
89     {
90       if (splits[d].infos_.size () != 1)
91         {
92           splits[d].infos_.boundary (-d, 0).beams_i_drul_[-d] = middle_beams;
93         }
94     }
95   while (flip (&d) != LEFT);
96
97   infos_ = splits[LEFT].infos_;
98   infos_.concat (splits[RIGHT].infos_);
99 }
100
101 void
102 Beaming_info_list::add_stem (Moment m, int b)
103 {
104   infos_.push (Beaming_info (m, b));
105 }