]> git.donarmstrong.com Git - lilypond.git/blob - lily/paper-book.cc
* lily/paper-book.cc (output): load framework module
[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 "output-def.hh"
12 #include "paper-book.hh"
13 #include "paper-outputter.hh"
14 #include "paper-score.hh"
15 #include "paper-system.hh"
16 #include "stencil.hh"
17 #include "warn.hh"
18
19 #include "ly-smobs.icc"
20
21 Paper_book::Paper_book ()
22 {
23   pages_ = SCM_BOOL_F;
24   lines_ = SCM_BOOL_F;
25   header_ = SCM_EOL;
26   
27   bookpaper_ = 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_lines_.size (); i++)
44     b->score_lines_[i].gc_mark ();
45
46   if (b->bookpaper_)
47     scm_gc_mark (b->bookpaper_->self_scm ());
48   scm_gc_mark (b->header_);
49   scm_gc_mark (b->pages_);
50   return b->lines_;
51 }
52
53 int
54 Paper_book::print_smob (SCM smob, SCM port, scm_print_state*)
55 {
56   Paper_book *b = (Paper_book*) ly_cdr (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 LY_DEFINE (ly_output_formats, "ly:output-formats",
102            0, 0, 0, (),
103            "Formats passed to --format as a list of strings, "
104            "used for the output.")
105 {
106   Array<String> output_formats = split_string (output_format_global, ',');
107
108   SCM lst = SCM_EOL;
109   int output_formats_count = output_formats.size ();
110   for (int i = 0; i < output_formats_count; i ++)
111     lst = scm_cons (scm_makfrom0str (output_formats[i].to_str0 ()), lst);
112   
113   return lst; 
114 }
115
116 void
117 Paper_book::output (String outname)
118 {
119   if (!score_lines_.size ())
120     return;
121
122   /* Generate all stencils to trigger font loads.  */
123   pages ();
124   
125   SCM formats = ly_output_formats();
126   for (SCM s = formats; ly_c_pair_p (s); s = ly_cdr (s)) 
127     {
128       String format = ly_scm2string (ly_car (s));
129       Paper_outputter *out = get_paper_outputter (outname + "." + format,
130                                                   format);
131   
132       SCM scopes = SCM_EOL;
133       if (ly_c_module_p (header_))
134         scopes = scm_cons (header_, scopes);
135   
136       String func_nm = format;
137       func_nm = "output-framework-" + func_nm;
138       String mod_nm = "scm framework-" + format;
139       
140       SCM mod = scm_c_resolve_module (mod_nm.to_str0 ());
141       SCM func = scm_c_module_lookup (mod, func_nm.to_str0 ());
142
143       func = scm_variable_ref (func);
144       scm_apply_0 (func, scm_list_n (out->self_scm (),
145                                      self_scm (),
146                                      scopes,
147                                      dump_fields (),
148                                      scm_makfrom0str (outname.to_str0 ()),
149                                      SCM_UNDEFINED));
150
151       scm_gc_unprotect_object (out->self_scm ());
152       progress_indication ("\n");
153     }
154 }
155
156 void
157 Paper_book::classic_output (String outname)
158 {
159   /* Generate all stencils to trigger font loads.  */
160   lines ();
161
162   // ugh code dup
163   SCM scopes = SCM_EOL;
164   if (ly_c_module_p (header_))
165     scopes = scm_cons (header_, scopes);
166
167   if (ly_c_module_p (score_lines_[0].header_))
168     scopes = scm_cons (score_lines_[0].header_, scopes);
169   //end ugh
170
171   Array<String> output_formats = split_string (output_format_global, ',');
172
173   for (int i = 0; i < output_formats.size (); i++)
174     {
175       String format = output_formats[i];
176       String func_nm = format;
177       func_nm = "output-classic-framework-" + func_nm;
178       
179       SCM func = ly_scheme_function (func_nm.to_str0 ());
180       Paper_outputter *out = get_paper_outputter (outname + "." + format,
181                                                   format);
182
183       scm_apply_0 (func, scm_list_5 (out->self_scm (), self_scm (), scopes,
184                                      dump_fields (),
185                                      scm_makfrom0str (outname.to_str0 ())));
186
187       scm_gc_unprotect_object (out->self_scm ());
188       progress_indication ("\n");
189     }
190 }
191
192 LY_DEFINE (ly_paper_book_pages, "ly:paper-book-pages",
193           1, 0, 0, (SCM pb),
194           "Return pages in book PB.")
195 {
196   return unsmob_paper_book(pb)->pages ();
197 }
198
199 LY_DEFINE (ly_paper_book_scopes, "ly:paper-book-scopes",
200           1, 0, 0, (SCM book),
201           "Return pages in paper book @var{book}.")
202 {
203   Paper_book *pb = unsmob_paper_book(book);
204   SCM_ASSERT_TYPE(pb, book, SCM_ARG1, __FUNCTION__, "Paper_book");
205   
206   SCM scopes = SCM_EOL;
207   if (ly_c_module_p (pb->header_))
208     scopes = scm_cons (pb->header_, scopes);
209   
210   return scopes;
211 }
212
213 LY_DEFINE (ly_paper_book_lines, "ly:paper-book-lines",
214            1, 0, 0, (SCM pb),
215            "Return lines in book PB.")
216 {
217   return unsmob_paper_book (pb)->lines ();
218 }
219
220 LY_DEFINE (ly_paper_book_book_paper, "ly:paper-book-book-paper",
221           1, 0, 0, (SCM pb),
222           "Return pages in book PB.")
223 {
224   return unsmob_paper_book (pb)->bookpaper_->self_scm ();
225 }
226
227 /* TODO: resurrect more complex user-tweaks for titling?  */
228 Stencil
229 Paper_book::book_title ()
230 {
231   SCM title_func = bookpaper_->lookup_variable (ly_symbol2scm ("book-title"));
232   Stencil title;
233
234   SCM scopes = SCM_EOL;
235   if (ly_c_module_p (header_))
236     scopes = scm_cons (header_, scopes);
237
238  
239   SCM tit = SCM_EOL;
240   if (ly_c_procedure_p (title_func))
241     tit = scm_call_2 (title_func,
242                      bookpaper_->self_scm (),
243                      scopes);
244
245   if (unsmob_stencil (tit))
246     title = *unsmob_stencil (tit);
247
248   if (!title.is_empty ())
249     title.align_to (Y_AXIS, UP);
250   
251   return title;
252 }
253
254 Stencil
255 Paper_book::score_title (int i)
256 {
257   SCM title_func = bookpaper_->lookup_variable (ly_symbol2scm ("score-title"));
258
259   Stencil title;
260
261   // ugh code dup
262   SCM scopes = SCM_EOL;
263   if (ly_c_module_p (header_))
264     scopes = scm_cons (header_, scopes);
265
266   if (ly_c_module_p (score_lines_[i].header_))
267     scopes = scm_cons (score_lines_[i].header_, scopes);
268   //end ugh
269
270   SCM tit = SCM_EOL;
271   if (ly_c_procedure_p (title_func))
272     tit = scm_call_2 (title_func,
273                      bookpaper_->self_scm (),
274                      scopes);
275
276   if (unsmob_stencil (tit))
277     title = *unsmob_stencil (tit);
278
279   if (!title.is_empty ())
280     title.align_to (Y_AXIS, UP);
281   
282   return title;
283 }
284   
285 SCM
286 Paper_book::lines ()
287 {
288   if (lines_ != SCM_BOOL_F)
289     return lines_;
290
291   lines_ = SCM_EOL;
292   Stencil title = book_title ();
293
294   if (!title.is_empty ())
295     {
296       Paper_system *pl = new Paper_system (title, true);
297       lines_ = scm_cons (pl->self_scm (), lines_);
298       scm_gc_unprotect_object (pl->self_scm ());
299     }
300   
301   int score_count = score_lines_.size ();
302   for (int i = 0; i < score_count; i++)
303     {
304       Stencil title = score_title (i);      
305       if (!title.is_empty ())
306         {
307           Paper_system *pl = new Paper_system (title, true);
308           lines_ = scm_cons (pl->self_scm (), lines_);
309           scm_gc_unprotect_object (pl->self_scm ());
310         }
311       
312       if (scm_vector_p (score_lines_[i].lines_) == SCM_BOOL_T)
313         {
314           // guh.         
315           SCM line_list = scm_vector_to_list (score_lines_[i].lines_);
316
317           line_list = scm_reverse (line_list);
318           lines_ = scm_append (scm_list_2 (line_list, lines_));
319         }
320     }
321   
322   lines_ = scm_reverse (lines_);
323   
324   int i = 0;
325   Paper_system *last = 0;
326   for (SCM s = lines_; s != SCM_EOL; s = ly_cdr (s))
327     {
328       Paper_system * p = unsmob_paper_line (ly_car (s));
329       p->number_ = ++i;
330
331       if (last && last->is_title ())
332         // ugh, hardcoded.      
333         p->penalty_ = 10000;
334       last = p;
335     }
336   
337   return lines_;
338 }
339
340 SCM
341 Paper_book::pages ()
342 {
343   if (SCM_BOOL_F != pages_)
344     return pages_;
345
346   pages_ = SCM_EOL;
347   Output_def *paper = bookpaper_;
348   SCM proc = paper->c_variable ("page-breaking");
349   pages_ = scm_apply_0 (proc, scm_list_2 (lines (), self_scm ()));
350   return pages_;
351 }
352
353
354 /****************************************************************/
355
356 Score_lines::Score_lines ()
357 {
358   lines_ = SCM_EOL;
359   header_ = SCM_EOL;
360 }
361
362 void
363 Score_lines::gc_mark ()
364 {
365   scm_gc_mark (lines_);
366   scm_gc_mark (header_);
367 }
368