]> git.donarmstrong.com Git - lilypond.git/blob - lily/p-score.cc
release: 1.0.3
[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           delete span_p;
135         }
136       else 
137         {
138           typeset_broken_spanner (span_p);
139         }
140     }
141   for (iter (elem_p_list_.top (),i); i.ok  () ;)
142     {
143       Item *i_l =i->access_Item ();
144       if (i_l && !i_l->line_l ())
145         {
146           i_l->unlink ();
147           Score_element * item_p= i.remove_p ();
148           delete item_p;
149         }
150       else
151         i++;
152     }
153 }
154
155 void
156 Paper_score::calc_breaking ()
157 {
158   Break_algorithm *algorithm_p=0;
159   Array<Column_x_positions> sol;
160   bool try_wrap = ! paper_l_->get_var ("castingalgorithm");
161
162   if (!try_wrap)
163     {
164       algorithm_p = new Gourlay_breaking ;
165       algorithm_p->set_pscore (this);
166       sol = algorithm_p->solve ();
167       delete algorithm_p;
168       if (! sol.size ())
169         {
170           warning (_ ("Can't solve this casting problem exactly; revert to Word_wrap"));
171           try_wrap = true;
172         }
173     }
174   if  (try_wrap)
175     {
176       algorithm_p = new Word_wrap;
177       algorithm_p->set_pscore (this);
178       sol = algorithm_p->solve ();
179       delete algorithm_p;
180     }
181   set_breaking (sol);
182 }
183
184 void
185 Paper_score::process ()
186 {
187   clean_cols ();
188   print ();
189   *mlog << _ ("Preprocessing elements...") << " " << flush;
190   super_elem_l_->breakable_col_processing ();
191   super_elem_l_->pre_processing ();
192   
193   *mlog << '\n' << _ ("Calculating column positions...") << " " << flush;
194   super_elem_l_->space_processing ();
195   calc_breaking ();
196   print ();
197   *mlog << _ ("Postprocessing elements...") << " " << endl;
198   super_elem_l_->post_processing ();
199   tex_output ();
200 }
201
202
203 void
204 Paper_score::tex_output ()
205 {
206   // output
207   String base_outname = paper_l_->outfile_str_ ;
208   if (base_outname.empty_b ())
209     {
210       base_outname = default_outname_base_global;
211       int def = paper_l_->get_next_default_count ();
212       if (def)
213         {
214           base_outname += "-" + to_str (def);
215         }
216     }
217
218   String outname = base_outname;
219   if (outname != "-")
220      outname += ".tex";
221   target_str_global_array.push (outname);
222
223   *mlog << _f ("TeX output to %s...", 
224     outname == "-" ? String ("<stdout>") : outname ) << endl;
225
226   Tex_stream tex_out (outname);
227   Tex_outputter interfees (&tex_out);
228
229   outputter_l_ = &interfees;
230
231   if (header_global_p)
232     {
233       tex_out << header_global_p->TeX_string ();
234     }
235     
236   
237   tex_out << _ ("% outputting Score, defined at: ") << origin_str_ << '\n';
238
239   if (header_l_)
240     {
241       tex_out << header_l_->TeX_string();
242     }
243   tex_out << paper_l_->TeX_output_settings_str ();
244   
245
246   if (experimental_features_global_b)
247     tex_out << "\\turnOnExperimentalFeatures%\n";
248
249   tex_out << "\\turnOnPostScript%\n";
250   super_elem_l_->output_all ();
251   tex_out << "\n\\EndLilyPondOutput";
252   outputter_l_ = 0;
253 }
254
255 /** Get all breakable columns between l and r, (not counting l and r).  */
256 Link_array<Paper_column>
257 Paper_score::breakable_col_range (Paper_column*l, Paper_column*r) const
258 {
259   Link_array<Paper_column> ret;
260
261   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
262   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
263
264   /*
265     ugh! windows-suck-suck-suck.
266     */
267   while (PCursor<Paper_column*>::compare (start,stop) < 0)
268     {
269       if (start->breakable_b_)
270         ret.push (start);
271       start++;
272     }
273
274   return ret;
275 }
276
277
278 Link_array<Paper_column>
279 Paper_score::col_range (Paper_column*l, Paper_column*r) const
280 {
281   Link_array<Paper_column> ret;
282
283   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
284   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
285   ret.push (l);
286
287   /*
288     ugh! windows-suck-suck-suck.
289     */
290   while (PCursor<Paper_column*>::compare (start,stop) < 0)
291     ret.push (start++);
292   ret.push (r);
293   return ret;
294 }
295
296 Link_array<Item>
297 Paper_score::broken_col_range (Item const*l_item_l, Item const*r_item_l) const
298 {
299   Link_array<Item> ret;
300   Item const*l=l_item_l;
301   Item const*r=r_item_l;
302
303   while (! l->is_type_b(Paper_column::static_name ()))
304     l = l->axis_group_l_a_[X_AXIS]->access_Score_element ()->access_Item ();
305
306   while (! r->is_type_b(Paper_column::static_name ()))
307     r = r->axis_group_l_a_[X_AXIS]->access_Score_element ()->access_Item ();
308
309   PCursor<Paper_column*> start (l ? find_col ((Paper_column*)l)+1 : col_p_list_.top ());
310   PCursor<Paper_column*> stop (r ? find_col ((Paper_column*)r) : col_p_list_.bottom ());
311
312   /*
313     ugh! windows-suck-suck-suck.
314     */
315   while (PCursor<Paper_column*>::compare (start,stop) < 0)
316     {
317       if (start->breakable_b_ && !start->line_l_)
318         ret.push (start);
319       start++;
320     }
321
322   return ret;
323 }