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