]> git.donarmstrong.com Git - lilypond.git/blob - lily/p-score.cc
release: 1.0.2
[lilypond.git] / lily / p-score.cc
1 /*
2   p-score.cc -- implement Paper_score
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996,  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "main.hh"
10 #include "super-element.hh"
11 #include "debug.hh"
12 #include "lookup.hh"
13 #include "spanner.hh"
14 #include "paper-def.hh"
15 #include "line-of-score.hh"
16 #include "pcursor.hh"
17 #include "plist.hh"
18 #include "p-col.hh"
19 #include "p-score.hh"
20 #include "tex-stream.hh"
21 #include "p-col.hh"
22 #include "header.hh"
23 #include "word-wrap.hh"
24 #include "gourlay-breaking.hh"
25 #include "tex-outputter.hh"
26 #include "file-results.hh"
27 #include "misc.hh"
28
29 // sucking Cygnus egcs - w32
30 #include "list.tcc"
31 #include "cursor.tcc"
32
33 Paper_score::Paper_score ()
34 {
35   outputter_l_ =0;
36   super_elem_l_   = new Super_elem;
37   typeset_element (super_elem_l_);
38 }
39
40 Paper_score::~Paper_score ()
41 {
42   super_elem_l_->unlink_all ();
43   for (PCursor<Score_element*> i(elem_p_list_.top()); i.ok(); i++)
44     assert(!i->linked_b());
45 }
46
47 void
48 Paper_score::typeset_element (Score_element * elem_p)
49 {
50   elem_p_list_.bottom ().add (elem_p);
51   elem_p->pscore_l_ = this;
52
53   elem_p->add_processing ();
54 }
55
56 void
57 Paper_score::typeset_broken_spanner (Spanner*span_p)
58 {
59   typeset_element (span_p);
60 }
61
62
63 void
64 Paper_score::typeset_unbroken_spanner (Spanner*span_p)
65 {
66   span_p_list_.bottom ().add (span_p);
67   span_p->pscore_l_=this;
68
69   // do not init start/stop fields. These are for broken spans only.
70   span_p->add_processing ();
71 }
72
73
74 void
75 Paper_score::clean_cols ()
76 {
77   int rank_i = 0;
78   for (iter_top (col_p_list_,c); c.ok ();)
79     {
80       c->set_rank (rank_i++);
81       c++;
82     }
83 }
84
85 void
86 Paper_score::add_column (Paper_column *p)
87 {
88   col_p_list_.bottom ().add (p);
89   typeset_element(p);
90 }
91
92
93
94 void
95 Paper_score::print () const
96 {
97 #ifndef NPRINT
98   if (!check_debug)
99     return ;
100   DOUT << "Paper_score { ";
101   DOUT << "\n elements: ";
102   for (iter_top (elem_p_list_,cc); cc.ok (); cc++)
103     cc->print ();
104   DOUT << "\n unbroken spanners: ";
105   for (iter (span_p_list_.top (), i); i.ok  (); i++)
106     i->print ();
107
108   DOUT << "}\n";
109 #endif
110 }
111
112 PCursor<Paper_column *>
113 Paper_score::find_col (Paper_column const *c) const
114 {
115   Paper_column const *what = c;
116
117   return col_p_list_.find ((Paper_column*)what);
118 }
119
120
121 void
122 Paper_score::set_breaking (Array<Column_x_positions> const &breaking)
123 {
124   super_elem_l_->line_of_score_l_->set_breaking (breaking);
125   super_elem_l_->break_processing ();
126
127   for (iter (span_p_list_.top (),i); i.ok  ();)
128     {
129       Spanner *span_p = i.remove_p ();
130       if (span_p->broken_b ()
131           || !((Score_element*)span_p)->line_l ())
132         {
133           span_p->unlink ();
134 #if 0
135           int sz = span_p->class_size();
136           set_frobnify (span_p,sz);
137 #endif
138           delete span_p;
139         }
140       else 
141         {
142           typeset_broken_spanner (span_p);
143         }
144     }
145   for (iter (elem_p_list_.top (),i); i.ok  () ;)
146     {
147       Item *i_l =i->access_Item ();
148       if (i_l && !i_l->line_l ())
149         {
150           i_l->unlink ();
151           Score_element * item_p= i.remove_p ();
152 #if 0
153           int sz = item_p->class_size ();
154           set_frobnify (item_p, sz);
155 #endif
156           delete item_p;
157         }
158       else
159         i++;
160     }
161 }
162
163 void
164 Paper_score::calc_breaking ()
165 {
166   Break_algorithm *algorithm_p=0;
167   Array<Column_x_positions> sol;
168   bool try_wrap = ! paper_l_->get_var ("castingalgorithm");
169
170   if (!try_wrap)
171     {
172       algorithm_p = new Gourlay_breaking ;
173       algorithm_p->set_pscore (this);
174       sol = algorithm_p->solve ();
175       delete algorithm_p;
176       if (! sol.size ())
177         {
178           warning (_ ("Can't solve this casting problem exactly; revert to Word_wrap"));
179           try_wrap = true;
180         }
181     }
182   if  (try_wrap)
183     {
184       algorithm_p = new Word_wrap;
185       algorithm_p->set_pscore (this);
186       sol = algorithm_p->solve ();
187       delete algorithm_p;
188     }
189   set_breaking (sol);
190 }
191
192 void
193 Paper_score::process ()
194 {
195   clean_cols ();
196   print ();
197   *mlog << _ ("Preprocessing elements...") << " " << flush;
198   super_elem_l_->breakable_col_processing ();
199   super_elem_l_->pre_processing ();
200   
201   *mlog << '\n' << _ ("Calculating column positions...") << " " << flush;
202   super_elem_l_->space_processing ();
203   calc_breaking ();
204   print ();
205   *mlog << _ ("Postprocessing elements...") << " " << endl;
206   super_elem_l_->post_processing ();
207   tex_output ();
208 }
209
210
211 void
212 Paper_score::tex_output ()
213 {
214   // output
215   String base_outname = paper_l_->outfile_str_ ;
216   if (base_outname.empty_b ())
217     {
218       base_outname = default_outname_base_global;
219       int def = paper_l_->get_next_default_count ();
220       if (def)
221         {
222           base_outname += "-" + to_str (def);
223         }
224     }
225
226   String outname = base_outname;
227   if (outname != "-")
228      outname += ".tex";
229   target_str_global_array.push (outname);
230
231   *mlog << _f ("TeX output to %s...", 
232     outname == "-" ? String ("<stdout>") : outname ) << endl;
233
234   Tex_stream tex_out (outname);
235   Tex_outputter interfees (&tex_out);
236
237   outputter_l_ = &interfees;
238
239   if (header_global_p)
240     {
241       tex_out << header_global_p->TeX_string ();
242     }
243     
244   
245   tex_out << _ ("% outputting Score, defined at: ") << origin_str_ << '\n';
246
247   if (header_l_)
248     {
249       tex_out << header_l_->TeX_string();
250     }
251   tex_out << paper_l_->TeX_output_settings_str ();
252   
253
254   if (experimental_features_global_b)
255     tex_out << "\\turnOnExperimentalFeatures%\n";
256
257   tex_out << "\\turnOnPostScript%\n";
258   super_elem_l_->output_all ();
259   tex_out << "\n\\EndLilyPondOutput";
260   outputter_l_ = 0;
261 }
262
263 /** Get all breakable columns between l and r, (not counting l and r).  */
264 Link_array<Paper_column>
265 Paper_score::breakable_col_range (Paper_column*l, Paper_column*r) const
266 {
267   Link_array<Paper_column> ret;
268
269   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
270   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
271
272   /*
273     ugh! windows-suck-suck-suck.
274     */
275   while (PCursor<Paper_column*>::compare (start,stop) < 0)
276     {
277       if (start->breakable_b_)
278         ret.push (start);
279       start++;
280     }
281
282   return ret;
283 }
284
285
286 Link_array<Paper_column>
287 Paper_score::col_range (Paper_column*l, Paper_column*r) const
288 {
289   Link_array<Paper_column> ret;
290
291   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
292   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
293   ret.push (l);
294
295   /*
296     ugh! windows-suck-suck-suck.
297     */
298   while (PCursor<Paper_column*>::compare (start,stop) < 0)
299     ret.push (start++);
300   ret.push (r);
301   return ret;
302 }
303
304 Link_array<Item>
305 Paper_score::broken_col_range (Item const*l_item_l, Item const*r_item_l) const
306 {
307   Link_array<Item> ret;
308   Item const*l=l_item_l;
309   Item const*r=r_item_l;
310
311   while (! l->is_type_b(Paper_column::static_name ()))
312     l = l->axis_group_l_a_[X_AXIS]->access_Score_element ()->access_Item ();
313
314   while (! r->is_type_b(Paper_column::static_name ()))
315     r = r->axis_group_l_a_[X_AXIS]->access_Score_element ()->access_Item ();
316
317   PCursor<Paper_column*> start (l ? find_col ((Paper_column*)l)+1 : col_p_list_.top ());
318   PCursor<Paper_column*> stop (r ? find_col ((Paper_column*)r) : col_p_list_.bottom ());
319
320   /*
321     ugh! windows-suck-suck-suck.
322     */
323   while (PCursor<Paper_column*>::compare (start,stop) < 0)
324     {
325       if (start->breakable_b_ && !start->line_l_)
326         ret.push (start);
327       start++;
328     }
329
330   return ret;
331 }