X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fline-of-score.cc;h=464cd4e6abd75458a467a484181d8e0869f2731d;hb=5f68ba5ca0edd64f0f6723e65c27993c2dfb1e96;hp=dc78eb09da95770d2acfbb9acd23f7754e53ec3a;hpb=0349917b7d91f01c8e5a3461185c850820e51710;p=lilypond.git diff --git a/lily/line-of-score.cc b/lily/line-of-score.cc index dc78eb09da..464cd4e6ab 100644 --- a/lily/line-of-score.cc +++ b/lily/line-of-score.cc @@ -3,9 +3,10 @@ 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" @@ -20,41 +21,47 @@ #include "molecule.hh" #include "all-font-metrics.hh" -Line_of_score::Line_of_score() - : Spanner (SCM_EOL) +// todo: use map. +void +fixup_refpoints (SCM s) { - set_elt_pointer ("columns", SCM_EOL); - set_elt_pointer ("all-elements", SCM_EOL); + for (; gh_pair_p (s); s = ly_cdr (s)) + { + Grob::fixup_refpoint (ly_car (s)); + } +} + - Axis_group_interface (this).set_interface (); - Axis_group_interface (this).set_axes (Y_AXIS,X_AXIS); +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_elt_pointer ("all-elements")); + return scm_ilength (get_grob_property ("all-elements")); } - -/* - Ugh. this is grossly hairy. - */ void -Line_of_score::typeset_element (Score_element * elem_p) +Line_of_score::typeset_grob (Grob * elem_p) { elem_p->pscore_l_ = pscore_l_; - Pointer_group_interface (this, "all-elements").add_element (elem_p); - scm_unprotect_object (elem_p->self_scm_); + 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_elt_pointer ("all-elements"); - gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = ly_cdr (s)) { - unsmob_element (gh_car (s))->do_break_processing (); + unsmob_grob (ly_car (s))->do_break_processing (); } /* fixups must be done in broken line_of_scores, because new elements @@ -62,11 +69,11 @@ Line_of_score::output_lines () int count = 0; for (int i=0; i < broken_into_l_arr_.size (); i++) { - Score_element *se = broken_into_l_arr_[i]; - SCM all = se->get_elt_pointer ("all-elements"); - for (SCM s = all; gh_pair_p (s); s = gh_cdr (s)) + Grob *se = broken_into_l_arr_[i]; + SCM all = se->get_grob_property ("all-elements"); + for (SCM s = all; gh_pair_p (s); s = ly_cdr (s)) { - unsmob_element (gh_car (s))->fixup_refpoint (); + fixup_refpoint (ly_car (s)); } count += scm_ilength (all); } @@ -75,29 +82,108 @@ Line_of_score::output_lines () /* needed for doing items. */ - for (SCM s = get_elt_pointer ("all-elements"); - gh_pair_p (s); s = gh_cdr (s)) - { - unsmob_element (gh_car (s))->fixup_refpoint (); - } + fixup_refpoints (get_grob_property ("all-elements")); + - for (SCM s = get_elt_pointer ("all-elements"); - gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = ly_cdr (s)) { - unsmob_element (gh_car (s))->handle_broken_dependencies (); + unsmob_grob (ly_car (s))->handle_broken_dependencies (); } handle_broken_dependencies (); - progress_indication ( _f("Element count %d.", count + element_count())); + + 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)); - 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 = ly_car (line_l->get_grob_property ("columns")); + Grob* e = unsmob_grob (lastcol); + + SCM between = ly_symbol2scm ("between-system-string"); + SCM inter = e->internal_get_grob_property (between); + if (gh_string_p (inter)) + { + pscore_l_->outputter_l_ + ->output_scheme (scm_list_n (between, + inter, SCM_UNDEFINED)); + } + } + } +} + +/* + Find the loose columns in POSNS, and drape them around the columns + specified in BETWEEN-COLS. */ +void +set_loose_columns (Line_of_score* which, Column_x_positions const *posns) +{ + for (int i = 0; iloose_cols_.size (); i++) + { + int divide_over = 1; + Item *loose = dynamic_cast (posns->loose_cols_[i]); + Paper_column* col = dynamic_cast (loose); + + if (col->line_l_) + continue; + + + Item * left = 0; + Item * right = 0; + while (1) + { + + SCM between = loose->get_grob_property ("between-cols"); + if (!gh_pair_p (between)) + break; + + if (!left) + { + left = dynamic_cast (unsmob_grob (ly_car (between))); + left = left->column_l (); + } + divide_over ++; + loose = dynamic_cast (unsmob_grob (ly_cdr (between))); + loose = loose->column_l (); + } + + right = loose; + + Real rx = right->relative_coordinate (right->parent_l (X_AXIS), X_AXIS); + Real lx = left->relative_coordinate (left->parent_l (X_AXIS), X_AXIS); + + int j = 1; + loose = col; + while (1) + { + SCM between = loose->get_grob_property ("between-cols"); + if (!gh_pair_p (between)) + break; + + Paper_column *thiscol = dynamic_cast (loose); + + thiscol->line_l_ = which; + thiscol->translate_axis (lx + j*(rx - lx)/divide_over, X_AXIS); + + j ++; + loose = dynamic_cast (unsmob_grob (ly_cdr (between))); + } + } } @@ -107,55 +193,92 @@ 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_); + // 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++) + 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; } - + set_loose_columns (line_l, &breaking[i]); 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) { - SCM offset_sym = ly_symbol2scm ("translate-molecule"); - SCM combine_sym = ly_symbol2scm ("combine-molecule"); -enter: - if (!gh_pair_p (expr)) - return; - - SCM head =gh_car (expr); - if (head == offset_sym) + while (1) { - o += ly_scm2offset (gh_cadr (expr)); - expr = gh_caddr (expr); - goto enter; - } - else if (head == combine_sym) - { - output_molecule (gh_cadr (expr), o); - expr = gh_caddr (expr); - goto enter; // tail recursion - } - else - { - pscore_l_->outputter_l_-> - output_scheme (gh_list (ly_symbol2scm ("placebox"), - gh_double2scm (o[X_AXIS]), - gh_double2scm (o[Y_AXIS]), - expr, - SCM_UNDEFINED)); + if (!gh_pair_p (expr)) + return; + + SCM head =ly_car (expr); + if (unsmob_input (head)) + { + Input * ip = unsmob_input (head); + + + pscore_l_->outputter_l_->output_scheme (scm_list_n (define_origin_sym, + ly_str02scm (ip->file_str ().ch_C ()), + gh_int2scm (ip->line_number ()), + gh_int2scm (ip->column_number ()), + SCM_UNDEFINED)); + expr = ly_cadr (expr); + } + else if (head == no_origin_sym) + { + pscore_l_->outputter_l_->output_scheme (scm_list_n (no_origin_sym, SCM_UNDEFINED)); + expr = ly_cadr (expr); + } + else if (head == offset_sym) + { + o += ly_scm2offset (ly_cadr (expr)); + expr = ly_caddr (expr); + } + else if (head == combine_sym) + { + output_molecule (ly_cadr (expr), o); + expr = ly_caddr (expr); + } + else + { + pscore_l_->outputter_l_-> + output_scheme (scm_list_n (placebox_sym, + gh_double2scm (o[X_AXIS]), + gh_double2scm (o[Y_AXIS]), + expr, + SCM_UNDEFINED)); + + return; + } } } @@ -168,73 +291,66 @@ Line_of_score::output_scheme (SCM s) void Line_of_score::add_column (Paper_column*p) { - SCM cs = get_elt_pointer ("columns"); - Score_element * prev = gh_pair_p (cs) ? unsmob_element (gh_car (cs)) : 0; - int rank = prev ? dynamic_cast (prev)->rank_i () + 1 : 0; - - p->set_rank (rank); - set_elt_pointer ("columns", gh_cons (p->self_scm_, cs)); + Grob *me = this; + SCM cs = me->get_grob_property ("columns"); + Grob * prev = gh_pair_p (cs) ? unsmob_grob (ly_car (cs)) : 0; - Axis_group_interface (this).add_element (p); - typeset_element (p); -} + p->rank_i_ = prev ? Paper_column::rank_i (prev) + 1 : 0; + me->set_grob_property ("columns", gh_cons (p->self_scm (), cs)); -void -fixup_refpoints (SCM s) -{ - for (; gh_pair_p (s); s = gh_cdr (s)) - { - Score_element * se = unsmob_element (gh_car (s)); - if (se) - { - se->fixup_refpoint (); - if (!dynamic_cast (se) && !se->parent_l (Y_AXIS)) - { - programming_error ("No parent!"); - } - } - } + Axis_group_interface::add_element (me, p); } + +/* + TODO: use scm_map iso. for loops. + */ void Line_of_score::pre_processing () { - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) - unsmob_element (gh_car (s))->discretionary_processing (); + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = ly_cdr (s)) + unsmob_grob (ly_car (s))->discretionary_processing (); - progress_indication ( _f("Element count %d ", element_count ())); + if (verbose_global_b) + progress_indication (_f ("Element count %d ", element_count ())); - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) - unsmob_element (gh_car (s))->handle_prebroken_dependencies (); + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = ly_cdr (s)) + unsmob_grob (ly_car (s))->handle_prebroken_dependencies (); - fixup_refpoints (get_elt_pointer ("all-elements")); + fixup_refpoints (get_grob_property ("all-elements")); - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = ly_cdr (s)) { - Score_element* sc = unsmob_element (gh_car (s)); - sc->calculate_dependencies (PRECALCED, PRECALCING, &Score_element::before_line_breaking); + Grob* sc = unsmob_grob (ly_car (s)); + sc->calculate_dependencies (PRECALCED, PRECALCING, ly_symbol2scm ("before-line-breaking-callback")); } - progress_indication ("\n" + _ ("Calculating column positions...") + " " ); - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) - unsmob_element (gh_car (s))->do_space_processing (); + progress_indication ("\n" + _ ("Calculating column positions...") + " "); + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = ly_cdr (s)) + { + Grob * e = unsmob_grob (ly_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::post_processing () +Line_of_score::post_processing (bool last_line) { - for (SCM s = get_elt_pointer ("all-elements"); - gh_pair_p (s); s = gh_cdr (s)) + for (SCM s = get_grob_property ("all-elements"); + gh_pair_p (s); s = ly_cdr (s)) { - Score_element* sc = unsmob_element (gh_car (s)); - sc->calculate_dependencies (POSTCALCED, POSTCALCING, &Score_element::after_line_breaking); + Grob* sc = unsmob_grob (ly_car (s)); + sc->calculate_dependencies (POSTCALCED, POSTCALCING, + ly_symbol2scm ("after-line-breaking-callback")); } - Interval i(extent(Y_AXIS)); - if (i.empty_b()) + Interval i (extent (this, Y_AXIS)); + if (i.empty_b ()) programming_error ("Huh? Empty Line_of_score?"); else translate_axis (- i[MAX], Y_AXIS); @@ -249,48 +365,63 @@ Line_of_score::post_processing () /* generate all molecules to trigger all font loads. - (ugh. This is not very memory efficient.) */ - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) - unsmob_element (gh_car (s))->get_molecule (); - + (ugh. This is not very memory efficient.) */ + for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = ly_cdr (s)) + { + unsmob_grob (ly_car (s))->get_molecule (); + } /* font defs; */ - SCM font_names = ly_quote_scm (all_fonts_global_p->font_descriptions ()); - output_scheme (gh_list (ly_symbol2scm ("define-fonts"), - font_names, - SCM_UNDEFINED)); + SCM font_names = ly_quote_scm (paper_l ()->font_descriptions ()); + output_scheme (scm_list_n (ly_symbol2scm ("define-fonts"), + font_names, + SCM_UNDEFINED)); /* line preamble. */ - output_scheme (gh_list (ly_symbol2scm ("start-line"), + output_scheme (scm_list_n (ly_symbol2scm ("start-line"), gh_double2scm (height), SCM_UNDEFINED)); - Real il = paper_l ()->get_var ("interline"); - - /* - all elements. - */ - for (SCM s = get_elt_pointer ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + /* 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 = ly_cdr (s)) + { + Grob *sc = unsmob_grob (ly_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 (ly_car (e)); + o[Y_AXIS] += gh_scm2double (ly_cdr (e)); + } + + output_molecule (m->get_expr (), o); + } + + if (last_line) { - Score_element * sc = unsmob_element (gh_car (s)); - Molecule m = sc->get_molecule (); - - Offset o (sc->relative_coordinate (this, X_AXIS), - sc->relative_coordinate (this, Y_AXIS)); - - SCM e = sc->get_elt_property ("extra-offset"); - if (gh_pair_p (e)) - { - o[X_AXIS] += il * gh_scm2double (gh_car (e)); - o[Y_AXIS] += il * gh_scm2double (gh_cdr (e)); - } - - output_molecule (m.get_expr (), o); + output_scheme (scm_list_n (ly_symbol2scm ("stop-last-line"), SCM_UNDEFINED)); + } + else + { + output_scheme (scm_list_n (ly_symbol2scm ("stop-line"), SCM_UNDEFINED)); } - output_scheme (gh_list (ly_symbol2scm ("stop-line"), SCM_UNDEFINED)); } @@ -301,22 +432,21 @@ Line_of_score::broken_col_range (Item const*l, Item const*r) const l = l->column_l (); r = r->column_l (); - SCM s = get_elt_pointer ("columns"); + SCM s = get_grob_property ("columns"); - while (gh_pair_p (s) && gh_car (s) != r->self_scm_) - s = gh_cdr (s); + while (gh_pair_p (s) && ly_car (s) != r->self_scm ()) + s = ly_cdr (s); if (gh_pair_p (s)) - s = gh_cdr (s); + s = ly_cdr (s); - while (gh_pair_p (s) && gh_car (s) != l->self_scm_) + while (gh_pair_p (s) && ly_car (s) != l->self_scm ()) { - Paper_column *c - = dynamic_cast (unsmob_element (gh_car (s))); - if (c->breakable_b () && !c->line_l_) + Paper_column*c = dynamic_cast (unsmob_grob (ly_car (s))); + if (Item::breakable_b (c) && !c->line_l_) ret.push (c); - s = gh_cdr (s); + s = ly_cdr (s); } ret.reverse (); @@ -327,15 +457,15 @@ Line_of_score::broken_col_range (Item const*l, Item const*r) const Return all columns, but filter out any unused columns , since they might disrupt the spacing problem. */ -Link_array +Link_array Line_of_score::column_l_arr ()const { - Link_array acs - = Pointer_group_interface__extract_elements (this, (Paper_column*) 0, "columns"); + Link_array acs + = Pointer_group_interface__extract_elements (this, (Grob*) 0, "columns"); bool bfound = false; - for (int i= acs.size (); i -- ; ) + for (int i= acs.size (); i -- ;) { - bool brb = acs[i]->breakable_b(); + bool brb = Item::breakable_b (acs[i]); bfound = bfound || brb; /* @@ -343,8 +473,9 @@ Line_of_score::column_l_arr ()const seem empty. We need to retain breakable columns, in case someone forced a breakpoint. */ - if (!bfound || !acs[i]->used_b ()) + if (!bfound || !Paper_column::used_b (acs[i])) acs.del (i); } return acs; } +