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