]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-book.cc
(parse_symbol_list): Bugfix.
[lilypond.git] / lily / paper-book.cc
1 /*
2   paper-book.cc -- implement Paper_book
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2004--2005 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "paper-book.hh"
10
11 #include "main.hh"
12 #include "output-def.hh"
13 #include "paper-score.hh"
14 #include "paper-system.hh"
15 #include "text-interface.hh"
16 #include "warn.hh"
17
18 #include "ly-smobs.icc"
19
20 Paper_book::Paper_book ()
21 {
22   header_ = SCM_EOL;
23   header_0_ = SCM_EOL;
24   pages_ = SCM_BOOL_F;
25   scores_ = SCM_EOL;
26   performances_ = SCM_EOL;
27   systems_ = SCM_BOOL_F;
28
29   paper_ = 0;
30   smobify_self ();
31 }
32
33 Paper_book::~Paper_book ()
34 {
35 }
36
37 IMPLEMENT_DEFAULT_EQUAL_P (Paper_book);
38 IMPLEMENT_SMOBS (Paper_book);
39 IMPLEMENT_TYPE_P (Paper_book, "ly:paper-book?");
40
41 SCM
42 Paper_book::mark_smob (SCM smob)
43 {
44   Paper_book *b = (Paper_book *) SCM_CELL_WORD_1 (smob);
45   if (b->paper_)
46     scm_gc_mark (b->paper_->self_scm ());
47   scm_gc_mark (b->header_);
48   scm_gc_mark (b->header_0_);
49   scm_gc_mark (b->pages_);
50   scm_gc_mark (b->performances_);
51   scm_gc_mark (b->scores_);
52   return b->systems_;
53 }
54
55 int
56 Paper_book::print_smob (SCM smob, SCM port, scm_print_state*)
57 {
58   Paper_book *b = (Paper_book *) SCM_CELL_WORD_1 (smob);
59
60   scm_puts ("#<", port);
61   scm_puts (classname (b), port);
62   scm_puts (" ", port);
63   scm_puts (">", port);
64   return 1;
65 }
66
67 SCM
68 dump_fields ()
69 {
70   SCM fields = SCM_EOL;
71   for (int i = dump_header_fieldnames_global.size (); i--;)
72     fields
73       = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].to_str0 ()),
74                   fields);
75   return fields;
76 }
77
78 void
79 Paper_book::add_score (SCM s)
80 {
81   scores_ = scm_cons (s, scores_);
82 }
83
84 void
85 Paper_book::add_performance (SCM s)
86 {
87   performances_ = scm_cons (s, performances_);
88 }
89
90 void
91 Paper_book::output (SCM output_channel)
92 {
93   if (scores_ == SCM_EOL)
94     return;
95
96   /* Generate all stencils to trigger font loads.  */
97   pages ();
98
99   SCM scopes = SCM_EOL;
100   if (ly_is_module (header_))
101     scopes = scm_cons (header_, scopes);
102
103   String mod_nm = "scm framework-" + output_backend_global;
104
105   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
106   if (make_print)
107     {
108       SCM func = scm_c_module_lookup (mod, "output-framework");
109
110       func = scm_variable_ref (func);
111       scm_apply_0 (func, scm_list_n (output_channel,
112                                      self_scm (),
113                                      scopes,
114                                      dump_fields (),
115                                      SCM_UNDEFINED));
116     }
117
118   if (make_preview)
119     {
120       SCM func = scm_c_module_lookup (mod, "output-preview-framework");
121       func = scm_variable_ref (func);
122       scm_apply_0 (func, scm_list_n (output_channel,
123                                      self_scm (),
124                                      scopes,
125                                      dump_fields (),
126                                      SCM_UNDEFINED));
127     }
128 }
129
130 void
131 Paper_book::classic_output (SCM output)
132 {
133   /* Generate all stencils to trigger font loads.  */
134   systems ();
135
136   SCM scopes = SCM_EOL;
137   if (ly_is_module (header_))
138     scopes = scm_cons (header_, scopes);
139
140   if (ly_is_module (header_0_))
141     scopes = scm_cons (header_0_, scopes);
142
143   String format = output_backend_global;
144   String mod_nm = "scm framework-" + format;
145
146   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
147   SCM func = scm_c_module_lookup (mod, "output-classic-framework");
148
149   func = scm_variable_ref (func);
150   scm_apply_0 (func, scm_list_n (output,
151                                  self_scm (),
152                                  scopes,
153                                  dump_fields (),
154                                  SCM_UNDEFINED));
155
156   progress_indication ("\n");
157 }
158
159 /* TODO: resurrect more complex user-tweaks for titling?  */
160 Stencil
161 Paper_book::book_title ()
162 {
163   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("book-title"));
164   Stencil title;
165
166   SCM scopes = SCM_EOL;
167   if (ly_is_module (header_))
168     scopes = scm_cons (header_, scopes);
169
170   SCM tit = SCM_EOL;
171   if (ly_is_procedure (title_func))
172     tit = scm_call_2 (title_func,
173                       paper_->self_scm (),
174                       scopes);
175
176   if (unsmob_stencil (tit))
177     title = *unsmob_stencil (tit);
178
179   if (!title.is_empty ())
180     title.align_to (Y_AXIS, UP);
181
182   return title;
183 }
184
185 Stencil
186 Paper_book::score_title (SCM header)
187 {
188   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title"));
189
190   Stencil title;
191
192   SCM scopes = SCM_EOL;
193   if (ly_is_module (header_))
194     scopes = scm_cons (header_, scopes);
195
196   if (ly_is_module (header))
197     scopes = scm_cons (header, scopes);
198
199   SCM tit = SCM_EOL;
200   if (ly_is_procedure (title_func))
201     tit = scm_call_2 (title_func,
202                       paper_->self_scm (),
203                       scopes);
204
205   if (unsmob_stencil (tit))
206     title = *unsmob_stencil (tit);
207
208   if (!title.is_empty ())
209     title.align_to (Y_AXIS, UP);
210
211   return title;
212 }
213
214 void
215 set_system_penalty (Paper_system *ps, SCM header)
216 {
217   if (ly_is_module (header))
218     {
219       SCM force = ly_module_lookup (header, ly_symbol2scm ("breakbefore"));
220       if (SCM_VARIABLEP (force)
221           && scm_is_bool (SCM_VARIABLE_REF (force)))
222         {
223           ps->break_before_penalty_ = to_boolean (SCM_VARIABLE_REF (force))
224             ? -10000
225             : 10000;
226         }
227     }
228 }
229
230 void
231 Paper_book::add_score_title (SCM header)
232 {
233   Stencil title = score_title (header);
234   if (title.is_empty ())
235     title = score_title (header_);
236   if (!title.is_empty ())
237     {
238       Paper_system *ps = new Paper_system (title, true);
239       systems_ = scm_cons (ps->self_scm (), systems_);
240       ps->unprotect ();
241       set_system_penalty (ps, header);
242     }
243 }
244
245 SCM
246 Paper_book::systems ()
247 {
248   if (systems_ != SCM_BOOL_F)
249     return systems_;
250
251   systems_ = SCM_EOL;
252   Stencil title = book_title ();
253
254   if (!title.is_empty ())
255     {
256       Paper_system *ps = new Paper_system (title, true);
257       set_system_penalty (ps, header_);
258
259       systems_ = scm_cons (ps->self_scm (), systems_);
260       ps->unprotect ();
261     }
262
263   SCM page_properties
264     = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
265                   paper_->self_scm ());
266
267   SCM header = SCM_EOL;
268   for (SCM s = scm_reverse (scores_); s != SCM_EOL; s = scm_cdr (s))
269     {
270       if (ly_is_module (scm_car (s)))
271         {
272           header = scm_car (s);
273           if (header_0_ == SCM_EOL)
274             header_0_ = header;
275         }
276       else if (Music_output *mop = unsmob_music_output (scm_car (s)))
277
278         {
279           if (Paper_score *pscore = dynamic_cast<Paper_score *> (mop))
280             {
281               add_score_title (header);
282
283               header = SCM_EOL;
284
285               SCM system_list = scm_vector_to_list (pscore->get_paper_systems ());
286               system_list = scm_reverse (system_list);
287               systems_ = scm_append (scm_list_2 (system_list, systems_));
288             }
289           else
290             {
291               /*
292                 Ignore MIDI
293               */
294             }
295         }
296       else if (scm_is_vector (scm_car (s)))
297         {
298           /*
299             UGH. code dup.
300           */
301           add_score_title (header);
302           header = SCM_EOL;
303
304           SCM system_list = scm_vector_to_list (scm_car (s));
305           system_list = scm_reverse (system_list);
306           systems_ = scm_append (scm_list_2 (system_list, systems_));
307         }
308       else if (Text_interface::is_markup (scm_car (s)))
309         {
310           SCM t = Text_interface::interpret_markup (paper_->self_scm (),
311                                                     page_properties,
312                                                     scm_car (s));
313           // FIXME: title=true?
314           Paper_system *ps = new Paper_system (*unsmob_stencil (t), true);
315           systems_ = scm_cons (ps->self_scm (), systems_);
316           ps->unprotect ();
317           // FIXME: figure out penalty.
318           //set_system_penalty (ps, scores_[i].header_);
319         }
320       else
321         assert (0);
322     }
323
324   systems_ = scm_reverse (systems_);
325
326   int i = 0;
327   Paper_system *last = 0;
328   for (SCM s = systems_; s != SCM_EOL; s = scm_cdr (s))
329     {
330       Paper_system *ps = unsmob_paper_system (scm_car (s));
331       ps->number_ = ++i;
332
333       if (last
334           && last->is_title ()
335           && !ps->break_before_penalty_)
336         ps->break_before_penalty_ = 10000;
337       last = ps;
338     }
339
340   return systems_;
341 }
342
343 SCM
344 Paper_book::pages ()
345 {
346   if (SCM_BOOL_F != pages_)
347     return pages_;
348
349   pages_ = SCM_EOL;
350   SCM proc = paper_->c_variable ("page-breaking");
351   pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ()));
352   return pages_;
353 }
354
355 SCM
356 Paper_book::performances () const
357 {
358   return scm_reverse (performances_);
359 }