X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpaper-book.cc;h=ea7c044417063db43700a3c80acbaa816b56cd77;hb=9602a6de93da3d612b7833fdd56168c3c8d19df1;hp=5eedc873fef5c05c455dee3b8be18701868084f5;hpb=b1a521c92717244d4bff11bb0b2b1304e4355956;p=lilypond.git diff --git a/lily/paper-book.cc b/lily/paper-book.cc index 5eedc873fe..ea7c044417 100644 --- a/lily/paper-book.cc +++ b/lily/paper-book.cc @@ -3,285 +3,315 @@ source file of the GNU LilyPond music typesetter - (c) 2004 Jan Nieuwenhuizen + (c) 2004--2005 Jan Nieuwenhuizen */ -#include +#include "paper-book.hh" -#include "ly-module.hh" #include "main.hh" -#include "paper-book.hh" -#include "paper-def.hh" -#include "paper-outputter.hh" +#include "output-def.hh" #include "paper-score.hh" -#include "stencil.hh" +#include "paper-system.hh" +#include "text-item.hh" +#include "warn.hh" -// WIP -- simplistic page interface -// Do we need this at all? SCM, smob? -class Page -{ -public: - Paper_def *paper_; - - SCM lines_; - Stencil *header_; - Stencil *footer_; - - /* actual height filled with text. */ - Real height_; - - //HMMM all this size stuff to paper/paper-outputter? - Real hsize_; - Real vsize_; - Real foot_sep_; - Real head_sep_; - - /* available area for text. */ - Real text_height (); - - Page (Paper_def*); - void output (Paper_outputter*, bool); -}; - -Page::Page (Paper_def *paper) +#include "ly-smobs.icc" + +Paper_book::Paper_book () { - paper_ = paper; - height_ = 0; - header_ = 0; - footer_ = 0; - lines_ = SCM_EOL; - - hsize_ = paper->get_realvar (ly_symbol2scm ("hsize")); - vsize_ = paper->get_realvar (ly_symbol2scm ("vsize")); - head_sep_ = 0; //paper->get_realvar (ly_symbol2scm ("head-sep")); - foot_sep_ = 0; //paper->get_realvar (ly_symbol2scm ("foot-sep")); + header_ = SCM_EOL; + header_0_ = SCM_EOL; + pages_ = SCM_BOOL_F; + scores_ = SCM_EOL; + systems_ = SCM_BOOL_F; + + paper_ = 0; + smobify_self (); } -void -Page::output (Paper_outputter *out, bool is_last) +Paper_book::~Paper_book () { - // TODO: header/footer etc - out->output_scheme (scm_list_1 (ly_symbol2scm ("start-page"))); - for (SCM s = lines_; gh_pair_p (s); s = ly_cdr (s)) - out->output_line (ly_car (s), is_last && gh_pair_p (ly_cdr (s))); - out->output_scheme (scm_list_2 (ly_symbol2scm ("stop-page"), - gh_bool2scm (is_last))); } -Real -Page::text_height () +IMPLEMENT_DEFAULT_EQUAL_P (Paper_book); +IMPLEMENT_SMOBS (Paper_book) + IMPLEMENT_TYPE_P (Paper_book, "ly:paper-book?") + + SCM +Paper_book::mark_smob (SCM smob) { - Real h = vsize_; - if (header_) - h -= header_->extent (Y_AXIS).length () + head_sep_; - if (footer_) - h -= footer_->extent (Y_AXIS).length () + foot_sep_; - return h; + 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->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); -Paper_book *paper_book; + scm_puts ("#<", port); + scm_puts (classname (b), port); + scm_puts (" ", port); + scm_puts (">", port); + return 1; +} -Paper_book::Paper_book () +SCM +dump_fields () +{ + SCM fields = SCM_EOL; + for (int i = dump_header_fieldnames_global.size (); i--;) + fields + = scm_cons (ly_symbol2scm (dump_header_fieldnames_global[i].to_str0 ()), + fields); + return fields; +} + +void +Paper_book::add_score (SCM s) { - protect_ = SCM_EOL; + scores_ = scm_cons (s, scores_); } void Paper_book::output (String outname) { + if (scores_ == SCM_EOL) + return; + /* Generate all stencils to trigger font loads. */ - Link_array *pages = get_pages (); + pages (); - Paper_def *paper = papers_[0]; - Paper_outputter *out = paper->get_paper_outputter (outname); - out->output_metadata (get_scopes (0), paper); - out->output_header (paper); + SCM scopes = SCM_EOL; + if (ly_c_module_p (header_)) + scopes = scm_cons (header_, scopes); + + String mod_nm = "scm framework-" + output_backend_global; - int page_count = pages->size (); - for (int i = 0; i < page_count; i++) - (*pages)[i]->output (out, i + 1 == page_count); + 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 (scm_makfrom0str (outname.to_str0 ()), + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + } - out->output_scheme (scm_list_1 (ly_symbol2scm ("end-output"))); + 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 (scm_makfrom0str (outname.to_str0 ()), + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + } progress_indication ("\n"); } -SCM -Paper_book::get_scopes (int i) +void +Paper_book::classic_output (String outname) { + /* Generate all stencils to trigger font loads. */ + systems (); + SCM scopes = SCM_EOL; - if (headers_[i]) - scopes = scm_cons (headers_[i], scopes); - if (global_headers_[i] && global_headers_[i] != headers_[i]) - scopes = scm_cons (global_headers_[i], scopes); - return scopes; + if (ly_c_module_p (header_)) + scopes = scm_cons (header_, scopes); + + if (ly_c_module_p (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.to_str0 ()); + SCM func = scm_c_module_lookup (mod, "output-classic-framework"); + + func = scm_variable_ref (func); + scm_apply_0 (func, scm_list_n (scm_makfrom0str (outname.to_str0 ()), + self_scm (), + scopes, + dump_fields (), + SCM_UNDEFINED)); + + progress_indication ("\n"); } -Stencil* -Paper_book::get_title (int i) +/* TODO: resurrect more complex user-tweaks for titling? */ +Stencil +Paper_book::book_title () { - SCM make_title = scm_primitive_eval (ly_symbol2scm ("make-title")); - SCM field = (i == 0 ? ly_symbol2scm ("bookTitle") - : ly_symbol2scm ("scoreTitle")); + SCM title_func = paper_->lookup_variable (ly_symbol2scm ("book-title")); + Stencil title; - SCM s = ly_modules_lookup (get_scopes (i), field); - if (s != SCM_UNDEFINED && scm_variable_bound_p (s) == SCM_BOOL_T) - { - Stencil *title = unsmob_stencil (gh_call2 (make_title, - papers_[0]->self_scm (), - scm_variable_ref (s))); - - title->align_to (Y_AXIS, UP); - return title; - } - - return 0; + SCM scopes = SCM_EOL; + if (ly_c_module_p (header_)) + scopes = scm_cons (header_, scopes); + + SCM tit = SCM_EOL; + if (ly_c_procedure_p (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; } -/* - WIP - - FIXME: titling is broken. - - TODO: - * ->SCM? - * decent page breaking algorithm - * header / footer (generate per Page, with page#) - * override: # pages, or pageBreakLines= #'(3 3 4), ? - * what about between-system-breaking, can we junk that? - -*/ -Link_array* -Paper_book::get_pages () +Stencil +Paper_book::score_title (SCM header) { - Link_array *pages = new Link_array; - int score_count = scores_.size (); + SCM title_func = paper_->lookup_variable (ly_symbol2scm ("score-title")); - /* Calculate the full book height. Hmm, can't we cache system - heights while making stencils? */ - Real book_height = 0; - for (int i = 0; i < score_count; i++) - { - Stencil *title = get_title (i); - if (title) - book_height += title->extent (Y_AXIS).length (); + Stencil title; - int line_count = SCM_VECTOR_LENGTH ((SCM) scores_[i]); - for (int j = 0; j < line_count; j++) - { - SCM line = scm_vector_ref ((SCM) scores_[i], scm_int2num (j)); - book_height += ly_scm2offset (ly_car (line))[Y_AXIS]; - } - } + SCM scopes = SCM_EOL; + if (ly_c_module_p (header_)) + scopes = scm_cons (header_, scopes); + + if (ly_c_module_p (header)) + scopes = scm_cons (header, scopes); + + SCM tit = SCM_EOL; + if (ly_c_procedure_p (title_func)) + tit = scm_call_2 (title_func, + paper_->self_scm (), + scopes); - Paper_def *paper = papers_[0]; - Page *page = new Page (paper); - fprintf (stderr, "book_height: %f\n", book_height); - fprintf (stderr, "vsize: %f\n", page->vsize_); - fprintf (stderr, "pages: %f\n", book_height / page->text_height ()); + if (unsmob_stencil (tit)) + title = *unsmob_stencil (tit); - /* Simplistic page breaking. */ - Real text_height = page->text_height (); - for (int i = 0; i < score_count; i++) + if (!title.is_empty ()) + title.align_to (Y_AXIS, UP); + + return title; +} + +void +set_system_penalty (Paper_system *ps, SCM header) +{ + if (ly_c_module_p (header)) { - Stencil *title = get_title (i); - if (title) - book_height += title->extent (Y_AXIS).length (); - Real h = 0; - if (title) - h = title->extent (Y_AXIS).length (); - - int line_count = SCM_VECTOR_LENGTH ((SCM) scores_[i]); - 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 line = scm_vector_ref ((SCM) scores_[i], scm_int2num (j)); - h += ly_scm2offset (ly_car (line))[Y_AXIS]; - if (page->height_ + h > text_height) - { - pages->push (page); - page = new Page (paper); - } - if (page->height_ + h <= text_height || page->height_ == 0) - { - if (j == 0 && title) - { - Offset dim = Offset (title->extent (X_AXIS).length (), - title->extent (Y_AXIS).length ()); - page->lines_ - = ly_snoc (scm_cons (ly_offset2scm (dim), - scm_list_1 - (scm_cons - (ly_offset2scm (Offset (0, 0)), - title->smobbed_copy ()))), - page->lines_); - } - page->lines_ = ly_snoc (line, page->lines_); - page->height_ += h; - h = 0; - } + ps->break_before_penalty_ = to_boolean (SCM_VARIABLE_REF (force)) + ? -10000 + : 10000; } } - - pages->push (page); - return pages; } -void -Paper_book::classic_output (String outname) +SCM +Paper_book::systems () { - Paper_outputter *out = papers_.top ()->get_paper_outputter (outname); - int count = scores_.size (); - - out->output_metadata (get_scopes (count - 1), papers_.top ()); - out->output_header (papers_.top ()); - - int line_count = SCM_VECTOR_LENGTH ((SCM) scores_.top ()); - for (int i = 0; i < line_count; i++) - out->output_line (scm_vector_ref ((SCM) scores_.top (), scm_int2num (i)), - i == line_count - 1); - - out->output_scheme (scm_list_1 (ly_symbol2scm ("end-output"))); - progress_indication ("\n"); -} + if (systems_ != SCM_BOOL_F) + return systems_; + systems_ = SCM_EOL; + Stencil title = book_title (); -#include "ly-smobs.icc" + if (!title.is_empty ()) + { + Paper_system *ps = new Paper_system (title, true); + set_system_penalty (ps, header_); -IMPLEMENT_DEFAULT_EQUAL_P (Paper_book); -IMPLEMENT_SIMPLE_SMOBS (Paper_book) -IMPLEMENT_TYPE_P (Paper_book, "ly:paper_book?") + systems_ = scm_cons (ps->self_scm (), systems_); + scm_gc_unprotect_object (ps->self_scm ()); + } -SCM -Paper_book::mark_smob (SCM smob) -{ - Paper_book *b = (Paper_book*) SCM_CELL_WORD_1 (smob); + SCM page_properties + = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"), + paper_->self_scm ()); -#if 0 //TODO - scm_gc_mark (b->scores_); - scm_gc_mark (b->global_headers_); - scm_gc_mark (b->headers_); - scm_gc_mark (b->papers_); -#endif + SCM header = SCM_EOL; + for (SCM s = scm_reverse (scores_); s != SCM_EOL; s = scm_cdr (s)) + { + if (ly_c_module_p (scm_car (s))) + { + header = scm_car (s); + if (header_0_ == SCM_EOL) + header_0_ = header; + } + else if (scm_is_vector (scm_car (s))) + { + 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 ()); + set_system_penalty (ps, header); + } + header = SCM_EOL; - return SCM_EOL; -} + SCM system_list = scm_vector_to_list (scm_car (s)); + system_list = scm_reverse (system_list); + systems_ = scm_append (scm_list_2 (system_list, systems_)); + } + else if (Text_interface::markup_p (scm_car (s))) + { + SCM t = Text_interface::interpret_markup (paper_->self_scm (), + page_properties, + scm_car (s)); + // FIXME: title=true? + Paper_system *ps = new Paper_system (*unsmob_stencil (t), true); + systems_ = scm_cons (ps->self_scm (), systems_); + scm_gc_unprotect_object (ps->self_scm ()); + // FIXME: figure out penalty. + //set_system_penalty (ps, scores_[i].header_); + } + else + assert (0); + } -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); - return 1; + systems_ = scm_reverse (systems_); + + int i = 0; + Paper_system *last = 0; + for (SCM s = systems_; s != SCM_EOL; s = scm_cdr (s)) + { + Paper_system *ps = unsmob_paper_system (scm_car (s)); + ps->number_ = ++i; + + if (last + && last->is_title () + && !ps->break_before_penalty_) + ps->break_before_penalty_ = 10000; + last = ps; + } + + return systems_; } SCM -Paper_book::smobbed_copy () const +Paper_book::pages () { - Paper_book *b = new Paper_book (*this); - return b->smobbed_self (); + if (SCM_BOOL_F != 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_; }