]> git.donarmstrong.com Git - lilypond.git/blob - lily/p-score.cc
release: 0.1.27
[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     outname = default_out_str_+ ".tex";
196
197   *mlog << _("TeX output to ") <<  outname << " ...\n";
198
199   Tex_stream tex_out (outname);
200   Tex_outputter interfees (&tex_out);
201
202   outputter_l_ = &interfees;
203
204   tex_out << _("% outputting Score, defined at: ") << origin_str_ << "\n";
205   if (header_l_)
206     {
207       tex_out << header_l_->TeX_string();
208     }
209
210   tex_out << "\n "<<  paper_l_->lookup_l ()->texsetting << "%(Tex id)\n";
211   if (experimental_features_global_b)
212     tex_out << "\\turnOnExperimentalFeatures%\n";
213   super_elem_l_->output_all ();
214   tex_out << "\n\\EndLilyPondOutput";
215   outputter_l_ = 0;
216 }
217
218 /** Get all breakable columns between l and r, (not counting l and r).  */
219 Link_array<Paper_column>
220 Paper_score::breakable_col_range (Paper_column*l,Paper_column*r) const
221 {
222   Link_array<Paper_column> ret;
223
224   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
225   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
226
227   /*
228     ugh! windows-suck-suck-suck.
229     */
230   while (PCursor<Paper_column*>::compare (start,stop) < 0)
231     {
232       if (start->breakable_b_)
233         ret.push (start);
234       start++;
235     }
236
237   return ret;
238 }
239 Link_array<Paper_column>
240 Paper_score::col_range (Paper_column*l, Paper_column*r) const
241 {
242   Link_array<Paper_column> ret;
243
244   PCursor<Paper_column*> start (l ? find_col (l)+1 : col_p_list_.top ());
245   PCursor<Paper_column*> stop (r ? find_col (r) : col_p_list_.bottom ());
246   ret.push (l);
247
248   /*
249     ugh! windows-suck-suck-suck.
250     */
251   while (PCursor<Paper_column*>::compare (start,stop) < 0)
252     ret.push (start++);
253   ret.push (r);
254   return ret;
255 }
256
257 Link_array<Item>
258 Paper_score::broken_col_range (Item const*l_item_l, Item const*r_item_l) const
259 {
260   Link_array<Item> ret;
261   Item const*l=l_item_l;
262   Item const*r=r_item_l;
263
264   while (! l->is_type_b(Paper_column::static_name ()))
265     l = l->axis_group_l_a_[X_AXIS]->item ();
266
267   while (! r->is_type_b(Paper_column::static_name ()))
268     r = r->axis_group_l_a_[X_AXIS]->item ();
269
270   PCursor<Paper_column*> start (l ? find_col ((Paper_column*)l)+1 : col_p_list_.top ());
271   PCursor<Paper_column*> stop (r ? find_col ((Paper_column*)r) : col_p_list_.bottom ());
272
273   /*
274     ugh! windows-suck-suck-suck.
275     */
276   while (PCursor<Paper_column*>::compare (start,stop) < 0)
277     {
278       if (start->breakable_b_ && !start->line_l_)
279         ret.push (start);
280       start++;
281     }
282
283   return ret;
284 }