]> git.donarmstrong.com Git - lilypond.git/blob - lily/staff-column.cc
release: 0.0.64
[lilypond.git] / lily / staff-column.cc
1 /*
2   staff-column.cc -- implement Staff_column
3
4   source file of the LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include "proto.hh"
9 #include "plist.hh"
10 #include "staff.hh"
11 #include "voice.hh"
12 #include "time-description.hh"
13 #include "score-column.hh"
14 #include "staff-column.hh"
15 #include "command-request.hh"
16 #include "musical-request.hh"
17 #include "interval.hh"
18 #include "p-score.hh"
19 #include "item.hh"
20 #include "p-col.hh"
21 #include "request-column.hh"
22 #include "grouping.hh"
23
24 void
25 Staff_column::OK() const
26 {
27 #ifndef NDEBUG
28     
29 #endif
30 }
31
32 Moment
33 Staff_column::when() const
34 {
35     return req_col_l_->when();
36 }
37
38 void
39 Staff_column::add_reqs(Array<Request*> req_l_arr)
40 {
41     for (int i=0; i < req_l_arr.size(); i++) {
42         Request * j = req_l_arr[i];
43         if (j->command()) {
44             Command_req * c_l = j->command();
45             if (c_l->timing()) {
46                 timing_req_l_arr_.push(j->command()->timing());
47             }
48             if (c_l->groupchange())
49                 creationreq_l_arr_.push(c_l);
50             else if (!c_l->barcheck() &&  !c_l->partial() &&
51                 !c_l->measuregrouping())
52                 setup_one_request(j);   
53         } else {
54             if (j->rhythmic()) {
55                 req_col_l_->musical_column_l_->add_duration(j->rhythmic()->duration());
56             }
57             if (j->musical()) {
58                 Musical_req*m = j->musical();
59                 if(m->skip())
60                     continue;
61             }
62             setup_one_request(j);
63         }
64     }
65 }
66
67 Staff_column::Staff_column()
68 {
69     staff_l_ = 0;
70 }
71
72
73
74
75 Staff_column::~Staff_column()
76 {
77 }
78
79 void
80 Staff_column::set_req_col(Request_column *col_l)
81 {
82     req_col_l_ = col_l;
83 }
84
85 void
86 Staff_column::setup_one_request(Request * j)
87 {
88     if (j->command()) // ugh
89         commandreq_l_arr_.push(j);
90     else if (j->musical())
91         musicalreq_l_arr_.push(j);
92 }
93
94 void
95 Staff_column::typeset_musical_item(Item*i)
96 {
97     assert(i);
98     Score_column * scorecolumn_l = req_col_l_->musical_column_l_;
99     scorecolumn_l->pcol_l_->pscore_l_->typeset_item(i, scorecolumn_l->pcol_l_,
100                                                         staff_l_->pstaff_l_);
101 }
102
103 /**
104   align items in #item_l_arr#,
105
106   @return the width of the items after aligning.
107  */
108 Interval
109 align_items(Array<Item*> item_l_arr)
110 {
111     Interval wid(0,0);
112     for  (int i =0; i < item_l_arr.size(); i++) {
113         Interval item_width= item_l_arr[i]->width();
114         if (item_width.empty_b()) {
115             item_width = Interval(0,0);
116         }
117         Real dx =wid.right - item_width.left;
118         item_width += dx;
119         item_l_arr[i]->translate(Offset(dx ,0));
120         wid.unite(item_width);
121     }
122     return wid;
123 }
124
125 void 
126 translate_items(Real x,  Array<Item*> item_l_arr)
127 {
128     for  (int i =0; i < item_l_arr.size(); i++) 
129         item_l_arr[i]->translate(Offset(x, 0));
130 }
131 /*
132   UGR
133   This still sux
134   */
135 void
136 Staff_column::typeset_breakable_items(Array<Item *> &pre_p_arr,
137                                       Array<Item *> &nobreak_p_arr,
138                                       Array<Item *> &post_p_arr)
139 {
140     Score_column * scol_l= req_col_l_->command_column_l_;
141     PCol * c= scol_l->pcol_l_;
142     PScore *ps_l=scol_l->pcol_l_->pscore_l_;
143     
144     if (!c->breakable_b()) {      
145         for  (int i =0; i < pre_p_arr.size(); i++)
146             delete pre_p_arr[i];
147         pre_p_arr.set_size(0);
148         for  (int i =0; i < post_p_arr.size(); i++)
149             delete post_p_arr[i];
150         post_p_arr.set_size(0);
151     }
152
153       
154     for  (int i =0; i < pre_p_arr.size(); i++) {
155         ps_l->typeset_item(pre_p_arr[i], c, staff_l_->pstaff_l_,0);
156     }
157     for  (int i =0; i < nobreak_p_arr.size(); i++) {
158         ps_l->typeset_item(nobreak_p_arr[i], c, staff_l_->pstaff_l_,1);
159     }
160     for  (int i =0; i < post_p_arr.size(); i++) {
161         ps_l->typeset_item(post_p_arr[i], c, staff_l_->pstaff_l_,2);
162     }
163
164     Interval pre_wid= align_items(pre_p_arr);
165     translate_items( -pre_wid.right, pre_p_arr);
166     align_items(nobreak_p_arr);
167     Interval post_wid =align_items(post_p_arr);
168     translate_items (-post_wid.left , post_p_arr);
169
170     pre_p_arr.set_size(0);
171     post_p_arr.set_size(0);
172     nobreak_p_arr.set_size(0);
173 }
174
175 Score_column*
176 Staff_column::command_column_l()
177 {
178     return req_col_l_->command_column_l_;
179 }
180
181 Score_column*
182 Staff_column::musical_column_l()
183 {
184     return req_col_l_->musical_column_l_;
185 }
186
187 void
188 Staff_column::update_time(Time_description &time_, 
189                     Rhythmic_grouping *default_grouping)
190 {
191     // first all meter changes
192     for (int i=0; i < timing_req_l_arr_.size(); i++) {
193         Timing_req * tr_l = timing_req_l_arr_[i];
194         if (tr_l->meterchange()) {
195             int b_i=tr_l->meterchange()->beats_i_;
196             int o_i = tr_l->meterchange()->one_beat_i_;
197             if (! time_.allow_meter_change_b() )
198                 tr_l->warning("Meter change not allowed here");
199             else{
200                 time_.set_meter(b_i, o_i);
201                 if (default_grouping)
202                     *default_grouping = 
203                     Rhythmic_grouping(MInterval(0,Moment(b_i, o_i)), b_i);
204             }
205         }
206     }
207     
208     // then do the rest
209     for (int i=0; i < timing_req_l_arr_.size(); i++) {
210         Timing_req * tr_l = timing_req_l_arr_[i];
211         if (tr_l->partial()) {
212             Moment m = tr_l->partial()->duration_;
213             String error = time_.try_set_partial_str(m);
214             if (error != "") {
215                 tr_l->warning(error);
216             } else 
217                 time_.setpartial(m);
218         } else if (tr_l->barcheck() && time_.whole_in_measure_) {
219             tr_l ->warning( "Barcheck failed");
220
221             time_.whole_in_measure_ = 0; // resync
222             time_.error_b_ = true;
223         } else if (tr_l->cadenza()) {
224             time_.set_cadenza(tr_l->cadenza()->on_b_);
225         } else if (tr_l->measuregrouping()) {
226             if (default_grouping)
227                 *default_grouping = parse_grouping(
228                     tr_l->measuregrouping()->beat_i_arr_,
229                     tr_l->measuregrouping()->elt_length_arr_);
230         }
231     }
232     time_.OK();
233 }   
234