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