]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-book.cc
* lily/include/main.hh: rename format to backend.
[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 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "paper-book.hh"
10
11 #include "ly-module.hh"
12 #include "main.hh"
13 #include "output-def.hh"
14 #include "paper-outputter.hh"
15 #include "paper-score.hh"
16 #include "paper-system.hh"
17 #include "warn.hh"
18
19 #include "ly-smobs.icc"
20
21 Paper_book::Paper_book ()
22 {
23   pages_ = SCM_BOOL_F;
24   systems_ = SCM_BOOL_F;
25   header_ = SCM_EOL;
26   
27   paper_ = 0;
28   smobify_self ();
29 }
30
31 Paper_book::~Paper_book ()
32 {
33 }
34
35 IMPLEMENT_DEFAULT_EQUAL_P (Paper_book);
36 IMPLEMENT_SMOBS (Paper_book)
37 IMPLEMENT_TYPE_P (Paper_book, "ly:paper-book?")
38
39 SCM
40 Paper_book::mark_smob (SCM smob)
41 {
42   Paper_book *b = (Paper_book*) SCM_CELL_WORD_1 (smob);
43   for (int i = 0; i < b->score_systems_.size (); i++)
44     b->score_systems_[i].gc_mark ();
45
46   if (b->paper_)
47     scm_gc_mark (b->paper_->self_scm ());
48   scm_gc_mark (b->header_);
49   scm_gc_mark (b->pages_);
50   return b->systems_;
51 }
52
53 int
54 Paper_book::print_smob (SCM smob, SCM port, scm_print_state*)
55 {
56   Paper_book *b = (Paper_book*) SCM_CELL_WORD_1 (smob);
57      
58   scm_puts ("#<", port);
59   scm_puts (classname (b), port);
60   scm_puts (" ", port);
61   //scm_puts (b->, port);
62   scm_puts (">", port);
63   return 1;
64 }
65
66 Array<String>
67 split_string (String s, char c)
68 {
69   Array<String> rv; 
70   while (s.length ())
71     {
72       int i = s.index (c);
73       
74       if (i == 0)
75         {
76           s = s.nomid_string (0, 1);
77           continue;
78         }
79       
80       if (i < 0)
81         i = s.length () ;
82
83       rv.push (s.cut_string (0, i));
84       s = s.nomid_string (0, i);
85     }
86
87   return rv;
88 }
89
90 SCM
91 dump_fields ()
92 {
93   SCM fields = SCM_EOL;
94   for (int i = dump_header_fieldnames_global.size (); i--; )
95     fields
96       = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].to_str0 ()),
97                   fields);
98   return fields;
99 }
100
101 void
102 Paper_book::post_processing (SCM module,
103                              SCM file_name)
104 {
105   struct
106   {
107     bool do_it_;
108     char const *func_name_;
109   } settings[] = {
110     {make_tex, "convert-to-tex"},
111     {make_dvi, "convert-to-dvi"},
112     {make_ps, "convert-to-ps"},
113     {make_pdf, "convert-to-pdf"},
114     {make_png, "convert-to-png"},
115     {0, 0},
116   };
117
118   for (int i = 0; settings[i].func_name_; i++)
119     {
120       if (settings[i].do_it_)
121         {
122           SCM func = scm_c_module_lookup (module, settings[i].func_name_);
123           if (scm_variable_p (func) == SCM_BOOL_T)
124             {
125               func = scm_variable_ref (func);
126               if (ly_c_procedure_p (func))
127                 scm_call_2 (func, self_scm (), file_name);
128             }
129         }
130     }
131 }
132
133 void
134 Paper_book::output (String outname)
135 {
136   if (!score_systems_.size ())
137     return;
138
139   /* Generate all stencils to trigger font loads.  */
140   pages ();
141   
142   String format = output_backend_global;
143   String file_name = outname;
144       
145   if (file_name != "-")
146     file_name += "." + format;
147       
148   Paper_outputter *out = get_paper_outputter (file_name, format);
149   
150   SCM scopes = SCM_EOL;
151   if (ly_c_module_p (header_))
152     scopes = scm_cons (header_, scopes);
153   
154   String mod_nm = "scm framework-" + format;
155
156   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
157   if (make_pages)
158     {
159       SCM func = scm_c_module_lookup (mod, "output-framework");
160
161       func = scm_variable_ref (func);
162       scm_apply_0 (func, scm_list_n (out->self_scm (),
163                                      self_scm (),
164                                      scopes,
165                                      dump_fields (),
166                                      scm_makfrom0str (outname.to_str0 ()),
167                                      SCM_UNDEFINED));
168       out->close ();
169       scm_gc_unprotect_object (out->self_scm ());
170       post_processing (mod, scm_makfrom0str (file_name.to_str0 ()));
171     }
172       
173   if (make_preview)
174     {
175       String file_name = outname + ".preview." + format;
176       Paper_outputter *out = get_paper_outputter (file_name, format);
177   
178       SCM func = scm_c_module_lookup (mod, "output-preview-framework");
179       func = scm_variable_ref (func);
180       scm_apply_0 (func, scm_list_n (out->self_scm (),
181                                      self_scm (),
182                                      scopes,
183                                      dump_fields (),
184                                      scm_makfrom0str (outname.to_str0 ()),
185                                      SCM_UNDEFINED));
186
187       out->close ();
188       scm_gc_unprotect_object (out->self_scm ());
189
190       post_processing (mod, scm_makfrom0str (file_name.to_str0 ()));
191     }
192   progress_indication ("\n");
193 }
194
195 void
196 Paper_book::classic_output (String outname)
197 {
198   /* Generate all stencils to trigger font loads.  */
199   systems ();
200
201   // ugh code dup
202   SCM scopes = SCM_EOL;
203   if (ly_c_module_p (header_))
204     scopes = scm_cons (header_, scopes);
205
206   if (ly_c_module_p (score_systems_[0].header_))
207     scopes = scm_cons (score_systems_[0].header_, scopes);
208   //end ugh
209
210   String format = output_backend_global;
211   String mod_nm = "scm framework-" + format;
212       
213   SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
214   SCM func = scm_c_module_lookup (mod, "output-classic-framework");
215
216   func = scm_variable_ref (func);
217       
218   Paper_outputter *out = get_paper_outputter (outname + "." + format,
219                                               format);
220
221   scm_apply_0 (func, scm_list_n (out->self_scm (), self_scm (), scopes,
222                                  dump_fields (),
223                                  scm_makfrom0str (outname.to_str0 ()),
224                                  SCM_UNDEFINED));
225
226   scm_gc_unprotect_object (out->self_scm ());
227   progress_indication ("\n");
228 }
229
230 LY_DEFINE (ly_paper_book_pages, "ly:paper-book-pages",
231           1, 0, 0, (SCM pb),
232           "Return pages in book PB.")
233 {
234   return unsmob_paper_book(pb)->pages ();
235 }
236
237 LY_DEFINE (ly_paper_book_scopes, "ly:paper-book-scopes",
238           1, 0, 0, (SCM book),
239           "Return pages in layout book @var{book}.")
240 {
241   Paper_book *pb = unsmob_paper_book(book);
242   SCM_ASSERT_TYPE(pb, book, SCM_ARG1, __FUNCTION__, "Paper_book");
243   
244   SCM scopes = SCM_EOL;
245   if (ly_c_module_p (pb->header_))
246     scopes = scm_cons (pb->header_, scopes);
247   
248   return scopes;
249 }
250
251 LY_DEFINE (ly_paper_book_systems, "ly:paper-book-systems",
252            1, 0, 0, (SCM pb),
253            "Return systems in book PB.")
254 {
255   return unsmob_paper_book (pb)->systems ();
256 }
257
258 LY_DEFINE (ly_paper_book_paper, "ly:paper-book-paper",
259           1, 0, 0, (SCM pb),
260           "Return pages in book PB.")
261 {
262   return unsmob_paper_book (pb)->paper_->self_scm ();
263 }
264
265 /* TODO: resurrect more complex user-tweaks for titling?  */
266 Stencil
267 Paper_book::book_title ()
268 {
269   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("book-title"));
270   Stencil title;
271
272   SCM scopes = SCM_EOL;
273   if (ly_c_module_p (header_))
274     scopes = scm_cons (header_, scopes);
275
276  
277   SCM tit = SCM_EOL;
278   if (ly_c_procedure_p (title_func))
279     tit = scm_call_2 (title_func,
280                      paper_->self_scm (),
281                      scopes);
282
283   if (unsmob_stencil (tit))
284     title = *unsmob_stencil (tit);
285
286   if (!title.is_empty ())
287     title.align_to (Y_AXIS, UP);
288   
289   return title;
290 }
291
292 Stencil
293 Paper_book::score_title (int i)
294 {
295   SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title"));
296
297   Stencil title;
298
299   // ugh code dup
300   SCM scopes = SCM_EOL;
301   if (ly_c_module_p (header_))
302     scopes = scm_cons (header_, scopes);
303
304   if (ly_c_module_p (score_systems_[i].header_))
305     scopes = scm_cons (score_systems_[i].header_, scopes);
306   //end ugh
307
308   SCM tit = SCM_EOL;
309   if (ly_c_procedure_p (title_func))
310     tit = scm_call_2 (title_func,
311                      paper_->self_scm (),
312                      scopes);
313
314   if (unsmob_stencil (tit))
315     title = *unsmob_stencil (tit);
316
317   if (!title.is_empty ())
318     title.align_to (Y_AXIS, UP);
319   
320   return title;
321 }
322
323 void
324 set_system_penalty (Paper_system * ps, SCM header)
325 {
326   if (ly_c_module_p (header))
327     {
328       SCM force = ly_module_lookup (header, ly_symbol2scm ("breakbefore"));
329       if (SCM_VARIABLEP(force)
330           && scm_is_bool (SCM_VARIABLE_REF(force)))
331         {
332           ps->break_before_penalty_ = to_boolean (SCM_VARIABLE_REF(force))
333             ? -10000
334             : 10000;
335         }
336     }
337 }
338             
339 SCM
340 Paper_book::systems ()
341 {
342   if (systems_ != SCM_BOOL_F)
343     return systems_;
344
345   systems_ = SCM_EOL;
346   Stencil title = book_title ();
347
348   if (!title.is_empty ())
349     {
350       Paper_system *ps = new Paper_system (title, true);
351       set_system_penalty (ps, header_);
352       
353       systems_ = scm_cons (ps->self_scm (), systems_);
354       scm_gc_unprotect_object (ps->self_scm ());
355     }
356   
357   int score_count = score_systems_.size ();
358   for (int i = 0; i < score_count; i++)
359     {
360       Stencil title = score_title (i);      
361       if (!title.is_empty ())
362         {
363           Paper_system *ps = new Paper_system (title, true);
364           systems_ = scm_cons (ps->self_scm (), systems_);
365           scm_gc_unprotect_object (ps->self_scm ());
366
367           set_system_penalty (ps, score_systems_[i].header_);
368           
369         }
370       
371       if (scm_vector_p (score_systems_[i].systems_) == SCM_BOOL_T)
372         {
373           // guh.         
374           SCM system_list = scm_vector_to_list (score_systems_[i].systems_);
375
376           system_list = scm_reverse (system_list);
377           systems_ = scm_append (scm_list_2 (system_list, systems_));
378         }
379     }
380   
381   systems_ = scm_reverse (systems_);
382   
383   int i = 0;
384   Paper_system *last = 0;
385   for (SCM s = systems_; s != SCM_EOL; s = scm_cdr (s))
386     {
387       Paper_system *ps = unsmob_paper_system (scm_car (s));
388       ps->number_ = ++i;
389
390       if (last
391           && last->is_title ()
392           && !ps->break_before_penalty_)
393         ps->break_before_penalty_ = 10000;
394       last = ps;
395     }
396   
397   return systems_;
398 }
399
400 SCM
401 Paper_book::pages ()
402 {
403   if (SCM_BOOL_F != pages_)
404     return pages_;
405
406   pages_ = SCM_EOL;
407   SCM proc = paper_->c_variable ("page-breaking");
408   pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ()));
409   return pages_;
410 }
411
412
413 /****************************************************************/
414
415 Score_systems::Score_systems ()
416 {
417   systems_ = SCM_EOL;
418   header_ = SCM_EOL;
419 }
420
421 void
422 Score_systems::gc_mark ()
423 {
424   scm_gc_mark (systems_);
425   scm_gc_mark (header_);
426 }
427