]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-book.cc
* lily/drum-note-performer.cc (class Drum_note_performer): use
[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 (scm_is_pair (performances_))
94     {
95       SCM proc = ly_lily_module_constant ("paper-book-write-midis");
96
97       scm_call_2 (proc, self_scm (), output_channel);
98     }
99
100   if (scores_ == SCM_EOL)
101     return;
102
103   /* Generate all stencils to trigger font loads.  */
104   pages ();
105
106   SCM scopes = SCM_EOL;
107   if (ly_is_module (header_))
108     scopes = scm_cons (header_, scopes);
109
110   String mod_nm = "scm framework-" + output_backend_global;
111
112   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
113   if (make_print)
114     {
115       SCM func = scm_c_module_lookup (mod, "output-framework");
116
117       func = scm_variable_ref (func);
118       scm_apply_0 (func, scm_list_n (output_channel,
119                                      self_scm (),
120                                      scopes,
121                                      dump_fields (),
122                                      SCM_UNDEFINED));
123     }
124
125   if (make_preview)
126     {
127       SCM func = scm_c_module_lookup (mod, "output-preview-framework");
128       func = scm_variable_ref (func);
129       scm_apply_0 (func, scm_list_n (output_channel,
130                                      self_scm (),
131                                      scopes,
132                                      dump_fields (),
133                                      SCM_UNDEFINED));
134     }
135 }
136
137 void
138 Paper_book::classic_output (SCM output)
139 {
140   /* Generate all stencils to trigger font loads.  */
141   systems ();
142
143   SCM scopes = SCM_EOL;
144   if (ly_is_module (header_))
145     scopes = scm_cons (header_, scopes);
146
147   if (ly_is_module (header_0_))
148     scopes = scm_cons (header_0_, scopes);
149
150   String format = output_backend_global;
151   String mod_nm = "scm framework-" + format;
152
153   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
154   SCM func = scm_c_module_lookup (mod, "output-classic-framework");
155
156   func = scm_variable_ref (func);
157   scm_apply_0 (func, scm_list_n (output,
158                                  self_scm (),
159                                  scopes,
160                                  dump_fields (),
161                                  SCM_UNDEFINED));
162
163   progress_indication ("\n");
164 }
165
166 /* TODO: resurrect more complex user-tweaks for titling?  */
167 Stencil
168 Paper_book::book_title ()
169 {
170   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("book-title"));
171   Stencil title;
172
173   SCM scopes = SCM_EOL;
174   if (ly_is_module (header_))
175     scopes = scm_cons (header_, scopes);
176
177   SCM tit = SCM_EOL;
178   if (ly_is_procedure (title_func))
179     tit = scm_call_2 (title_func,
180                       paper_->self_scm (),
181                       scopes);
182
183   if (unsmob_stencil (tit))
184     title = *unsmob_stencil (tit);
185
186   if (!title.is_empty ())
187     title.align_to (Y_AXIS, UP);
188
189   return title;
190 }
191
192 Stencil
193 Paper_book::score_title (SCM header)
194 {
195   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title"));
196
197   Stencil title;
198
199   SCM scopes = SCM_EOL;
200   if (ly_is_module (header_))
201     scopes = scm_cons (header_, scopes);
202
203   if (ly_is_module (header))
204     scopes = scm_cons (header, scopes);
205
206   SCM tit = SCM_EOL;
207   if (ly_is_procedure (title_func))
208     tit = scm_call_2 (title_func,
209                       paper_->self_scm (),
210                       scopes);
211
212   if (unsmob_stencil (tit))
213     title = *unsmob_stencil (tit);
214
215   if (!title.is_empty ())
216     title.align_to (Y_AXIS, UP);
217
218   return title;
219 }
220
221 void
222 set_system_penalty (Paper_system *ps, SCM header)
223 {
224   if (ly_is_module (header))
225     {
226       SCM force = ly_module_lookup (header, ly_symbol2scm ("breakbefore"));
227       if (SCM_VARIABLEP (force)
228           && scm_is_bool (SCM_VARIABLE_REF (force)))
229         {
230           ps->break_before_penalty_ = to_boolean (SCM_VARIABLE_REF (force))
231             ? -10000
232             : 10000;
233         }
234     }
235 }
236
237 void
238 Paper_book::add_score_title (SCM header)
239 {
240   Stencil title = score_title (header);
241   if (title.is_empty ())
242     title = score_title (header_);
243   if (!title.is_empty ())
244     {
245       Paper_system *ps = new Paper_system (title, true);
246       systems_ = scm_cons (ps->self_scm (), systems_);
247       ps->unprotect ();
248       set_system_penalty (ps, header);
249     }
250 }
251
252 SCM
253 Paper_book::systems ()
254 {
255   if (systems_ != SCM_BOOL_F)
256     return systems_;
257
258   systems_ = SCM_EOL;
259   Stencil title = book_title ();
260
261   if (!title.is_empty ())
262     {
263       Paper_system *ps = new Paper_system (title, true);
264       set_system_penalty (ps, header_);
265
266       systems_ = scm_cons (ps->self_scm (), systems_);
267       ps->unprotect ();
268     }
269
270   SCM page_properties
271     = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
272                   paper_->self_scm ());
273
274   SCM header = SCM_EOL;
275   for (SCM s = scm_reverse (scores_); s != SCM_EOL; s = scm_cdr (s))
276     {
277       if (ly_is_module (scm_car (s)))
278         {
279           header = scm_car (s);
280           if (header_0_ == SCM_EOL)
281             header_0_ = header;
282         }
283       else if (Music_output *mop = unsmob_music_output (scm_car (s)))
284
285         {
286           if (Paper_score *pscore = dynamic_cast<Paper_score *> (mop))
287             {
288               add_score_title (header);
289
290               header = SCM_EOL;
291
292               SCM system_list = scm_vector_to_list (pscore->get_paper_systems ());
293               system_list = scm_reverse (system_list);
294               systems_ = scm_append (scm_list_2 (system_list, systems_));
295             }
296           else
297             {
298               /*
299                 Ignore MIDI
300               */
301             }
302         }
303       else if (scm_is_vector (scm_car (s)))
304         {
305           /*
306             UGH. code dup.
307           */
308           add_score_title (header);
309           header = SCM_EOL;
310
311           SCM system_list = scm_vector_to_list (scm_car (s));
312           system_list = scm_reverse (system_list);
313           systems_ = scm_append (scm_list_2 (system_list, systems_));
314         }
315       else if (Text_interface::is_markup (scm_car (s)))
316         {
317           SCM t = Text_interface::interpret_markup (paper_->self_scm (),
318                                                     page_properties,
319                                                     scm_car (s));
320           // FIXME: title=true?
321           Paper_system *ps = new Paper_system (*unsmob_stencil (t), true);
322           systems_ = scm_cons (ps->self_scm (), systems_);
323           ps->unprotect ();
324           // FIXME: figure out penalty.
325           //set_system_penalty (ps, scores_[i].header_);
326         }
327       else
328         assert (0);
329     }
330
331   systems_ = scm_reverse (systems_);
332
333   int i = 0;
334   Paper_system *last = 0;
335   for (SCM s = systems_; s != SCM_EOL; s = scm_cdr (s))
336     {
337       Paper_system *ps = unsmob_paper_system (scm_car (s));
338       ps->number_ = ++i;
339
340       if (last
341           && last->is_title ()
342           && !ps->break_before_penalty_)
343         ps->break_before_penalty_ = 10000;
344       last = ps;
345     }
346
347   return systems_;
348 }
349
350 SCM
351 Paper_book::pages ()
352 {
353   if (SCM_BOOL_F != pages_)
354     return pages_;
355
356   pages_ = SCM_EOL;
357   SCM proc = paper_->c_variable ("page-breaking");
358   pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ()));
359   return pages_;
360 }
361
362 SCM
363 Paper_book::performances () const
364 {
365   return scm_reverse (performances_);
366 }