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