]> git.donarmstrong.com Git - lilypond.git/blob - score.cc
release: 0.0.6
[lilypond.git] / score.cc
1 #include "scommands.hh"
2 #include "tstream.hh"
3 #include "score.hh"
4 #include "sccol.hh"
5 #include "pscore.hh"
6 #include "staff.hh"
7 #include "debug.hh"
8 #include "paper.hh"
9
10 void
11 Score::set(Paperdef*p)
12 {
13     delete paper_;
14     paper_ = p;
15 }
16 void
17 Score::output(String s)
18 {
19     OK();
20     if (paper_->outfile=="")
21         paper_->outfile = s;
22     
23     *mlog << "output to " << paper_->outfile << "...\n";
24     Tex_stream the_output(paper_->outfile);    
25     pscore_->output(the_output);
26 }
27
28
29 void
30 Score::process()
31 {
32     *mlog << "Processing ...";
33     set(commands_->parse(last()));
34     commands_->print();
35     
36     if (!paper_)
37         paper_ = new Paperdef;
38     
39     commands_->clean(last());
40     
41     /// distribute commands to disciples
42     distribute_commands();
43     
44     pscore_ = new PScore(paper_);
45     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
46         sc->set_output(pscore_);
47         sc->process();
48     }
49
50     // do this after processing, staffs first have to generate PCols.
51     do_pcols();
52     calc_idealspacing();
53     clean_cols();
54     OK();
55     //    print();
56     *mlog << "Calculating ... ";
57     pscore_->calc_breaking();
58     // TODO: calculate vertical structs
59     // TODO: calculate mixed structs.
60     *mlog << "\n";
61 }
62
63 // remove empty cols with no spacing attached.
64 /* should rethink ownership of cols
65     */
66 void
67 Score::clean_cols()
68 {    
69     for (PCursor<Staff * > sc(staffs_); sc.ok(); sc++)
70         sc->clean_cols();
71     
72     for (PCursor<Score_column*> c(cols_); c.ok(); ) {
73         if (!c->pcol->used) {
74             mtor << "removing : ";
75             c->print();
76             c.del();
77         } else
78             c++;
79     }
80     
81     pscore_->clean_cols();
82 }
83 /* this sux.  We should have Score_column create the appropriate PCol.
84     Unfortunately, PCols don't know about their position.    
85     */
86 // todo
87 PCursor<Score_column*>
88 Score::create_cols(Real w)
89 {
90     Score_column* c1 = new Score_column(w);
91     Score_column* c2 = new Score_column(w);
92     
93     c1->musical = false;
94     c2->musical = true;
95     
96     PCursor<Score_column*> scc(cols_);
97
98     for (; scc.ok(); scc++) {
99         assert(scc->when != w);
100         if (scc->when > w)
101             break;
102     }
103
104     if (!scc.ok()) {
105         cols_.bottom().add(c1);
106         cols_.bottom().add(c2);
107         scc = cols_.bottom();
108         scc --;
109     } else {
110         scc.insert(c1);
111         scc.insert(c2);
112         scc -= 2;
113     }
114     return scc;
115 }
116
117 Score_column*
118 Score::find_col(Real w,bool mus)
119 {
120     PCursor<Score_column*> scc(cols_);
121     for (; scc.ok(); scc++) {
122         if (scc->when == w && scc->musical == mus)
123             return scc;
124         if (scc->when > w)
125             break;
126     }
127     scc = create_cols(w);
128     if (mus)
129         scc++;
130     return scc;
131 }
132
133 void
134 Score::distribute_commands(void)
135 {
136     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
137         sc->add_commands(*commands_);
138     }
139 }
140 void
141 Score::add(Staff*s)
142 {
143     s->score_ = this;
144     staffs_.bottom().add(s);    
145 }
146
147
148 void
149 Score::do_pcols()
150 {
151     PCursor<Score_column*> sc(cols_);
152     for (; sc.ok(); sc++) {
153         pscore_->add(sc->pcol);
154     }
155 }
156 Real
157 Score::last() const
158 {    
159     Real l = 0;
160     for (PCursor<Staff*> stc(staffs_); stc.ok(); stc++) {
161         l = MAX(l, stc->last());
162     }
163     return l;
164 }
165
166 void
167 Score::OK() const
168 {
169 #ifndef NDEBUG
170     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
171         sc->OK();
172         assert(sc->score_ == this);
173     }
174     staffs_.OK();
175     cols_.OK();
176     for (PCursor<Score_column*> cc(cols_); cc.ok() && (cc+1).ok(); cc++) {
177         assert(cc->when <= (cc+1)->when);
178     }
179     commands_->OK();
180 #endif    
181 }
182
183
184 void
185 Score::print() const
186 {
187 #ifndef NPRINT
188     mtor << "score {\n"; 
189     for (PCursor<Staff*> sc(staffs_); sc.ok(); sc++) {
190         sc->print();
191     }
192     for (PCursor<Score_column*> sc(cols_); sc.ok(); sc++) {
193         sc->print();
194     }
195     commands_->print();
196     mtor << "}\n";
197 #endif
198 }
199
200 Score::Score()
201 {
202     pscore_=0;
203     paper_ = 0;
204     commands_ = new Score_commands;
205 }
206
207 Score::~Score()
208 {
209     delete pscore_;
210     delete commands_;
211     delete paper_;
212 }
213
214 void
215 Score::set(Score_commands*c)
216 {
217     delete commands_;
218     commands_ = c;
219 }