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