X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpaper-book.cc;h=8ef498aaec847516fe388469e4d3f9db22e25bd8;hb=3152e2de8181f567baa0eafd01970ba3ba4ede02;hp=8fbc9fbd2ddd6d1fe69c7c1a455ea73db988f3b8;hpb=853303f6ec72641e842d58e68bc304c5afffcd13;p=lilypond.git diff --git a/lily/paper-book.cc b/lily/paper-book.cc index 8fbc9fbd2d..8ef498aaec 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -3,42 +3,30 @@ source file of the GNU LilyPond music typesetter - (c) 2004 Jan Nieuwenhuizen + (c) 2004--2006 Jan Nieuwenhuizen */ -#include "ly-module.hh" -#include "main.hh" -#include "page.hh" #include "paper-book.hh" -#include "paper-def.hh" -#include "paper-outputter.hh" -#include "paper-line.hh" + +#include "main.hh" +#include "output-def.hh" #include "paper-score.hh" -#include "stencil.hh" +#include "paper-system.hh" +#include "text-interface.hh" #include "warn.hh" -// JUNKME -SCM -stencil2line (Stencil stil, bool is_title = false) -{ - static SCM z; - if (!z) - z = scm_permanent_object (ly_offset2scm (Offset (0, 0))); - Offset dim = Offset (stil.extent (X_AXIS).length (), - stil.extent (Y_AXIS).length ()); - Paper_line *pl = new Paper_line (dim, scm_cons (stil.smobbed_copy (), - SCM_EOL), - -10001 * is_title, is_title); - - return scm_gc_unprotect_object (pl->self_scm ()); -} - +#include "ly-smobs.icc" Paper_book::Paper_book () { - copyright_ = SCM_EOL; - tagline_ = SCM_EOL; - + header_ = SCM_EOL; + header_0_ = SCM_EOL; + pages_ = SCM_BOOL_F; + scores_ = SCM_EOL; + performances_ = SCM_EOL; + systems_ = SCM_BOOL_F; + + paper_ = 0; smobify_self (); } @@ -46,326 +34,359 @@ 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 (); - - scm_gc_mark (b->copyright_); - return b->tagline_; + 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*) 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; } +SCM +dump_fields () +{ + SCM fields = SCM_EOL; + for (vsize i = dump_header_fieldnames_global.size (); i--;) + fields + = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].c_str ()), + fields); + return fields; +} + +void +Paper_book::add_score (SCM s) +{ + scores_ = scm_cons (s, scores_); +} + void -Paper_book::output (String outname) +Paper_book::add_performance (SCM s) { - if (!score_lines_.size ()) - // FIXME: no end-output? + performances_ = scm_cons (s, performances_); +} + +void +Paper_book::output (SCM output_channel) +{ + if (scm_is_pair (performances_)) + { + SCM proc = ly_lily_module_constant ("paper-book-write-midis"); + + scm_call_2 (proc, self_scm (), output_channel); + } + + if (scores_ == SCM_EOL) return; - + /* Generate all stencils to trigger font loads. */ - SCM pages = this->pages (); + pages (); + + SCM scopes = SCM_EOL; + if (ly_is_module (header_)) + scopes = scm_cons (header_, scopes); - Paper_def *paper = score_lines_[0].paper_; - Paper_outputter *out = paper->get_paper_outputter (outname); - int page_count = scm_ilength (pages); - out->output_header (paper->bookpaper_, scopes (0), page_count, false); + string mod_nm = "scm framework-" + output_backend_global; - for (SCM s = pages; s != SCM_EOL; s = ly_cdr (s)) + SCM mod = scm_c_resolve_module (mod_nm.c_str ()); + if (make_print) { - Page *p = unsmob_page (ly_car (s)); - progress_indication ("[" + to_string (p->number_)); - out->output_page (p, ly_cdr (s) == SCM_EOL); - progress_indication ("]"); + SCM func = scm_c_module_lookup (mod, "output-framework"); + + func = scm_variable_ref (func); + scm_apply_0 (func, scm_list_n (output_channel, + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); } - out->output_scheme (scm_list_1 (ly_symbol2scm ("end-output"))); - progress_indication ("\n"); + if (make_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)); + } } -SCM -Paper_book::scopes (int i) +void +Paper_book::classic_output (SCM output) { - return score_lines_[i].scopes (); -} + /* Generate all stencils to trigger font loads. */ + systems (); + + SCM scopes = SCM_EOL; + if (ly_is_module (header_)) + scopes = scm_cons (header_, scopes); + + if (ly_is_module (header_0_)) + scopes = scm_cons (header_0_, scopes); + string format = output_backend_global; + 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? */ Stencil -Paper_book::title (int i) +Paper_book::book_title () { - /* - TODO: get from book-paper definition. - */ - SCM user_title = ly_scheme_function ("user-title"); - SCM book_title = ly_scheme_function ("book-title"); - SCM score_title = ly_scheme_function ("score-title"); - SCM field = (i == 0 ? ly_symbol2scm ("bookTitle") - : ly_symbol2scm ("scoreTitle")); - + SCM title_func = paper_->lookup_variable (ly_symbol2scm ("book-title")); Stencil title; - SCM scopes = this->scopes (i); - SCM s = ly_modules_lookup (scopes, field); - if (s != SCM_UNDEFINED && scm_variable_bound_p (s) == SCM_BOOL_T) - title = *unsmob_stencil (scm_call_2 (user_title, - score_lines_[0].paper_->self_scm (), - scm_variable_ref (s))); - else - title = *unsmob_stencil (scm_call_2 (i == 0 ? book_title : score_title, - score_lines_[0].paper_->self_scm (), - scopes)); + + SCM scopes = SCM_EOL; + if (ly_is_module (header_)) + scopes = scm_cons (header_, scopes); + + SCM tit = SCM_EOL; + if (ly_is_procedure (title_func)) + tit = scm_call_2 (title_func, + paper_->self_scm (), + scopes); + + if (unsmob_stencil (tit)) + title = *unsmob_stencil (tit); + if (!title.is_empty ()) title.align_to (Y_AXIS, UP); - + return title; } -void -Paper_book::classic_output (String outname) +Stencil +Paper_book::score_title (SCM header) { - int count = score_lines_.size (); - Paper_def * p = score_lines_.top ().paper_; - Paper_outputter *out = p->get_paper_outputter (outname); - out->output_header (p->bookpaper_, scopes (count - 1), 0, true); - - SCM top_lines = score_lines_.top ().lines_; - Paper_line *first = unsmob_paper_line (scm_vector_ref (top_lines, - scm_int2num (0))); - Offset o (0, -0.5 * first->dim ()[Y_AXIS]); - int line_count = SCM_VECTOR_LENGTH (top_lines); - for (int i = 0; i < line_count; i++) - { - /* In classic compatibility TeX tracks how large things are, and - advances the Y pos for us. If we advance it too, we get too - much space. + SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title")); - FIXME: vague... why is TeX is different from other ouput - backends, why not fix the TeX backend? -- jcn */ - if (output_format_global == "tex") - o = Offset (0, 0); + Stencil title; - out->output_line (scm_vector_ref (top_lines, scm_int2num (i)), - &o, i == line_count - 1); - } - - out->output_scheme (scm_list_1 (ly_symbol2scm ("end-output"))); - progress_indication ("\n"); + SCM scopes = SCM_EOL; + if (ly_is_module (header_)) + scopes = scm_cons (header_, scopes); + + if (ly_is_module (header)) + scopes = scm_cons (header, scopes); + + SCM tit = SCM_EOL; + if (ly_is_procedure (title_func)) + tit = scm_call_2 (title_func, + paper_->self_scm (), + scopes); + + if (unsmob_stencil (tit)) + title = *unsmob_stencil (tit); + + if (!title.is_empty ()) + title.align_to (Y_AXIS, UP); + + return title; } -/* calculate book height, #lines, stencils. */ void -Paper_book::init () +set_system_penalty (Prob *ps, SCM header) { - int score_count = score_lines_.size (); - - /* Calculate the full book height. Hmm, can't we cache system - heights while making stencils? */ - height_ = 0; - for (int i = 0; i < score_count; i++) + if (ly_is_module (header)) { - Stencil title = this->title (i); - if (!title.is_empty ()) - height_ += title.extent (Y_AXIS).length (); - - int line_count = SCM_VECTOR_LENGTH (score_lines_[i].lines_); - for (int j = 0; j < line_count; j++) + SCM force = ly_module_lookup (header, ly_symbol2scm ("breakbefore")); + if (SCM_VARIABLEP (force) + && scm_is_bool (SCM_VARIABLE_REF (force))) { - SCM s = scm_vector_ref ((SCM) score_lines_[i].lines_, scm_int2num (j)); - height_ += unsmob_paper_line (s)->dim ()[Y_AXIS]; + ps->set_property ("penalty", + scm_from_int(to_boolean (SCM_VARIABLE_REF (force)) + ? -10000 + : 10000)); } } - - Paper_def *paper = score_lines_[0].paper_; - SCM scopes = this->scopes (0); - - SCM make_tagline = paper->c_variable ("make-tagline"); - tagline_ = scm_call_2 (make_tagline, paper->self_scm (), scopes); - Real tag_height = 0; - if (Stencil *s = unsmob_stencil (tagline_)) - tag_height = s->extent (Y_AXIS).length (); - height_ += tag_height; - - SCM make_copyright = paper->c_variable ("make-copyright"); - copyright_ = scm_call_2 (make_copyright, paper->self_scm (), scopes); - Real copy_height = 0; - if (Stencil *s = unsmob_stencil (copyright_)) - copy_height = s->extent (Y_AXIS).length (); - height_ += copy_height; } + SCM -Paper_book::lines () +Paper_book::get_score_title (SCM header) { - int score_count = score_lines_.size (); - SCM lines = SCM_EOL; - for (int i = 0; i < score_count; i++) + Stencil title = score_title (header); + if (title.is_empty ()) + title = score_title (header_); + if (!title.is_empty ()) { - Stencil title = this->title (i); - if (!title.is_empty ()) - lines = ly_snoc (stencil2line (title, true), lines); - lines = scm_append (scm_list_2 (lines, scm_vector_to_list (score_lines_[i].lines_))); + /* + 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); + set_system_penalty (ps, header); + + return ps->self_scm(); } - - //debug helper; ughr - int i = 0; - for (SCM s = lines; s != SCM_EOL; s = ly_cdr (s)) - unsmob_paper_line (ly_car (s))->number_ = ++i; - return lines; + + return SCM_BOOL_F; } + SCM -Paper_book::pages () +Paper_book::get_system_specs () { - init (); - Page::page_count_ = 0; - Paper_def *paper = score_lines_[0].paper_; - Page *page = new Page (paper, 1); - - Real text_height = page->text_height (); - - Real copy_height = 0; - if (Stencil *s = unsmob_stencil (copyright_)) - copy_height = s->extent (Y_AXIS).length (); - - Real tag_height = 0; - if (Stencil *s = unsmob_stencil (tagline_)) - tag_height = s->extent (Y_AXIS).length (); - - SCM all = lines (); - SCM proc = paper->c_variable ("page-breaking"); - SCM breaks = scm_apply_0 (proc, scm_list_n (all, scm_make_real (height_), - scm_make_real (text_height), - scm_make_real (-copy_height), - scm_make_real (-tag_height), - SCM_UNDEFINED)); - - /* Copyright on first page. */ - if (unsmob_stencil (copyright_)) - page->copyright_ = copyright_; - - SCM pages = SCM_EOL; - int page_count = SCM_VECTOR_LENGTH ((SCM) breaks); - int line = 1; - for (int i = 0; i < page_count; i++) + SCM system_specs = SCM_EOL; + + Stencil title = book_title (); + if (!title.is_empty ()) { - if (i) - page = new Page (paper, i + 1); + SCM props = paper_->lookup_variable (ly_symbol2scm ("book-title-properties")); + Prob *ps = make_paper_system (props); + paper_system_set_stencil (ps, title); + set_system_penalty (ps, header_); + + system_specs = scm_cons (ps->self_scm (), system_specs); + ps->unprotect (); + } - int next = i + 1 < page_count - ? ly_scm2int (scm_vector_ref (breaks, scm_int2num (i))) : 0; - while ((!next && all != SCM_EOL) || line <= next) + SCM page_properties + = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"), + paper_->self_scm ()); + + SCM header = SCM_EOL; + for (SCM s = scm_reverse (scores_); s != SCM_EOL; s = scm_cdr (s)) + { + if (ly_is_module (scm_car (s))) + { + header = scm_car (s); + if (header_0_ == SCM_EOL) + header_0_ = header; + } + else if (Music_output *mop = unsmob_music_output (scm_car (s))) { - SCM s = ly_car (all); - page->lines_ = ly_snoc (s, page->lines_); - page->height_ += unsmob_paper_line (s)->dim ()[Y_AXIS]; - page->line_count_++; - all = ly_cdr (all); - line++; + if (Paper_score *pscore = dynamic_cast (mop)) + { + SCM title = get_score_title (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 + */ + } } - pages = scm_cons (page->self_scm (), pages); + else if (Text_interface::is_markup (scm_car (s))) + { + SCM t = Text_interface::interpret_markup (paper_->self_scm (), + page_properties, + scm_car (s)); + + // TODO: init props + Prob *ps = make_paper_system (SCM_EOL); + paper_system_set_stencil (ps, *unsmob_stencil (t)); + ps->set_property ("is-title", SCM_BOOL_T); + 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); } - /* Tagline on last page. */ - if (unsmob_stencil (tagline_)) - page->tagline_ = tagline_; - - return scm_reverse (pages); + system_specs = scm_reverse_x (system_specs, SCM_EOL); + return system_specs; } -static SCM -c_ragged_page_breaks (SCM lines, Real book_height, Real text_height, - Real first, Real last) +SCM +Paper_book::systems () { - int page_number = 0; - int page_count = int (book_height / text_height + 0.5); - SCM breaks = SCM_EOL; - Real page_height = text_height + first; - Real h = 0; - int number = 0; - for (SCM s = lines; s != SCM_EOL; s = ly_cdr (s)) + 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)) { - 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) + 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 { - breaks = ly_snoc (scm_int2num (number), breaks); - page_number++; - page_height = text_height + (page_number == page_count) * last; - h = 0; + systems_ = scm_cons (scm_car (s), systems_); } - if (ly_cdr (s) == SCM_EOL) - breaks = ly_snoc (scm_int2num (pl->number_), breaks); } + + systems_ = scm_reverse (systems_); - return scm_vector (breaks); -} + int i = 0; + Prob *last = 0; + for (SCM s = systems_; s != SCM_EOL; 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; + } -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_ASSERT_TYPE (scm_pair_p (lines), lines, SCM_ARG1, __FUNCTION__, "list"); - SCM_ASSERT_TYPE (ly_c_number_p (book), book, SCM_ARG2, __FUNCTION__, "real"); - SCM_ASSERT_TYPE (ly_c_number_p (text), text, SCM_ARG2, __FUNCTION__, "real"); - SCM_ASSERT_TYPE (ly_c_number_p (first), first, SCM_ARG2, __FUNCTION__, "real"); - SCM_ASSERT_TYPE (ly_c_number_p (last), last, SCM_ARG2, __FUNCTION__, "real"); - - return c_ragged_page_breaks (lines, - ly_scm2double (book), ly_scm2double (text), - ly_scm2double (first), ly_scm2double (last)); + return systems_; } -/****************************************************************/ - -Score_lines::Score_lines () +SCM +Paper_book::pages () { - lines_ = SCM_EOL; - global_header_ = SCM_EOL; - header_ = SCM_EOL; - paper_ = 0; -} + if (SCM_BOOL_F != pages_) + return pages_; -void -Score_lines::gc_mark () -{ - scm_gc_mark (lines_); - scm_gc_mark (global_header_); - scm_gc_mark (header_); - if (paper_) - scm_gc_mark (paper_->self_scm ()); + pages_ = SCM_EOL; + SCM proc = paper_->c_variable ("page-breaking"); + pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ())); + return pages_; } - -SCM -Score_lines::scopes () +SCM +Paper_book::performances () const { - SCM scopes = SCM_EOL; - if (header_) - scopes = scm_cons (header_, scopes); - if (SCM_MODULEP(global_header_) - && global_header_ != header_) - scopes = scm_cons (global_header_, scopes); - - return scopes; + return scm_reverse (performances_); }