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