]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-engraver.cc
70d2943c74a2bfe7d2fad7265f083c9e7d486ede
[lilypond.git] / lily / score-engraver.cc
1 /*
2   score-grav.cc -- implement Score_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "super-element.hh"
10 #include "line-of-score.hh"
11 #include "debug.hh"
12 #include "item.hh"
13 #include "score-engraver.hh"
14 #include "p-score.hh"
15 #include "musical-request.hh"
16 #include "score-column.hh"
17 #include "command-request.hh"
18 #include "paper-def.hh"
19
20
21
22 Score_engraver::Score_engraver()
23 {
24   break_penalty_i_ = 0;
25   scoreline_l_ =0;
26   command_column_l_ =0;
27   musical_column_l_ =0;
28   breaks_i_ =0;
29   pscore_p_ = 0;
30 }
31  
32 void
33 Score_engraver::prepare (Moment w)
34 {
35   Global_translator::prepare (w);
36   set_columns (new Score_column (w),  new Score_column (w));
37   
38   break_penalty_i_ = 0;
39   post_move_processing();
40 }
41
42 void
43 Score_engraver::finish()
44 {
45   if ((breaks_i_%8))
46     *mlog << "[" << breaks_i_ << "]" << flush;
47    
48   check_removal();
49   removal_processing();
50 }
51
52 /*
53   use start/finish?
54  */
55 void
56 Score_engraver::do_creation_processing ()
57 {
58   scoreline_l_ = pscore_p_->line_l_;
59   scoreline_l_->set_bounds(LEFT,command_column_l_);
60   command_column_l_->set_elt_property (breakable_scm_sym, SCM_BOOL_T);
61
62   Engraver_group_engraver::do_creation_processing();
63 }
64
65
66 void
67 Score_engraver::do_removal_processing()
68 {
69   Engraver_group_engraver::do_removal_processing();
70   scoreline_l_->set_bounds(RIGHT,command_column_l_);
71   command_column_l_->set_elt_property (breakable_scm_sym, SCM_BOOL_T);
72
73   typeset_all ();
74   set_columns (0,0);
75 }
76
77 void
78 Score_engraver::process()
79 {
80   process_requests();
81   do_announces();
82   pre_move_processing();
83   check_removal();
84 }
85
86 void
87 Score_engraver::announce_element (Score_element_info info)
88 {
89   announce_info_arr_.push (info);
90   info.origin_trans_l_arr_.push (this);
91
92   if (Spanner *s = dynamic_cast <Spanner *> (info.elem_l_))
93     pscore_p_->typeset_unbroken_spanner (s);
94   else if (Item *i = dynamic_cast<Item*> (info.elem_l_))
95     pscore_p_->typeset_element (i);
96 }
97
98 /* All elements are propagated to the top upon announcement. If
99    something was created during one run of
100    Engraver_group_engraver::do_announces, then
101    announce_info_arr_.size() will be nonzero again
102 */
103 /* junkme? Done by Engraver_group_engraver::do_announces ()?
104  */
105    
106 void
107 Score_engraver::do_announces()
108 {
109   while (announce_info_arr_.size()) 
110     Engraver_group_engraver::do_announces();
111 }
112
113
114 void
115 Score_engraver::typeset_element (Score_element *elem_p)
116 {
117   elem_p_arr_.push (elem_p);
118 }
119
120
121 void
122 Score_engraver::typeset_all()
123 {
124   for  (int i =0; i < elem_p_arr_.size(); i++) 
125     {
126       Score_element * elem_p = elem_p_arr_[i];
127       elem_p->add_processing ();
128       if (Spanner *s = dynamic_cast <Spanner *> (elem_p))
129         {
130             /*
131             do something sensible if spanner not 
132             spanned on 2 items.
133            */
134           Direction d = LEFT;
135           do {
136             if (!s->spanned_drul_[d])
137               {
138                 s->set_bounds(d, command_column_l_);
139                 ::warning (_f ("Unbound spanner `%s\'", classname(s)));
140               }
141           } while (flip(&d) != LEFT);
142         }
143       else 
144         {
145           Item *item_p = dynamic_cast <Item *> (elem_p);
146
147           if (!item_p->parent_l (X_AXIS))
148             {
149               bool br = (item_p->remove_elt_property (breakable_scm_sym) != SCM_BOOL_F);
150               if (br)
151                 command_column_l_->add_element(item_p);
152               else
153                 musical_column_l_->add_element(item_p);
154             }
155         }
156       if (!elem_p->dim_cache_[Y_AXIS]->parent_l_)
157         scoreline_l_->add_element (elem_p);
158     }
159   elem_p_arr_.clear();
160 }
161
162 void
163 Score_engraver::do_pre_move_processing()
164 {
165   if (break_penalty_i_ > Break_req::DISALLOW)
166     {
167       command_column_l_->set_elt_property (breakable_scm_sym, SCM_BOOL_T);
168       breaks_i_ ++;
169       if (! (breaks_i_%8))
170         *mlog << "[" << breaks_i_ << "]" << flush;
171     }
172   // this generates all items.
173   Engraver_group_engraver::do_pre_move_processing();
174   
175   typeset_all();
176 }
177
178 void
179 Score_engraver::set_columns (Score_column *new_command_l, 
180                              Score_column *new_musical_l)
181 {
182   if (command_column_l_ && command_column_l_->linked_b()) 
183     {
184       pscore_p_->add_column (command_column_l_);
185       scoreline_l_->add_column (command_column_l_);
186     }
187   else 
188     {
189       delete command_column_l_ ;
190       command_column_l_ =0;
191     }
192   if (new_command_l) 
193     command_column_l_ = new_command_l;
194
195   if (musical_column_l_ && musical_column_l_->linked_b()) 
196     {
197       pscore_p_->add_column (musical_column_l_);
198       scoreline_l_->add_column (musical_column_l_);      
199     }
200   else 
201     {
202       delete musical_column_l_;
203       musical_column_l_ = 0;
204     }
205   
206   if (new_musical_l) 
207     {
208       musical_column_l_ = new_musical_l;
209     }
210 }
211
212
213 Staff_info
214 Score_engraver::get_staff_info() const
215 {
216   Staff_info inf = Engraver_group_engraver::get_staff_info();
217
218   inf.command_l_ = command_column_l_;
219   inf.musical_l_ = musical_column_l_;
220   
221   return inf;
222 }
223
224
225 Music_output*
226 Score_engraver::get_output_p ()
227 {
228   Music_output * o = pscore_p_;
229   pscore_p_=0;
230   return o;
231 }
232
233 bool
234 Score_engraver::do_try_music (Music*r)
235 {
236   bool gotcha = Engraver_group_engraver::do_try_music (r);  
237
238   if (!gotcha)
239     {
240       /*
241         UGH! THIS IS NOT SYMMETRIC. CLEAN ME UP!
242        */
243       if (Break_req* b = dynamic_cast<Break_req *> (r))
244         {
245           gotcha = true;
246           if (b->penalty_i_ <= Break_req::DISALLOW)
247             break_penalty_i_ = b->penalty_i_;
248           else if (b->penalty_i_ >= Break_req::FORCE)
249             command_column_l_->break_penalty_i_ = b->penalty_i_;
250         }
251     }
252    return gotcha;
253 }
254
255 void
256 Score_engraver::forbid_breaks ()
257 {
258   break_penalty_i_ = Break_req::DISALLOW;
259 }
260
261 ADD_THIS_TRANSLATOR(Score_engraver);
262
263 void
264 Score_engraver::do_add_processing ()
265 {
266   Translator_group::do_add_processing ();
267   assert (dynamic_cast<Paper_def *> (output_def_l_));
268   assert (!daddy_trans_l_);
269   pscore_p_ = new Paper_score;
270   pscore_p_->paper_l_ = dynamic_cast<Paper_def*>(output_def_l_);
271 }