]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-engraver.cc
release: 1.1.24
[lilypond.git] / lily / beam-engraver.cc
1 /*   
2   beam-engraver.cc --  implement Beam_engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "beam-engraver.hh"
11 #include "musical-request.hh"
12 #include "beam.hh"
13 #include "grouping.hh"
14 #include "stem.hh"
15 #include "warn.hh"
16 #include "time-description.hh"
17
18 Beam_engraver::Beam_engraver ()
19 {
20   beam_p_ = 0;
21   finished_beam_p_ =0;
22   finished_grouping_p_ = 0;
23   grouping_p_ =0;
24   reqs_drul_[LEFT] = reqs_drul_[RIGHT] =0;
25 }
26
27 bool
28 Beam_engraver::do_try_music (Music *m)
29 {
30   if (Beam_req * c = dynamic_cast<Beam_req*>(m))
31     {
32       Direction d =c->spantype_;
33
34       if (d == STOP && !beam_p_)
35         {
36           m->warning (_ ("No Beam to end"));
37           return false;
38         }
39       reqs_drul_[d ] = c;
40       return true;
41     }
42   return false;
43 }
44
45
46 void
47 Beam_engraver::do_process_requests ()
48 {
49   if (reqs_drul_[STOP])
50     {
51       if (!beam_p_)
52         reqs_drul_[STOP]->warning (_("No beam to end"));
53       finished_beam_p_ = beam_p_;
54       finished_grouping_p_ = grouping_p_;
55
56       beam_p_ = 0;
57       grouping_p_ = 0;
58     }
59   
60   if (reqs_drul_[START])
61     {
62       if (beam_p_)
63         {
64           reqs_drul_[START]->warning (_ ("Already have a Beam"));
65           return;
66         }
67
68       beam_p_ = new Beam;
69       grouping_p_ = new Rhythmic_grouping;
70
71       Scalar prop = get_property ("beamslopedamping", 0);
72       if (prop.isnum_b ()) 
73         beam_p_->damping_i_ = prop;
74
75       prop = get_property ("beamquantisation", 0);
76       if (prop.isnum_b ()) 
77         beam_p_->quantisation_ = (Beam::Quantisation)(int)prop;
78  
79       // must set minVerticalAlign == maxVerticalAlign to get sane results
80       // see input/test/beam-interstaff.ly
81       prop = get_property ("minVerticalAlign", 0);
82       if (prop.isnum_b ())
83         beam_p_->vertical_align_drul_[MIN] = prop;
84
85       prop = get_property ("maxVerticalAlign", 0);
86       if (prop.isnum_b ())
87         beam_p_->vertical_align_drul_[MAX] = prop;
88
89       announce_element (Score_element_info (beam_p_, reqs_drul_[START]));
90     }
91 }
92
93 void
94 Beam_engraver::typeset_beam ()
95 {
96   if (finished_beam_p_)
97     {
98       Rhythmic_grouping const * rg_C = get_staff_info().rhythmic_C_;
99       rg_C->extend (finished_grouping_p_->interval());
100       finished_beam_p_->set_grouping (*rg_C, *finished_grouping_p_);
101       typeset_element (finished_beam_p_);
102       finished_beam_p_ = 0;
103     
104       delete finished_grouping_p_;
105       finished_grouping_p_= 0;
106     
107       reqs_drul_[STOP] = 0;
108     }
109 }
110
111 void
112 Beam_engraver::do_post_move_processing ()
113 {
114   reqs_drul_ [START] =0;
115 }
116
117 void
118 Beam_engraver::do_pre_move_processing ()
119 {
120   typeset_beam ();
121 }
122
123 void
124 Beam_engraver::do_removal_processing ()
125 {
126   typeset_beam ();
127   if (beam_p_)
128     {
129       warning (_ ("Unfinished beam"));
130       finished_beam_p_ = beam_p_;
131       finished_grouping_p_ = grouping_p_;
132       typeset_beam ();
133     }
134 }
135
136 void
137 Beam_engraver::acknowledge_element (Score_element_info info)
138 {
139     if (beam_p_)
140       {
141         Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
142         if (!stem_l)
143           return;
144
145
146         Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
147         if (!rhythmic_req)
148           {
149             String s = _ ("Stem must have Rhythmic structure.");
150             if (info.req_l_)
151               info.req_l_->warning (s);
152             else
153               ::warning (s);
154           
155             return;
156           }
157       
158
159         if (rhythmic_req->duration_.durlog_i_<= 2)
160           {
161             rhythmic_req->warning (_ ("stem doesn't fit in beam"));
162             reqs_drul_[LEFT]->warning (_ ("beam was started here"));
163             return;
164           }
165
166         /*
167           TODO: do something sensible if it doesn't fit in the beam.
168         */
169         Moment start = get_staff_info().time_C_->whole_in_measure_;
170
171         if (!grouping_p_->child_fit_b (start))
172           {
173             String s (_ ("please fix me") + ": " 
174                       + _f ("stem at %s doesn't fit in beam", now_moment ().str ()));
175
176             if (info.req_l_)
177               info.req_l_->warning(s);
178             else 
179               warning (s);
180           }
181         else
182           {
183             grouping_p_->add_child (start, rhythmic_req->duration ());
184             stem_l->flag_i_ = rhythmic_req->duration_.durlog_i_;
185             beam_p_->add_stem (stem_l);
186           }
187       }
188 }
189
190
191
192 ADD_THIS_TRANSLATOR(Beam_engraver);