X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fline-of-score.cc;h=9c70f62adb98d0e8ee5c2200826270b801a93927;hb=6bf1606d827527f02953add0988a4fbbf0dc0c4e;hp=3bba1d479bd35869be7f12f57e8ef71404326c94;hpb=ad7defd5f5a3d0151a711555c2d680c56ef559c7;p=lilypond.git diff --git a/lily/line-of-score.cc b/lily/line-of-score.cc index 3bba1d479b..9c70f62adb 100644 --- a/lily/line-of-score.cc +++ b/lily/line-of-score.cc @@ -3,38 +3,123 @@ source file of the GNU LilyPond music typesetter - (c) 1996--2000 Han-Wen Nienhuys + (c) 1996--2001 Han-Wen Nienhuys */ +#include "input-smob.hh" +#include "axis-group-interface.hh" +#include "debug.hh" #include "line-of-score.hh" +#include "main.hh" +#include "paper-column.hh" #include "paper-def.hh" #include "paper-outputter.hh" -#include "paper-column.hh" #include "paper-score.hh" +#include "string.hh" #include "warn.hh" -#include "main.hh" -#include "debug.hh" +#include "dimensions.hh" +#include "molecule.hh" +#include "all-font-metrics.hh" -Line_of_score::Line_of_score() +// todo: use map. +void +fixup_refpoints (SCM s) { - set_elt_property ("columns", SCM_EOL); - set_axes (Y_AXIS,X_AXIS); + for (; gh_pair_p (s); s = gh_cdr (s)) + { + Grob::fixup_refpoint (gh_car (s)); + } } +Line_of_score::Line_of_score (SCM s) + : Spanner (s) +{ + rank_i_ = 0; + + Axis_group_interface::set_interface (this); + Axis_group_interface::set_axes (this, Y_AXIS,X_AXIS); +} + +int +Line_of_score::element_count () const +{ + return scm_ilength (get_grob_property ("all-elements")); +} + +void +Line_of_score::typeset_grob (Grob * elem_p) +{ + elem_p->pscore_l_ = pscore_l_; + Pointer_group_interface::add_element (this, "all-elements",elem_p); + scm_gc_unprotect_object (elem_p->self_scm ()); +} void Line_of_score::output_lines () { + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + unsmob_grob (gh_car (s))->do_break_processing (); + } + /* + fixups must be done in broken line_of_scores, because new elements + are put over there. */ + int count = 0; + for (int i=0; i < broken_into_l_arr_.size (); i++) + { + Grob *se = broken_into_l_arr_[i]; + SCM all = se->get_grob_property ("all-elements"); + for (SCM s = all; gh_pair_p (s); s = gh_cdr (s)) + { + fixup_refpoint (gh_car (s)); + } + count += scm_ilength (all); + } + + + /* + needed for doing items. + */ + fixup_refpoints (get_grob_property ("all-elements")); + + + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + unsmob_grob (gh_car (s))->handle_broken_dependencies (); + } + handle_broken_dependencies (); + + if (verbose_global_b) + progress_indication (_f ("Element count %d.", count + element_count ())); + + for (int i=0; i < broken_into_l_arr_.size (); i++) { Line_of_score *line_l = dynamic_cast (broken_into_l_arr_[i]); - progress_indication ("["); - line_l->post_processing (); - progress_indication (to_str (i)); - line_l->output_line (i + 1 == broken_into_l_arr_.size ()); - progress_indication ("]"); + if (verbose_global_b) + progress_indication ("["); + line_l->post_processing (i+1 == broken_into_l_arr_.size ()); + + if (verbose_global_b) + { + progress_indication (to_str (i)); + progress_indication ("]"); + } + + if (i < broken_into_l_arr_.size () - 1) + { + SCM lastcol = gh_car (line_l->get_grob_property ("columns")); + Grob* e = unsmob_grob (lastcol); + SCM inter = e->get_grob_property ("between-system-string"); + if (gh_string_p (inter)) + { + pscore_l_->outputter_l_->output_string (inter); + } + } } } @@ -44,56 +129,289 @@ Line_of_score::break_into_pieces (Array const &breaking) { for (int i=0; i < breaking.size (); i++) { - Line_of_score *line_l = dynamic_cast (clone()); + Line_of_score *line_l = dynamic_cast (clone ()); line_l->rank_i_ = i; - Link_array c (breaking[i].cols_); - pscore_l_->typeset_element (line_l); - line_l->set_bound(LEFT,c[0]); - line_l->set_bound(RIGHT,c.top ()); - for (int j=0; j < c.size(); j++) + // line_l->set_immutable_grob_property ("rank", gh_int2scm (i)); + Link_array c (breaking[i].cols_); + pscore_l_->typeset_line (line_l); + + line_l->set_bound (LEFT,c[0]); + line_l->set_bound (RIGHT,c.top ()); + for (int j=0; j < c.size (); j++) { c[j]->translate_axis (breaking[i].config_[j],X_AXIS); - c[j]->line_l_ = line_l; + dynamic_cast (c[j])->line_l_ = line_l; } broken_into_l_arr_.push (line_l); } } + +#define GLOBAL_SYMBOL(cname, name) \ +SCM cname ; \ +void \ +cname ## _init_func () \ +{ \ + cname = ly_symbol2scm (name); \ + scm_permanent_object (cname); \ +} \ +ADD_SCM_INIT_FUNC (cname,cname ## _init_func);\ + + +GLOBAL_SYMBOL (offset_sym , "translate-molecule"); +GLOBAL_SYMBOL (placebox_sym , "placebox"); +GLOBAL_SYMBOL (combine_sym , "combine-molecule"); +GLOBAL_SYMBOL (no_origin_sym , "no-origin"); +GLOBAL_SYMBOL (define_origin_sym , "define-origin"); + + + +void +Line_of_score::output_molecule (SCM expr, Offset o) +{ + + while (1) + { + if (!gh_pair_p (expr)) + return; + + SCM head =gh_car (expr); + if (unsmob_input (head)) + { + Input * ip = unsmob_input (head); + + + pscore_l_->outputter_l_->output_scheme (gh_list (define_origin_sym, + ly_str02scm (ip->file_str ().ch_C ()), + gh_int2scm (ip->line_number ()), + gh_int2scm (ip->column_number ()), + SCM_UNDEFINED)); + expr = gh_cadr (expr); + } + else if (head == no_origin_sym) + { + pscore_l_->outputter_l_->output_scheme (gh_list (no_origin_sym, SCM_UNDEFINED)); + expr = gh_cadr (expr); + } + else if (head == offset_sym) + { + o += ly_scm2offset (gh_cadr (expr)); + expr = gh_caddr (expr); + } + else if (head == combine_sym) + { + output_molecule (gh_cadr (expr), o); + expr = gh_caddr (expr); + } + else + { + pscore_l_->outputter_l_-> + output_scheme (gh_list (placebox_sym, + gh_double2scm (o[X_AXIS]), + gh_double2scm (o[Y_AXIS]), + expr, + SCM_UNDEFINED)); + + return; + } + } +} + +void +Line_of_score::output_scheme (SCM s) +{ + pscore_l_->outputter_l_->output_scheme (s); +} + void Line_of_score::add_column (Paper_column*p) { - set_elt_property ("columns", - gh_cons (p->self_scm_, get_elt_property ("columns"))); - add_element (p); + Grob *me = this; + SCM cs = me->get_grob_property ("columns"); + Grob * prev = gh_pair_p (cs) ? unsmob_grob (gh_car (cs)) : 0; + + p->rank_i_ = prev ? Paper_column::rank_i (prev) + 1 : 0; + + me->set_grob_property ("columns", gh_cons (p->self_scm (), cs)); + + Axis_group_interface::add_element (me, p); } + + +/* + TODO: use scm_map iso. for loops. + */ void -Line_of_score::do_print() const +Line_of_score::pre_processing () { - Spanner::do_print(); - Axis_group_spanner::do_print (); + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + unsmob_grob (gh_car (s))->discretionary_processing (); + + if (verbose_global_b) + progress_indication (_f ("Element count %d ", element_count ())); + + + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + unsmob_grob (gh_car (s))->handle_prebroken_dependencies (); + + fixup_refpoints (get_grob_property ("all-elements")); + + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + Grob* sc = unsmob_grob (gh_car (s)); + sc->calculate_dependencies (PRECALCED, PRECALCING, ly_symbol2scm ("before-line-breaking-callback")); + } + + progress_indication ("\n" + _ ("Calculating column positions...") + " "); + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + Grob * e = unsmob_grob (gh_car (s)); + SCM proc = e->get_grob_property ("spacing-procedure"); + if (gh_procedure_p (proc)) + gh_call1 (proc, e->self_scm ()); + } } void -Line_of_score::output_line (bool last_line) +Line_of_score::post_processing (bool last_line) { - Interval i(extent(Y_AXIS)); - if (i.empty_b()) + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + Grob* sc = unsmob_grob (gh_car (s)); + sc->calculate_dependencies (POSTCALCED, POSTCALCING, + ly_symbol2scm ("after-line-breaking-callback")); + } + + Interval i (extent (this, Y_AXIS)); + if (i.empty_b ()) programming_error ("Huh? Empty Line_of_score?"); else translate_axis (- i[MAX], Y_AXIS); + + Real height = i.length (); + if (height > 50 CM) + { + programming_error ("Improbable system height"); + height = 50 CM; + } + + /* + generate all molecules to trigger all font loads. + + (ugh. This is not very memory efficient.) */ + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + unsmob_grob (gh_car (s))->get_molecule (); + } + /* + font defs; + */ + SCM font_names = ly_quote_scm (paper_l ()->font_descriptions ()); + output_scheme (gh_list (ly_symbol2scm ("define-fonts"), + font_names, + SCM_UNDEFINED)); + + /* + line preamble. + */ + output_scheme (gh_list (ly_symbol2scm ("start-line"), + gh_double2scm (height), + SCM_UNDEFINED)); + + /* Output elements in three layers, 0, 1, 2. + The default layer is 1. */ + for (int i = 0; i < 3; i++) + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); + s = gh_cdr (s)) + { + Grob *sc = unsmob_grob (gh_car (s)); + Molecule *m = sc->get_molecule (); + if (!m) + continue; + + SCM s = sc->get_grob_property ("layer"); + int layer = gh_number_p (s) ? gh_scm2int (s) : 1; + if (layer != i) + continue; + + Offset o (sc->relative_coordinate (this, X_AXIS), + sc->relative_coordinate (this, Y_AXIS)); + + SCM e = sc->get_grob_property ("extra-offset"); + if (gh_pair_p (e)) + { + o[X_AXIS] += gh_scm2double (gh_car (e)); + o[Y_AXIS] += gh_scm2double (gh_cdr (e)); + } + + output_molecule (m->get_expr (), o); + } - pscore_l_->outputter_l_->start_line (i.length ()); - Super_element::output_all (); if (last_line) - pscore_l_->outputter_l_->stop_last_line(); + { + output_scheme (gh_list (ly_symbol2scm ("stop-last-line"), SCM_UNDEFINED)); + } else - pscore_l_->outputter_l_->stop_line (); + { + output_scheme (gh_list (ly_symbol2scm ("stop-line"), SCM_UNDEFINED)); + } } -int -Line_of_score::compare (Line_of_score* const &p1,Line_of_score* const &p2) + +Link_array +Line_of_score::broken_col_range (Item const*l, Item const*r) const { - return p1->rank_i_ - p2->rank_i_; + Link_array ret; + + l = l->column_l (); + r = r->column_l (); + SCM s = get_grob_property ("columns"); + + while (gh_pair_p (s) && gh_car (s) != r->self_scm ()) + s = gh_cdr (s); + + if (gh_pair_p (s)) + s = gh_cdr (s); + + while (gh_pair_p (s) && gh_car (s) != l->self_scm ()) + { + Paper_column*c = dynamic_cast (unsmob_grob (gh_car (s))); + if (Item::breakable_b (c) && !c->line_l_) + ret.push (c); + + s = gh_cdr (s); + } + + ret.reverse (); + return ret; } + +/** + Return all columns, but filter out any unused columns , since they might + disrupt the spacing problem. + */ +Link_array +Line_of_score::column_l_arr ()const +{ + Link_array acs + = Pointer_group_interface__extract_elements (this, (Grob*) 0, "columns"); + bool bfound = false; + for (int i= acs.size (); i -- ;) + { + bool brb = Item::breakable_b (acs[i]); + bfound = bfound || brb; + + /* + the last column should be breakable. Weed out any columns that + seem empty. We need to retain breakable columns, in case + someone forced a breakpoint. + */ + if (!bfound || !Paper_column::used_b (acs[i])) + acs.del (i); + } + return acs; +} +