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