X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpaper-book.cc;h=72648b682fe952df2d0a9a4292be258a229c3670;hb=ca91e9064f2920586a4fd610bda911ab3b4d8793;hp=d2227ed86c17ef0de6418c8360132a06c1ca8d0f;hpb=c659cb200486c2f908703696a1b2873e78c8160a;p=lilypond.git diff --git a/lily/paper-book.cc b/lily/paper-book.cc index d2227ed86c..72648b682f 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -3,27 +3,33 @@ source file of the GNU LilyPond music typesetter - (c) 2004 Jan Nieuwenhuizen + (c) 2004--2007 Jan Nieuwenhuizen */ #include "paper-book.hh" -#include "ly-module.hh" +#include "grob.hh" #include "main.hh" #include "output-def.hh" -#include "paper-outputter.hh" +#include "paper-column.hh" #include "paper-score.hh" #include "paper-system.hh" +#include "text-interface.hh" #include "warn.hh" +#include "program-option.hh" +#include "page-marker.hh" #include "ly-smobs.icc" Paper_book::Paper_book () { + header_ = SCM_EOL; + header_0_ = SCM_EOL; pages_ = SCM_BOOL_F; + scores_ = SCM_EOL; + performances_ = SCM_EOL; systems_ = SCM_BOOL_F; - header_ = SCM_EOL; - + paper_ = 0; smobify_self (); } @@ -33,257 +39,137 @@ Paper_book::~Paper_book () } IMPLEMENT_DEFAULT_EQUAL_P (Paper_book); -IMPLEMENT_SMOBS (Paper_book) -IMPLEMENT_TYPE_P (Paper_book, "ly:paper-book?") +IMPLEMENT_SMOBS (Paper_book); +IMPLEMENT_TYPE_P (Paper_book, "ly:paper-book?"); SCM Paper_book::mark_smob (SCM smob) { - Paper_book *b = (Paper_book*) SCM_CELL_WORD_1 (smob); - for (int i = 0; i < b->score_systems_.size (); i++) - b->score_systems_[i].gc_mark (); - + Paper_book *b = (Paper_book *) SCM_CELL_WORD_1 (smob); if (b->paper_) scm_gc_mark (b->paper_->self_scm ()); scm_gc_mark (b->header_); + scm_gc_mark (b->header_0_); scm_gc_mark (b->pages_); + scm_gc_mark (b->performances_); + scm_gc_mark (b->scores_); return b->systems_; } int Paper_book::print_smob (SCM smob, SCM port, scm_print_state*) { - Paper_book *b = (Paper_book*) SCM_CELL_WORD_1 (smob); - - scm_puts ("#<", port); - scm_puts (classname (b), port); - scm_puts (" ", port); - //scm_puts (b->, port); - scm_puts (">", port); + Paper_book *b = (Paper_book *) SCM_CELL_WORD_1 (smob); + (void)b; + scm_puts ("#", port); return 1; } -Array -split_string (String s, char c) -{ - Array rv; - while (s.length ()) - { - int i = s.index (c); - - if (i == 0) - { - s = s.nomid_string (0, 1); - continue; - } - - if (i < 0) - i = s.length () ; - - rv.push (s.cut_string (0, i)); - s = s.nomid_string (0, i); - } - - return rv; -} - SCM dump_fields () { SCM fields = SCM_EOL; - for (int i = dump_header_fieldnames_global.size (); i--; ) + for (vsize i = dump_header_fieldnames_global.size (); i--;) fields - = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].to_str0 ()), + = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].c_str ()), fields); return fields; } -LY_DEFINE (ly_output_formats, "ly:output-formats", - 0, 0, 0, (), - "Formats passed to --format as a list of strings, " - "used for the output.") +void +Paper_book::add_score (SCM s) { - Array output_formats = split_string (output_format_global, ','); - - SCM lst = SCM_EOL; - int output_formats_count = output_formats.size (); - for (int i = 0; i < output_formats_count; i ++) - lst = scm_cons (scm_makfrom0str (output_formats[i].to_str0 ()), lst); - - return lst; + scores_ = scm_cons (s, scores_); } void -Paper_book::post_processing (SCM module, - SCM file_name) +Paper_book::add_performance (SCM s) { - struct - { - bool do_it_; - char const *func_name_; - } settings[] = { - {make_tex, "convert-to-tex"}, - {make_dvi, "convert-to-dvi"}, - {make_ps, "convert-to-ps"}, - {make_pdf, "convert-to-pdf"}, - {make_png, "convert-to-png"}, - {0, 0}, - }; - - for (int i = 0; settings[i].func_name_; i++) - { - if (settings[i].do_it_) - { - SCM func = scm_c_module_lookup (module, settings[i].func_name_); - if (scm_variable_p (func) == SCM_BOOL_T) - { - func = scm_variable_ref (func); - if (ly_c_procedure_p (func)) - scm_call_2 (func, self_scm (), file_name); - } - } - } + performances_ = scm_cons (s, performances_); } void -Paper_book::output (String outname) +Paper_book::output (SCM output_channel) { - if (!score_systems_.size ()) - return; - - /* Generate all stencils to trigger font loads. */ - pages (); - - SCM formats = ly_output_formats (); - for (SCM s = formats; scm_is_pair (s); s = scm_cdr (s)) + if (scm_is_pair (performances_)) { - String format = ly_scm2string (scm_car (s)); - String file_name = outname; - - if (file_name != "-") - file_name += "." + format; - - Paper_outputter *out = get_paper_outputter (file_name, format); - - SCM scopes = SCM_EOL; - if (ly_c_module_p (header_)) - scopes = scm_cons (header_, scopes); - - String mod_nm = "scm framework-" + format; - - SCM mod = scm_c_resolve_module (mod_nm.to_str0 ()); - if (make_pages) - { - SCM func = scm_c_module_lookup (mod, "output-framework"); - - func = scm_variable_ref (func); - scm_apply_0 (func, scm_list_n (out->self_scm (), - self_scm (), - scopes, - dump_fields (), - scm_makfrom0str (outname.to_str0 ()), - SCM_UNDEFINED)); - out->close (); - scm_gc_unprotect_object (out->self_scm ()); - post_processing (mod, scm_makfrom0str (file_name.to_str0 ())); - } - - if (make_preview) - { - String file_name = outname + ".preview." + format; - Paper_outputter *out = get_paper_outputter (file_name, format); - - SCM func = scm_c_module_lookup (mod, "output-preview-framework"); - func = scm_variable_ref (func); - scm_apply_0 (func, scm_list_n (out->self_scm (), - self_scm (), - scopes, - dump_fields (), - scm_makfrom0str (outname.to_str0 ()), - SCM_UNDEFINED)); - - out->close (); - scm_gc_unprotect_object (out->self_scm ()); - - post_processing (mod, scm_makfrom0str (file_name.to_str0 ())); - } + SCM proc = ly_lily_module_constant ("write-performances-midis"); + + scm_call_2 (proc, performances (), output_channel); } - progress_indication ("\n"); -} -void -Paper_book::classic_output (String outname) -{ + if (scores_ == SCM_EOL) + return; + /* Generate all stencils to trigger font loads. */ - systems (); + pages (); - // ugh code dup SCM scopes = SCM_EOL; - if (ly_c_module_p (header_)) + if (ly_is_module (header_)) scopes = scm_cons (header_, scopes); - if (ly_c_module_p (score_systems_[0].header_)) - scopes = scm_cons (score_systems_[0].header_, scopes); - //end ugh + string mod_nm = "scm framework-" + get_output_backend_name (); - Array output_formats = split_string (output_format_global, ','); + SCM mod = scm_c_resolve_module (mod_nm.c_str ()); - for (int i = 0; i < output_formats.size (); i++) + if (get_program_option ("print-pages")) { - String format = output_formats[i]; - String mod_nm = "scm framework-" + format; - - SCM mod = scm_c_resolve_module (mod_nm.to_str0 ()); - SCM func = scm_c_module_lookup (mod, "output-classic-framework"); + SCM func = scm_c_module_lookup (mod, "output-framework"); func = scm_variable_ref (func); - - Paper_outputter *out = get_paper_outputter (outname + "." + format, - format); - - scm_apply_0 (func, scm_list_n (out->self_scm (), self_scm (), scopes, + scm_apply_0 (func, scm_list_n (output_channel, + self_scm (), + scopes, dump_fields (), - scm_makfrom0str (outname.to_str0 ()), SCM_UNDEFINED)); - - scm_gc_unprotect_object (out->self_scm ()); - progress_indication ("\n"); } -} -LY_DEFINE (ly_paper_book_pages, "ly:paper-book-pages", - 1, 0, 0, (SCM pb), - "Return pages in book PB.") -{ - return unsmob_paper_book(pb)->pages (); + if (get_program_option ("preview")) + { + SCM func = scm_c_module_lookup (mod, "output-preview-framework"); + func = scm_variable_ref (func); + scm_apply_0 (func, scm_list_n (output_channel, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + } } -LY_DEFINE (ly_paper_book_scopes, "ly:paper-book-scopes", - 1, 0, 0, (SCM book), - "Return pages in layout book @var{book}.") +void +Paper_book::classic_output (SCM output) { - Paper_book *pb = unsmob_paper_book(book); - SCM_ASSERT_TYPE(pb, book, SCM_ARG1, __FUNCTION__, "Paper_book"); + if (scm_is_pair (performances_)) + { + SCM proc = ly_lily_module_constant ("write-performances-midis"); + + scm_call_2 (proc, performances (), output); + } + /* Generate all stencils to trigger font loads. */ + systems (); + SCM scopes = SCM_EOL; - if (ly_c_module_p (pb->header_)) - scopes = scm_cons (pb->header_, scopes); - - return scopes; -} + if (ly_is_module (header_)) + scopes = scm_cons (header_, scopes); -LY_DEFINE (ly_paper_book_systems, "ly:paper-book-systems", - 1, 0, 0, (SCM pb), - "Return systems in book PB.") -{ - return unsmob_paper_book (pb)->systems (); -} + if (ly_is_module (header_0_)) + scopes = scm_cons (header_0_, scopes); -LY_DEFINE (ly_paper_book_paper, "ly:paper-book-paper", - 1, 0, 0, (SCM pb), - "Return pages in book PB.") -{ - return unsmob_paper_book (pb)->paper_->self_scm (); + string format = get_output_backend_name (); + string mod_nm = "scm framework-" + format; + + SCM mod = scm_c_resolve_module (mod_nm.c_str ()); + SCM func = scm_c_module_lookup (mod, "output-classic-framework"); + + func = scm_variable_ref (func); + scm_apply_0 (func, scm_list_n (output, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + + progress_indication ("\n"); } /* TODO: resurrect more complex user-tweaks for titling? */ @@ -294,108 +180,300 @@ Paper_book::book_title () Stencil title; SCM scopes = SCM_EOL; - if (ly_c_module_p (header_)) + if (ly_is_module (header_)) scopes = scm_cons (header_, scopes); - SCM tit = SCM_EOL; - if (ly_c_procedure_p (title_func)) + if (ly_is_procedure (title_func)) tit = scm_call_2 (title_func, - paper_->self_scm (), - scopes); + paper_->self_scm (), + scopes); if (unsmob_stencil (tit)) title = *unsmob_stencil (tit); if (!title.is_empty ()) title.align_to (Y_AXIS, UP); - + return title; } Stencil -Paper_book::score_title (int i) +Paper_book::score_title (SCM header) { SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title")); Stencil title; - // ugh code dup SCM scopes = SCM_EOL; - if (ly_c_module_p (header_)) + if (ly_is_module (header_)) scopes = scm_cons (header_, scopes); - if (ly_c_module_p (score_systems_[i].header_)) - scopes = scm_cons (score_systems_[i].header_, scopes); - //end ugh + if (ly_is_module (header)) + scopes = scm_cons (header, scopes); SCM tit = SCM_EOL; - if (ly_c_procedure_p (title_func)) + if (ly_is_procedure (title_func)) tit = scm_call_2 (title_func, - paper_->self_scm (), - scopes); + paper_->self_scm (), + scopes); if (unsmob_stencil (tit)) title = *unsmob_stencil (tit); if (!title.is_empty ()) title.align_to (Y_AXIS, UP); - + return title; } - -SCM -Paper_book::systems () + +void +set_page_permission (SCM sys, SCM symbol, SCM permission) { - if (systems_ != SCM_BOOL_F) - return systems_; + if (Paper_score *ps = dynamic_cast (unsmob_music_output (sys))) + { + vector cols = ps->get_columns (); + if (cols.size ()) + { + Paper_column *col = dynamic_cast (cols.back ()); + col->set_property (symbol, permission); + col->find_prebroken_piece (LEFT)->set_property (symbol, permission); + } + } + else if (Prob *pb = unsmob_prob (sys)) + pb->set_property (symbol, permission); +} - systems_ = SCM_EOL; - Stencil title = book_title (); +/* read the breakbefore property of a score block and set up the preceding + system-spec to honour it. That is, SYS should be the system spec that + immediately precedes the score (from which HEADER is taken) + in the get_system_specs () list */ +void +set_system_penalty (SCM sys, SCM header) +{ + if (ly_is_module (header)) + { + SCM force = ly_module_lookup (header, ly_symbol2scm ("breakbefore")); + if (SCM_VARIABLEP (force) + && scm_is_bool (SCM_VARIABLE_REF (force))) + { + if (to_boolean (SCM_VARIABLE_REF (force))) + { + set_page_permission (sys, ly_symbol2scm ("page-break-permission"), + ly_symbol2scm ("force")); + set_page_permission (sys, ly_symbol2scm ("line-break-permission"), + ly_symbol2scm ("force")); + } + else + set_page_permission (sys, ly_symbol2scm ("page-break-permission"), SCM_EOL); + } + } +} +void +set_label (SCM sys, SCM label) +{ + if (Paper_score *ps = dynamic_cast (unsmob_music_output (sys))) + { + vector cols = ps->get_columns (); + if (cols.size ()) + { + Paper_column *col = dynamic_cast (cols[0]); + col->set_property ("labels", scm_cons (label, col->get_property ("labels"))); + Paper_column *col_right = dynamic_cast (col->find_prebroken_piece (RIGHT)); + col_right->set_property ("labels", scm_cons (label, col_right->get_property ("labels"))); + } + } + else if (Prob *pb = unsmob_prob (sys)) + pb->set_property ("labels", scm_cons (label, pb->get_property ("labels"))); +} + +SCM +Paper_book::get_score_title (SCM header) +{ + Stencil title = score_title (header); + if (title.is_empty ()) + title = score_title (header_); if (!title.is_empty ()) { - Paper_system *ps = new Paper_system (title, true); - systems_ = scm_cons (ps->self_scm (), systems_); - scm_gc_unprotect_object (ps->self_scm ()); + /* + TODO: this should come from the \layout {} block, which should + override settings from \paper {} + */ + SCM props = paper_->lookup_variable (ly_symbol2scm ("score-title-properties")); + Prob *ps = make_paper_system (props); + paper_system_set_stencil (ps, title); + + return ps->self_scm (); } + + return SCM_BOOL_F; +} + + +SCM +Paper_book::get_system_specs () +{ + SCM system_specs = SCM_EOL; - int score_count = score_systems_.size (); - for (int i = 0; i < score_count; i++) + Stencil title = book_title (); + if (!title.is_empty ()) + { + SCM props = paper_->lookup_variable (ly_symbol2scm ("book-title-properties")); + Prob *ps = make_paper_system (props); + paper_system_set_stencil (ps, title); + + system_specs = scm_cons (ps->self_scm (), system_specs); + ps->unprotect (); + } + + SCM page_properties + = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"), + paper_->self_scm ()); + + SCM interpret_markup_list = ly_lily_module_constant ("interpret-markup-list"); + SCM header = SCM_EOL; + for (SCM s = scm_reverse (scores_); scm_is_pair (s); s = scm_cdr (s)) { - Stencil title = score_title (i); - if (!title.is_empty ()) + if (ly_is_module (scm_car (s))) { - Paper_system *ps = new Paper_system (title, true); - systems_ = scm_cons (ps->self_scm (), systems_); - scm_gc_unprotect_object (ps->self_scm ()); - } - - if (scm_vector_p (score_systems_[i].systems_) == SCM_BOOL_T) + header = scm_car (s); + if (header_0_ == SCM_EOL) + header_0_ = header; + } + else if (Page_marker *page_marker = unsmob_page_marker (scm_car (s))) { - // guh. - SCM system_list = scm_vector_to_list (score_systems_[i].systems_); + /* page markers are used to set page breaking/turning permission, + or to place bookmarking labels */ + if (scm_is_symbol (page_marker->permission_symbol ())) + { + /* set previous element page break or turn permission */ + if (scm_is_pair (system_specs)) + set_page_permission (scm_car (system_specs), + page_marker->permission_symbol (), + page_marker->permission_value ()); + } + if (scm_is_symbol (page_marker->label ())) + { + /* set previous element label */ + if (scm_is_pair (system_specs)) + set_label (scm_car (system_specs), page_marker->label ()); + } + } + else if (Music_output *mop = unsmob_music_output (scm_car (s))) + { + if (Paper_score *pscore = dynamic_cast (mop)) + { + SCM title = get_score_title (header); + + if (scm_is_pair (system_specs)) + set_system_penalty (scm_car (system_specs), header); + + if (unsmob_prob (title)) + { + system_specs = scm_cons (title, system_specs); + unsmob_prob (title)->unprotect (); + } + header = SCM_EOL; + system_specs = scm_cons (pscore->self_scm (), system_specs); + } + else + { + /* + Ignore MIDI + */ + } + } + else if (Text_interface::is_markup_list (scm_car (s))) + { + SCM texts = scm_call_3 (interpret_markup_list, + paper_->self_scm (), + page_properties, + scm_car (s)); + for (SCM list = texts ; scm_is_pair (list) ; list = scm_cdr (list)) + { + SCM t = scm_car (list); + // TODO: init props + Prob *ps = make_paper_system (SCM_EOL); + ps->set_property ("page-break-permission", ly_symbol2scm ("allow")); + ps->set_property ("page-turn-permission", ly_symbol2scm ("allow")); + + paper_system_set_stencil (ps, *unsmob_stencil (t)); + ps->set_property ("is-title", SCM_BOOL_T); + if (scm_is_pair (scm_cdr (list))) + { + /* If an other markup is following, set this markup + * next padding and next space to 0, so that baseline-skip + * only should be taken into account for lines vertical + * spacing. */ + ps->set_property ("next-padding", scm_double2num (0.0)); + ps->set_property ("next-space", scm_double2num (0.0)); + } + system_specs = scm_cons (ps->self_scm (), system_specs); + ps->unprotect (); + + // FIXME: figure out penalty. + //set_system_penalty (ps, scores_[i].header_); + } + } + else + assert (0); + } + + system_specs = scm_reverse_x (system_specs, SCM_EOL); + return system_specs; +} + +SCM +Paper_book::systems () +{ + if (systems_ != SCM_BOOL_F) + return systems_; + + systems_ = SCM_EOL; + SCM specs = get_system_specs (); + for (SCM s = specs; scm_is_pair (s); s = scm_cdr (s)) + { + if (Paper_score *pscore = dynamic_cast (unsmob_music_output (scm_car (s)))) + { + SCM system_list = scm_vector_to_list (pscore->get_paper_systems ()); system_list = scm_reverse (system_list); systems_ = scm_append (scm_list_2 (system_list, systems_)); } + else + { + systems_ = scm_cons (scm_car (s), systems_); + } } systems_ = scm_reverse (systems_); - + + /* backwards compatibility for the old page breaker */ int i = 0; - Paper_system *last = 0; - for (SCM s = systems_; s != SCM_EOL; s = scm_cdr (s)) + Prob *last = 0; + for (SCM s = systems_; scm_is_pair (s); s = scm_cdr (s)) { - Paper_system *ps = unsmob_paper_system (scm_car (s)); - ps->number_ = ++i; + Prob *ps = unsmob_prob (scm_car (s)); + ps->set_property ("number", scm_from_int (++i)); - if (last && last->is_title ()) - // ugh, hardcoded. - ps->penalty_ = 10000; + if (last + && to_boolean (last->get_property ("is-title")) + && !scm_is_number (ps->get_property ("penalty"))) + ps->set_property ("penalty", scm_from_int (10000)); last = ps; + + if (scm_is_pair (scm_cdr (s))) + { + SCM perm = ps->get_property ("page-break-permission"); + Prob *next = unsmob_prob (scm_cadr (s)); + if (perm == SCM_EOL) + next->set_property ("penalty", scm_from_int (10001)); + else if (perm == ly_symbol2scm ("force")) + next->set_property ("penalty", scm_from_int (-10001)); + } } - + return systems_; } @@ -406,24 +484,27 @@ Paper_book::pages () return pages_; pages_ = SCM_EOL; - SCM proc = paper_->c_variable ("page-breaking"); - pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ())); - return pages_; -} + SCM proc = paper_->c_variable ("page-breaking-wrapper"); + pages_ = scm_apply_0 (proc, scm_list_1 (self_scm ())); + /* set systems_ from the pages */ + if (systems_ == SCM_BOOL_F) + { + systems_ = SCM_EOL; + for (SCM p = pages_; scm_is_pair (p); p = scm_cdr (p)) + { + Prob *page = unsmob_prob (scm_car (p)); + SCM systems = page->get_property ("lines"); -/****************************************************************/ + systems_ = scm_append (scm_list_2 (systems_, systems)); + } + } -Score_systems::Score_systems () -{ - systems_ = SCM_EOL; - header_ = SCM_EOL; + return pages_; } -void -Score_systems::gc_mark () +SCM +Paper_book::performances () const { - scm_gc_mark (systems_); - scm_gc_mark (header_); + return scm_reverse (performances_); } -