]> git.donarmstrong.com Git - lilypond.git/blob - lily/beam-engraver.cc
release: 1.3.41
[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--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9 #include "engraver-group-engraver.hh"
10 #include "beam-engraver.hh"
11 #include "musical-request.hh"
12 #include "beam.hh"
13 #include "stem.hh"
14 #include "warn.hh"
15 #include "beaming.hh"
16 #include "score-engraver.hh"
17
18 Beam_engraver::Beam_engraver ()
19 {
20   beam_p_ = 0;
21   finished_beam_p_ =0;
22   finished_beam_info_p_=0;
23   beam_info_p_ =0;
24   reqs_drul_[LEFT] = reqs_drul_[RIGHT] =0;
25   prev_start_req_ =0;
26 }
27
28 bool
29 Beam_engraver::do_try_music (Music *m)
30 {
31   if (Span_req * c = dynamic_cast<Span_req*>(m))
32     {
33       if (c->span_type_str_ != "beam")
34         return false;
35       
36       Direction d =c->span_dir_;
37
38       if (d == STOP && !beam_p_)
39         {
40           m->warning (_ ("can't find start of beam"));
41           return false;
42         }
43       reqs_drul_[d ] = c;
44       return true;
45     }
46   return false;
47 }
48
49
50 void
51 Beam_engraver::do_process_music ()
52 {
53   if (reqs_drul_[STOP])
54     {
55       if (!beam_p_)
56         reqs_drul_[STOP]->warning (_("can't find start of beam"));
57       prev_start_req_ =0;
58       finished_beam_p_ = beam_p_;
59       finished_beam_info_p_ = beam_info_p_;
60
61       beam_info_p_ =0;
62       beam_p_ = 0;
63     }
64
65
66   if (beam_p_)
67     {
68       Score_engraver * e = 0;
69       Translator * t  =  daddy_grav_l ();
70       for (; !e && t;  t = t->daddy_trans_l_)
71         {
72           e = dynamic_cast<Score_engraver*> (t);
73         }
74       
75       if (!e)
76         programming_error ("No score engraver!");
77       else
78         e->forbid_breaks ();
79     }
80   
81   if (reqs_drul_[START])
82     {
83       if (beam_p_)
84         {
85           reqs_drul_[START]->warning (_ ("already have a beam"));
86           return;
87         }
88
89       prev_start_req_ = reqs_drul_[START];
90       beam_p_ = new Beam;
91
92       SCM smp = get_property ("measurePosition");
93       Moment mp =  (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
94
95       beam_start_location_ = mp;
96       beam_start_mom_ = now_mom();
97       beam_info_p_ = new Beaming_info_list;
98       
99       
100       /* urg, must copy to Auto_beam_engraver too */
101  
102       announce_element (Score_element_info (beam_p_, reqs_drul_[START]));
103     }
104 }
105
106 void
107 Beam_engraver::typeset_beam ()
108 {
109   if (finished_beam_p_)
110     {
111       finished_beam_info_p_->beamify ();
112       
113       finished_beam_p_->set_beaming (finished_beam_info_p_);
114       typeset_element (finished_beam_p_);
115       delete finished_beam_info_p_;
116       finished_beam_info_p_ =0;
117       finished_beam_p_ = 0;
118     
119       reqs_drul_[STOP] = 0;
120     }
121 }
122
123 void
124 Beam_engraver::do_post_move_processing ()
125 {
126   reqs_drul_ [START] =0;
127 }
128
129 void
130 Beam_engraver::do_pre_move_processing ()
131 {
132   typeset_beam ();
133 }
134
135 void
136 Beam_engraver::do_removal_processing ()
137 {
138   typeset_beam ();
139   if (beam_p_)
140     {
141       prev_start_req_->warning (_ ("unterminated beam"));
142       finished_beam_p_ = beam_p_;
143       finished_beam_info_p_ = beam_info_p_;
144       typeset_beam ();
145     }
146 }
147
148 void
149 Beam_engraver::acknowledge_element (Score_element_info info)
150 {
151   if (beam_p_)
152     {
153       Stem* stem_l = dynamic_cast<Stem *> (info.elem_l_);
154       if (!stem_l || stem_l->beam_l ())
155         return;
156
157
158       bool stem_grace = stem_l->get_elt_property ("grace") == SCM_BOOL_T;
159
160       SCM wg =get_property ("weAreGraceContext");
161       bool wgb= to_boolean (wg);
162
163       if (wgb!= stem_grace)
164         return;
165
166       Rhythmic_req *rhythmic_req = dynamic_cast <Rhythmic_req *> (info.req_l_);
167       if (!rhythmic_req)
168         {
169           String s = _ ("stem must have Rhythmic structure");
170           if (info.req_l_)
171             info.req_l_->warning (s);
172           else
173             ::warning (s);
174           
175           return;
176         }
177       
178       if (rhythmic_req->duration_.durlog_i_<= 2)
179         {
180           rhythmic_req->warning (_ ("stem doesn't fit in beam"));
181           prev_start_req_->warning (_ ("beam was started here"));
182           /*
183             don't return, since
184
185             [r4 c8] can just as well be modern notation.
186            */
187         }
188
189       stem_l->set_elt_property ("duration-log",
190                                 gh_int2scm (rhythmic_req->duration_.durlog_i_));
191       Moment stem_location = now_mom () - beam_start_mom_ + beam_start_location_;
192       beam_info_p_->add_stem (stem_location,
193                               (rhythmic_req->duration_.durlog_i_ - 2) >? 1);
194       beam_p_->add_stem (stem_l);
195     }
196 }
197
198
199
200 ADD_THIS_TRANSLATOR(Beam_engraver);
201