X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fline-of-score.cc;h=3d104e93775104d5e74748a36bbd2cf5a32b766c;hb=9661ba1fb275f3e14f8a69f2cee2f02a2f893e48;hp=c91627ffb04fd13398979bee7f064f33b051c409;hpb=615a9212789c2cb2994748c023d0e19f3a83a0fd;p=lilypond.git diff --git a/lily/line-of-score.cc b/lily/line-of-score.cc index c91627ffb0..3d104e9377 100644 --- a/lily/line-of-score.cc +++ b/lily/line-of-score.cc @@ -3,108 +3,409 @@ source file of the GNU LilyPond music typesetter - (c) 1996, 1997--1998 Han-Wen Nienhuys + (c) 1996--2000 Han-Wen Nienhuys */ +#include "input-smob.hh" +#include "axis-group-interface.hh" +#include "debug.hh" #include "line-of-score.hh" -#include "spanner.hh" -#include "atom.hh" +#include "main.hh" +#include "paper-column.hh" #include "paper-def.hh" -#include "p-col.hh" -#include "p-score.hh" +#include "paper-outputter.hh" +#include "paper-score.hh" +#include "string.hh" +#include "warn.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) { - error_mark_b_ = 0; + for (; gh_pair_p (s); s = gh_cdr (s)) + { + Score_element::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); +} -void -Line_of_score::add_element (Score_element*e) +int +Line_of_score::element_count () const { - // avoid excess dependencies. - if (!(e->axis_group_l_a_[0] || e->axis_group_l_a_[1])) - add_dependency (e); + return scm_ilength ( get_elt_property ("all-elements")); } -bool -Line_of_score::contains_b (Paper_column const* c) const +void +Line_of_score::typeset_element (Score_element * elem_p) { - return cols.find_l ((Paper_column*)c); + elem_p->pscore_l_ = pscore_l_; + Pointer_group_interface (this, "all-elements").add_element (elem_p); + scm_unprotect_object (elem_p->self_scm_); } -Line_of_score* -Line_of_score::set_breaking (Array const &breaking, int j) const +void +Line_of_score::output_lines () { - const Array &curline (breaking[j].cols); - const Array &errors (breaking[j].error_col_l_arr_); - const Array &config (breaking[j].config); - - for (int i=0; i < errors.size(); i++) - errors[i]->error_mark_b_ = true; - - Line_of_score *line_l=0; - - if (breaking.size() >1) - { - line_l = dynamic_cast (clone()); - } - else - line_l = (Line_of_score*) this; - - ((Array &)line_l->cols) = curline; - line_l->set_bounds(LEFT,curline[0]); - - line_l->set_bounds(RIGHT,curline.top()); - - for (int i=0; i < curline.size(); i++) + for (SCM s = get_elt_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + unsmob_element (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++) { - curline[i]->translate_axis (config[i],X_AXIS); - curline[i]->line_l_ = (Line_of_score*)line_l; + Score_element *se = broken_into_l_arr_[i]; + SCM all = se->get_elt_property ("all-elements"); + for (SCM s = all; gh_pair_p (s); s = gh_cdr (s)) + { + fixup_refpoint (gh_car (s)); + } + count += scm_ilength (all); } - return line_l; -} + + /* + needed for doing items. + */ + fixup_refpoints (get_elt_property ("all-elements")); + + + for (SCM s = get_elt_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + unsmob_element (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]); + 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_elt_property ("columns")); + Score_element* e = unsmob_element (lastcol); + SCM inter = e->get_elt_property ("between-system-string"); + if (gh_string_p (inter)) + { + pscore_l_->outputter_l_->output_string (inter); + } + } + } +} +// const? void -Line_of_score::do_print() const +Line_of_score::break_into_pieces (Array const &breaking) { - Spanner::do_print(); + for (int i=0; i < breaking.size (); i++) + { + Line_of_score *line_l = dynamic_cast (clone()); + line_l->rank_i_ = i; + // line_l->set_immutable_elt_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); + dynamic_cast (c[j])->line_l_ = line_l; + } + + broken_into_l_arr_.push (line_l); + } } -Interval -Line_of_score::do_width() const -{ - return Spanner::do_width(); + +#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; + } + } } -Link_array -Line_of_score::get_extra_dependencies () const +void +Line_of_score::output_scheme (SCM s) { - Link_array r; - for (int i=0; i < cols.size (); i++) - r.push (cols[i]); - return r; + pscore_l_->outputter_l_->output_scheme (s); } void -Line_of_score::do_unlink () +Line_of_score::add_column (Paper_column*p) { - Spanner::do_unlink (); - for (int i=0; i < cols.size (); i++) - cols[i]->line_l_ =0; - cols.set_size (0); + Score_element *me = this; + SCM cs = me->get_elt_property ("columns"); + Score_element * prev = gh_pair_p (cs) ? unsmob_element (gh_car (cs)) : 0; + + p->rank_i_ = prev ? Paper_column::rank_i (prev) + 1 : 0; + + + + me->set_elt_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::pre_processing () +{ + for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + unsmob_element (gh_car (s))->discretionary_processing (); + + if(verbose_global_b) + progress_indication ( _f("Element count %d ", element_count ())); + + + for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + unsmob_element (gh_car (s))->handle_prebroken_dependencies (); + + fixup_refpoints (get_elt_property ("all-elements")); + + for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + Score_element* sc = unsmob_element (gh_car (s)); + sc->calculate_dependencies (PRECALCED, PRECALCING, ly_symbol2scm ("before-line-breaking-callback")); + } + + progress_indication ("\n" + _ ("Calculating column positions...") + " " ); + for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + Score_element * e = unsmob_element (gh_car (s)); + SCM proc = e->get_elt_property ("spacing-procedure"); + if (gh_procedure_p (proc)) + gh_call1 (proc, e->self_scm_); + } +} + void -Line_of_score::do_junk_links () +Line_of_score::post_processing (bool last_line) { - cols.set_size (0); + for (SCM s = get_elt_property ("all-elements"); + gh_pair_p (s); s = gh_cdr (s)) + { + Score_element* sc = unsmob_element (gh_car (s)); + sc->calculate_dependencies (POSTCALCED, POSTCALCING, + ly_symbol2scm ("after-line-breaking-callback")); + } + + Interval i(extent(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_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + unsmob_element (gh_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)); + + /* + line preamble. + */ + output_scheme (gh_list (ly_symbol2scm ("start-line"), + gh_double2scm (height), + SCM_UNDEFINED)); + + Real il = paper_l ()->get_var ("interline"); + + /* + all elements. + */ + for (SCM s = get_elt_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s)) + { + 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); + } + if (last_line) + { + output_scheme (gh_list (ly_symbol2scm ("stop-last-line"), SCM_UNDEFINED)); + } + else + { + output_scheme (gh_list (ly_symbol2scm ("stop-line"), SCM_UNDEFINED)); + } +} + + +Link_array +Line_of_score::broken_col_range (Item const*l, Item const*r) const +{ + Link_array ret; + + l = l->column_l (); + r = r->column_l (); + SCM s = get_elt_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_element (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, (Score_element*) 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; } +