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