]> git.donarmstrong.com Git - lilypond.git/blob - lily/score-grav.cc
8c31c827c7f5b8399dba99c9dbf4768617286165
[lilypond.git] / lily / score-grav.cc
1 /*
2   score-grav.cc -- implement Score_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include "super-elem.hh"
9 #include "scoreline.hh"
10 #include "debug.hh"
11 #include "score-elem.hh"
12 #include "bar.hh"               // needed for Bar::static_name
13 #include "staffline.hh"
14 #include "score-grav.hh"
15 #include "p-col.hh"
16 #include "p-score.hh"
17 #include "score.hh"
18 #include "musical-request.hh"
19 #include "score-column.hh"
20 #include "command-request.hh"
21
22
23 void
24 Score_engraver::set_score(Score *s)
25 {
26     Global_translator::set_score(s);
27     scoreline_l_ = s->pscore_p_->super_elem_l_->line_of_score_l_;
28 }
29
30 Score_engraver::Score_engraver()
31 {
32     disallow_break_b_ = false;
33     scoreline_l_ =0;
34     command_column_l_ =0;
35     musical_column_l_ =0;
36     breaks_i_ =0;
37 }
38
39  
40 void
41 Score_engraver::prepare(Moment w)
42 {
43     command_column_l_ = new Score_column(w);
44     musical_column_l_ = new Score_column(w);
45     
46     command_column_l_->musical_b_ = false;
47     musical_column_l_->musical_b_ = true;
48     
49     score_l_->pscore_p_->add(command_column_l_);
50     score_l_->pscore_p_->add(musical_column_l_);
51     disallow_break_b_ = false;
52     post_move_processing();
53 }
54
55 void
56 Score_engraver::finish()
57 {
58     if ( (breaks_i_%8))
59             *mlog << "[" << breaks_i_ << "]" << flush;
60    
61     check_removal();
62     do_removal_processing();
63 }
64
65 void
66 Score_engraver::do_creation_processing()
67 {
68     scoreline_l_->left_col_l_ = get_staff_info().command_pcol_l();
69     scoreline_l_->left_col_l_ ->set_breakable();
70     Engraver_group_engraver::do_creation_processing();
71 }
72
73 void
74 Score_engraver::do_removal_processing()
75 {
76     Engraver_group_engraver::do_removal_processing();
77     scoreline_l_->right_col_l_ = get_staff_info().command_pcol_l();
78     scoreline_l_->right_col_l_ ->set_breakable();
79     typeset_all();
80 }
81
82 void
83 Score_engraver::process()
84 {
85         process_requests();
86         do_announces();
87         pre_move_processing();
88         check_removal();
89 }
90
91 void
92 Score_engraver::announce_element(Score_elem_info info)
93 {
94     announce_info_arr_.push(info);
95     info.origin_grav_l_arr_.push(this);
96         
97 }
98 void
99 Score_engraver::do_announces()
100 {
101     /* All elements are propagated to the top upon announcement. If
102       something was created during one run of
103       Engraver_group_engraver::do_announces, then
104       announce_info_arr_.size() will be nonzero again
105
106       */
107     while (announce_info_arr_.size()) {
108         for (int i=0; i <announce_info_arr_.size(); i++)
109             /*
110               TODO
111
112               More subtle spacing
113              */
114             if (announce_info_arr_[i].req_l_) {
115                 Musical_req *m = announce_info_arr_[i].req_l_->musical();
116                 if (m && m->rhythmic()) {
117                     musical_column_l_->add_duration( m->duration());
118                 }
119             }
120         Engraver_group_engraver::do_announces();
121     }
122 }
123
124
125 void
126 Score_engraver::typeset_element(Score_elem *elem_p)
127 {
128     musical_item_p_arr_.push(elem_p);
129 }
130
131 void
132 Score_engraver::typeset_breakable_item(Item * nobreak_p)
133 {
134     if (nobreak_p) {
135         nobreak_item_p_arr_.push(nobreak_p);
136     }
137 }
138
139 void
140 Score_engraver::typeset_all()
141 {
142     PCol * c= get_staff_info().command_pcol_l();
143     PScore *ps_l = score_l_->pscore_p_;
144
145     for  (int i =0; i < nobreak_item_p_arr_.size(); i++) {
146         ps_l->typeset_item(nobreak_item_p_arr_[i], c, 0);
147         scoreline_l_->add_dependency(nobreak_item_p_arr_[i]);
148     }
149     nobreak_item_p_arr_.set_size(0);
150     
151     for (int i=0; i < musical_item_p_arr_.size(); i++) {
152         PCol* m = get_staff_info().musical_pcol_l();
153         Score_elem *elem_p = musical_item_p_arr_[i];
154
155         scoreline_l_->add(elem_p);
156         if (elem_p->spanner()) {
157             ps_l->typeset_unbroken_spanner(elem_p->spanner());
158         } else if (elem_p->item()) {
159             ps_l->typeset_item(elem_p->item(), m, 0);
160         } else
161             assert(false);
162     }
163     musical_item_p_arr_.set_size(0);
164 }
165
166
167 void
168 Score_engraver::do_pre_move_processing()
169 {
170     if ( !disallow_break_b_ ){ 
171         get_staff_info().command_pcol_l()->set_breakable();
172         breaks_i_ ++;
173         if ( ! (breaks_i_%8))
174             *mlog << "[" << breaks_i_ << "]" << flush;
175     }
176     // this generates all items.
177     Engraver_group_engraver::do_pre_move_processing();
178     
179     typeset_all();
180 }
181
182
183 Staff_info
184 Score_engraver::get_staff_info()const
185 {
186     Staff_info inf;
187
188     inf.command_l_ = command_column_l_;
189     inf.musical_l_ = musical_column_l_;
190     return inf;
191 }
192
193 Paper_def*
194 Score_engraver::paper()const
195 {
196     return score_l_->paper_p_;
197 }
198
199
200
201 bool
202 Score_engraver::do_try_request(Request*r)
203 {
204     bool gotcha = Engraver_group_engraver::do_try_request(r);  
205     if ( !gotcha && r->command() && r->command()->disallowbreak())
206             disallow_break_b_ = true;
207     return gotcha;
208 }
209
210 IMPLEMENT_IS_TYPE_B1(Score_engraver,Engraver_group_engraver);
211
212 ADD_THIS_ENGRAVER(Score_engraver);
213