X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpaper-book.cc;h=aecafbe3a053d66a15d884684ea570e01c011a85;hb=21f6ea846dc1930cb41f185485ce6e1c8d9b30bd;hp=cbd690772eb17196a899f8694fe78970d18d5c88;hpb=6e8c2c2bbc0526de8a677a18b5b76e6096b59ef6;p=lilypond.git diff --git a/lily/paper-book.cc b/lily/paper-book.cc index cbd690772e..aecafbe3a0 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -1,36 +1,50 @@ /* - paper-book.cc -- implement Paper_book + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2004--2012 Jan Nieuwenhuizen - (c) 2004 Jan Nieuwenhuizen + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ -#include "ly-module.hh" -#include "main.hh" #include "paper-book.hh" + +#include "grob.hh" +#include "international.hh" +#include "main.hh" #include "output-def.hh" -#include "paper-outputter.hh" -#include "paper-line.hh" +#include "paper-column.hh" #include "paper-score.hh" -#include "stencil.hh" +#include "paper-system.hh" +#include "text-interface.hh" #include "warn.hh" +#include "program-option.hh" +#include "page-marker.hh" - -/* - Ugh. the Function of the Paper_book class is unclear. Trim this - file. - - */ - +#include "ly-smobs.icc" Paper_book::Paper_book () { - pages_ = SCM_BOOL_F; - lines_ = SCM_BOOL_F; header_ = SCM_EOL; - - bookpaper_ = 0; + header_0_ = SCM_EOL; + pages_ = SCM_BOOL_F; + scores_ = SCM_EOL; + bookparts_ = SCM_EOL; + performances_ = SCM_EOL; + systems_ = SCM_BOOL_F; + + paper_ = 0; + parent_ = 0; smobify_self (); } @@ -38,437 +52,636 @@ Paper_book::~Paper_book () { } -#include "ly-smobs.icc" - 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_lines_.size (); i++) - b->score_lines_[i].gc_mark (); - - if (b->bookpaper_) - scm_gc_mark (b->bookpaper_->self_scm ()); + Paper_book *b = (Paper_book *) SCM_CELL_WORD_1 (smob); + if (b->paper_) + scm_gc_mark (b->paper_->self_scm ()); + if (b->parent_) + scm_gc_mark (b->parent_->self_scm ()); scm_gc_mark (b->header_); + scm_gc_mark (b->header_0_); scm_gc_mark (b->pages_); - return b->lines_; + scm_gc_mark (b->performances_); + scm_gc_mark (b->scores_); + scm_gc_mark (b->bookparts_); + return b->systems_; } int -Paper_book::print_smob (SCM smob, SCM port, scm_print_state*) +Paper_book::print_smob (SCM smob, SCM port, scm_print_state *) { - Paper_book *b = (Paper_book*) ly_cdr (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) +Output_def * +Paper_book::top_paper () { - 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; + Output_def *paper = paper_; + while (paper->parent_) + paper = paper->parent_; + return paper; } 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 ()), - fields); + = 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, ','); + scores_ = scm_cons (s, scores_); +} - SCM lst = SCM_EOL; - for (int i = 0; i < output_formats.size (); i ++) - lst = scm_cons (scm_makfrom0str (output_formats[i].to_str0 ()), lst); - - return lst; +void +Paper_book::add_bookpart (SCM p) +{ + bookparts_ = scm_cons (p, bookparts_); } -/* - TODO: there is too much code dup, and the interface is not - clear. FIXME. - */ void -Paper_book::output (String outname) +Paper_book::add_performance (SCM s) { - if (!score_lines_.size ()) - return; + performances_ = scm_cons (s, performances_); +} - - /* Generate all stencils to trigger font loads. */ - pages (); +long +Paper_book::output_aux (SCM output_channel, + bool is_last, + long *first_page_number, + long *first_performance_number) +{ + long page_nb = 0; + if (scm_is_pair (performances_)) + { + SCM proc = ly_lily_module_constant ("write-performances-midis"); - - SCM formats = ly_output_formats(); - for (SCM s = formats; ly_c_pair_p (s); s = ly_cdr (s)) + scm_call_3 (proc, + performances (), + output_channel, + scm_from_long (*first_performance_number)); + *first_performance_number += scm_ilength (performances_); + } + + if (scm_is_pair (bookparts_)) + { + for (SCM p = bookparts_; scm_is_pair (p); p = scm_cdr (p)) + if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p))) + { + bool is_last_part = (is_last && !scm_is_pair (scm_cdr (p))); + page_nb += pbookpart->output_aux (output_channel, + is_last_part, + first_page_number, + first_performance_number); + } + } + else { - String format = ly_scm2string (ly_car (s)); - - Paper_outputter *out = get_paper_outputter (outname + "." + format, format); - - SCM scopes = SCM_EOL; - if (ly_c_module_p (header_)) - scopes = scm_cons (header_, scopes); - - String func_nm = format; - func_nm = "output-framework-" + func_nm; - - SCM func = ly_scheme_function (func_nm.to_str0 ()); - scm_apply_0 (func, scm_list_n (out->self_scm (), - self_scm (), - scopes, - dump_fields (), - scm_makfrom0str (outname.to_str0 ()), - SCM_UNDEFINED - )) ; - - scm_gc_unprotect_object (out->self_scm ()); + if (scores_ == SCM_EOL) + return 0; + paper_->set_variable (ly_symbol2scm ("first-page-number"), + scm_from_long (*first_page_number)); + paper_->set_variable (ly_symbol2scm ("is-last-bookpart"), + ly_bool2scm (is_last)); + /* Generate all stencils to trigger font loads. */ + page_nb = scm_ilength (pages ()); + *first_page_number += page_nb; } + return page_nb; } - void -Paper_book::classic_output (String outname) +Paper_book::output (SCM output_channel) { + long first_page_number + = robust_scm2int (paper_->c_variable ("first-page-number"), 1); + long first_performance_number = 0; + + /* FIXME: We need a line-width for ps output (framework-ps.scm:92). + If we don't have any, we take the paper-width unless we know + better which line-width to choose (e.g. if there are \bookparts + with different line-widths) and why we need it at all. + */ + + if (paper_->c_variable ("line-width") == SCM_UNDEFINED) + paper_->set_variable (ly_symbol2scm ("line-width"), + paper_->c_variable ("paper-width")); + + if (!output_aux (output_channel, + true, + &first_page_number, + &first_performance_number)) + return; - /* Generate all stencils to trigger font loads. */ - lines (); - - - // 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_lines_[0].header_)) - scopes = scm_cons (score_lines_[0].header_, scopes); - //end ugh + string mod_nm = "scm framework-" + get_output_backend_name (); + SCM mod = scm_c_resolve_module (mod_nm.c_str ()); - Array output_formats = split_string (output_format_global, ','); + if (get_program_option ("print-pages")) + { + SCM framework = ly_module_lookup (mod, + ly_symbol2scm ("output-framework")); + + if (framework != SCM_BOOL_F) + { + SCM func = scm_variable_ref (framework); + scm_apply_0 (func, scm_list_n (output_channel, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + } + else + warning (_f ("program option -dprint-pages not supported by backend `%s'", + get_output_backend_name ())); + } - for (int i = 0; i < output_formats.size (); i++) + if (get_program_option ("preview")) { - String format = output_formats[i]; - String func_nm = format; - func_nm = "output-classic-framework-" + func_nm; - - SCM func = ly_scheme_function (func_nm.to_str0 ()); - - Paper_outputter *out = get_paper_outputter (outname + "." + format, format); - - scm_apply_0 (func, scm_list_n (out->self_scm (), - self_scm (), - scopes, - dump_fields (), - scm_makfrom0str (outname.to_str0 ()), - SCM_UNDEFINED - )) ; - - scm_gc_unprotect_object (out->self_scm ()); + SCM framework + = ly_module_lookup (mod, ly_symbol2scm ("output-preview-framework")); + + if (framework != SCM_BOOL_F) + { + SCM func = scm_variable_ref (framework); + scm_apply_0 (func, scm_list_n (output_channel, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + } + else + warning (_f ("program option -dpreview not supported by backend `%s'", + get_output_backend_name ())); } - - progress_indication ("\n"); } - - - -LY_DEFINE(ly_paper_book_pages, "ly:paper-book-pages", - 1,0,0, - (SCM pb), - "Return pages in book PB.") +void +Paper_book::classic_output_aux (SCM output, + long *first_performance_number) { - return unsmob_paper_book(pb)->pages (); -} + if (scm_is_pair (performances_)) + { + SCM proc = ly_lily_module_constant ("write-performances-midis"); + scm_call_3 (proc, + performances (), + output, + scm_from_long (*first_performance_number)); + *first_performance_number += scm_ilength (performances_); + } + /* Generate all stencils to trigger font loads. */ + systems (); +} -LY_DEFINE(ly_paper_book_scopes, "ly:paper-book-scopes", - 1,0,0, - (SCM book), - "Return pages in paper 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"); - + long first_performance_number = 0; + classic_output_aux (output, &first_performance_number); + 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); + if (ly_is_module (header_0_)) + scopes = scm_cons (header_0_, scopes); -LY_DEFINE(ly_paper_book_lines, "ly:paper-book-lines", - 1,0,0, - (SCM pb), - "Return lines in book PB.") -{ - return unsmob_paper_book (pb)->lines (); -} + 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"); -LY_DEFINE(ly_paper_book_book_paper, "ly:paper-book-book-paper", - 1,0,0, - (SCM pb), - "Return pages in book PB.") -{ - return unsmob_paper_book(pb)->bookpaper_->self_scm (); -} - -/* + func = scm_variable_ref (func); + scm_apply_0 (func, scm_list_n (output, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); -TODO: resurrect more complex user-tweaks for titling . + progress_indication ("\n"); +} -*/ +/* TODO: resurrect more complex user-tweaks for titling? */ Stencil Paper_book::book_title () { - SCM title_func = bookpaper_->lookup_variable (ly_symbol2scm ("book-title")); + SCM title_func = paper_->lookup_variable (ly_symbol2scm ("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, - bookpaper_->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 = bookpaper_->lookup_variable (ly_symbol2scm ("score-title")); + 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_lines_[i].header_)) - scopes = scm_cons (score_lines_[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, - bookpaper_->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::lines () +void +set_page_permission (SCM sys, SCM symbol, SCM permission) { - if (SCM_BOOL_F != lines_) - return lines_; - - lines_ = SCM_EOL; - Stencil title = book_title (); - - if (!title.is_empty ()) + if (Paper_score *ps = dynamic_cast (unsmob_music_output (sys))) { - Paper_line *pl = new Paper_line (title, true); - - lines_ = scm_cons (pl->self_scm (), lines_); - scm_gc_unprotect_object (pl->self_scm ()); + 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); + } } - - int score_count = score_lines_.size (); - for (int i = 0; i < score_count; i++) + else if (Prob *pb = unsmob_prob (sys)) + pb->set_property (symbol, permission); +} + +/* 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)) { - Stencil title = score_title (i); - if (!title.is_empty ()) - { - Paper_line *pl = new Paper_line (title, true); - lines_ = scm_cons (pl->self_scm (), lines_); - scm_gc_unprotect_object (pl->self_scm ()); - } - - if (scm_vector_p (score_lines_[i].lines_) == SCM_BOOL_T) - { - SCM line_list = scm_vector_to_list (score_lines_[i].lines_); // guh. - - line_list = scm_reverse (line_list); - lines_ = scm_append (scm_list_2 (line_list, lines_)); - } + 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); + } } - - lines_ = scm_reverse (lines_); - - int i = 0; - Paper_line * last = 0; - for (SCM s = lines_; s != SCM_EOL; s = ly_cdr (s)) +} + +void +set_labels (SCM sys, SCM labels) +{ + if (Paper_score *ps = dynamic_cast (unsmob_music_output (sys))) { - Paper_line * p = unsmob_paper_line (ly_car (s)); - p->number_ = ++i; - - if (last && last->is_title ()) - { - p->penalty_ = 10000; // ugh, hardcoded. - } - last = p; + vector cols = ps->get_columns (); + if (cols.size ()) + { + Paper_column *col = dynamic_cast (cols[0]); + col->set_property ("labels", + scm_append_x (scm_list_2 (col->get_property ("labels"), + labels))); + Paper_column *col_right + = dynamic_cast (col->find_prebroken_piece (RIGHT)); + col_right->set_property ("labels", + scm_append_x (scm_list_2 (col_right->get_property ("labels"), + labels))); + } } - - - return lines_; + else if (Prob *pb = unsmob_prob (sys)) + pb->set_property ("labels", + scm_append_x (scm_list_2 (pb->get_property ("labels"), + labels))); } - SCM -Paper_book::pages () +Paper_book::get_score_title (SCM header) { - if (SCM_BOOL_F != pages_) - return pages_; - - pages_ = SCM_EOL; - - Output_def *paper = bookpaper_; - - SCM proc = paper->c_variable ("page-breaking"); - pages_ = scm_apply_0 (proc, scm_list_n (lines (), - self_scm (), - SCM_UNDEFINED)); + Stencil title = score_title (header); + if (title.is_empty ()) + title = score_title (header_); + if (!title.is_empty ()) + { + /* + 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 pages_; + return SCM_BOOL_F; } - - - -#if 0 - -static SCM -c_ragged_page_breaks (SCM lines, - Paper_book *book, - Real text_height, - Real first, Real last) +SCM +Paper_book::get_system_specs () { - int page_number = 0; + SCM system_specs = SCM_EOL; - Real book_height =0.; - for (SCM s = lines ; ly_c_pair_p (s); s = ly_cdr (s)) + Stencil title = book_title (); + if (!title.is_empty ()) { - book_height += unsmob_paper_line (ly_car (s))->dim ()[Y_AXIS]; + 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 (); } - int page_count = int (book_height / text_height + 0.5); // ceil? - SCM breaks = SCM_EOL; - Real page_height = text_height + first; - Real h = 0; - int number = 0; - for (SCM s = lines; ly_c_pair_p (s); s = ly_cdr (s)) + 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; + SCM labels = SCM_EOL; + for (SCM s = scm_reverse (scores_); scm_is_pair (s); s = scm_cdr (s)) { - Paper_line *pl = unsmob_paper_line (ly_car (s)); - if (!pl->is_title () && h < page_height) - number++; - h += pl->dim ()[Y_AXIS]; - if (!pl->is_title () && h > page_height) - { - breaks = ly_snoc (scm_int2num (number), breaks); - page_number++; - page_height = text_height + (page_number == page_count) * last; - h = 0; - } - if (ly_cdr (s) == SCM_EOL) - breaks = ly_snoc (scm_int2num (pl->number_), breaks); + if (ly_is_module (scm_car (s))) + { + header = scm_car (s); + if (header_0_ == SCM_EOL) + header_0_ = header; + } + else if (Page_marker *page_marker = unsmob_page_marker (scm_car (s))) + { + /* 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 ())) + { + /* The next element label is to be set */ + labels = scm_cons (page_marker->label (), labels); + } + } + 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); + if (scm_is_pair (labels)) + { + set_labels (scm_car (system_specs), labels); + labels = SCM_EOL; + } + } + 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)); + Prob *first = 0; + Prob *last = 0; + 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")); + ps->set_property ("last-markup-line", SCM_BOOL_F); + ps->set_property ("first-markup-line", SCM_BOOL_F); + + paper_system_set_stencil (ps, *unsmob_stencil (t)); + + SCM footnotes = get_footnotes (unsmob_stencil (t)->expr ()); + ps->set_property ("footnotes", footnotes); + ps->set_property ("is-title", SCM_BOOL_T); + if (list == texts) + first = ps; + else + { + // last line so far, in a multi-line paragraph + last = ps; + //Place closely to previous line, no stretching. + ps->set_property ("tight-spacing", SCM_BOOL_T); + } + system_specs = scm_cons (ps->self_scm (), system_specs); + ps->unprotect (); + + if (scm_is_pair (labels)) + { + set_labels (scm_car (system_specs), labels); + labels = SCM_EOL; + } + // FIXME: figure out penalty. + //set_system_penalty (ps, scores_[i].header_); + } + /* Set properties to avoid widowed/orphaned lines. + Single-line markup_lists are excluded, but in future + we may want to add the case of a very short, single line. */ + if (first && last) + { + last->set_property ("last-markup-line", SCM_BOOL_T); + first->set_property ("first-markup-line", SCM_BOOL_T); + } + } + else + assert (0); } - return scm_vector (breaks); + system_specs = scm_reverse_x (system_specs, SCM_EOL); + return system_specs; } -LY_DEFINE (ly_ragged_page_breaks, "ly:ragged-page-breaks", - 5, 0, 0, (SCM lines, SCM book, SCM text, SCM first, SCM last), - "Return a vector with line numbers of page breaks.") +SCM +Paper_book::systems () { - Paper_book* b = unsmob_paper_book (book); + if (systems_ != SCM_BOOL_F) + return systems_; - SCM_ASSERT_TYPE (scm_pair_p (lines), lines, SCM_ARG1, __FUNCTION__, "list"); - SCM_ASSERT_TYPE (b, book, SCM_ARG2, __FUNCTION__, "Paper_book"); - SCM_ASSERT_TYPE (ly_c_number_p (text), text, SCM_ARG3, __FUNCTION__, "number"); - SCM_ASSERT_TYPE (ly_c_number_p (first), first, SCM_ARG4, __FUNCTION__, "number"); - SCM_ASSERT_TYPE (ly_c_number_p (last), last, SCM_ARG5, __FUNCTION__, "number"); + systems_ = SCM_EOL; + if (scm_is_pair (bookparts_)) + { + SCM system_list = SCM_EOL; + for (SCM p = bookparts_; scm_is_pair (p); p = scm_cdr (p)) + if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p))) + system_list = scm_cons (pbookpart->systems (), system_list); + systems_ = scm_append (scm_reverse_x (system_list, SCM_EOL)); + } + else + { + 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 ()); + + systems_ = scm_reverse_x (system_list, systems_); + } + else + { + systems_ = scm_cons (scm_car (s), systems_); + } + } + systems_ = scm_reverse_x (systems_, SCM_EOL); + + /* backwards compatibility for the old page breaker */ + int i = 0; + Prob *last = 0; + for (SCM s = systems_; scm_is_pair (s); s = scm_cdr (s)) + { + Prob *ps = unsmob_prob (scm_car (s)); + ps->set_property ("number", scm_from_int (++i)); + + 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 c_ragged_page_breaks (lines, b, - ly_scm2double (text), - ly_scm2double (first), ly_scm2double (last)); + return systems_; } -#endif - - -/****************************************************************/ -Score_lines::Score_lines () +SCM +Paper_book::pages () { - lines_ = SCM_EOL; - header_ = SCM_EOL; + if (SCM_BOOL_F != pages_) + return pages_; + + pages_ = SCM_EOL; + if (scm_is_pair (bookparts_)) + { + for (SCM p = bookparts_; scm_is_pair (p); p = scm_cdr (p)) + if (Paper_book *pbookpart = unsmob_paper_book (scm_car (p))) + pages_ = scm_append_x (scm_list_2 (pages_, pbookpart->pages ())); + } + else if (scm_is_pair (scores_)) + { + SCM page_breaking = paper_->c_variable ("page-breaking"); + pages_ = scm_apply_0 (page_breaking, scm_list_1 (self_scm ())); + + // Create all the page stencils. + SCM page_module = scm_c_resolve_module ("scm page"); + SCM page_stencil = scm_c_module_lookup (page_module, "page-stencil"); + page_stencil = scm_variable_ref (page_stencil); + for (SCM pages = pages_; scm_is_pair (pages); pages = scm_cdr (pages)) + scm_apply_1 (page_stencil, scm_car (pages), SCM_EOL); + + // Perform any user-supplied post-processing. + SCM post_process = paper_->c_variable ("page-post-process"); + if (ly_is_procedure (post_process)) + scm_apply_2 (post_process, paper_->self_scm (), pages_, SCM_EOL); + + /* 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)); + } + } + } + return pages_; } -void -Score_lines::gc_mark () +SCM +Paper_book::performances () const { - scm_gc_mark (lines_); - scm_gc_mark (header_); + return scm_reverse (performances_); } -