X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Ftie-column.cc;h=9f8bf74fb949502925090cb01df5279142768080;hb=d11056c687720e610a40f69e6f6ec32525751ff2;hp=32d6f4a1add79311731ee8bc9b9dc6aced65de3e;hpb=9b40d66187029df3dca86fc5ecc65f64db315a48;p=lilypond.git diff --git a/lily/tie-column.cc b/lily/tie-column.cc index 32d6f4a1ad..9f8bf74fb9 100644 --- a/lily/tie-column.cc +++ b/lily/tie-column.cc @@ -1,113 +1,180 @@ -/* - tie-column.cc -- implement Tie_column - +/* + tie-column.cc -- implement Tie_column + source file of the GNU LilyPond music typesetter - - (c) 2000 Han-Wen Nienhuys - - */ -#include "spanner.hh" + (c) 2000--2005 Han-Wen Nienhuys +*/ + #include "tie-column.hh" +#include "paper-column.hh" +#include "spanner.hh" #include "group-interface.hh" #include "tie.hh" #include "directional-element-interface.hh" #include "rhythmic-head.hh" - - +/* + tie dir depends on what Tie_column does. +*/ +/* + TODO: this doesn't follow standard pattern. Regularize. +*/ void -Tie_column::set_interface (Score_element*me) +Tie_column::add_tie (Grob *me, Grob *tie) { - me->set_interface (ly_symbol2scm ("tie-column")); - me->set_extent_callback (SCM_EOL, X_AXIS); - me->set_extent_callback (SCM_EOL, Y_AXIS) ; -} + if (tie->get_parent (Y_AXIS) + && Tie_column::has_interface (tie->get_parent (Y_AXIS))) + return; -bool -Tie_column::has_interface (Score_element*me) -{ - return me->has_interface (ly_symbol2scm ("tie-column")); + if (!Pointer_group_interface::count (me, ly_symbol2scm ("ties"))) + { + dynamic_cast (me)->set_bound (LEFT, Tie::head (tie, LEFT)); + dynamic_cast (me)->set_bound (RIGHT, Tie::head (tie, RIGHT)); + } + + tie->set_parent (me, Y_AXIS); + Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), tie); + tie->add_dependency (me); } void -Tie_column::add_tie (Score_element*me,Score_element *s) +Tie_column::set_directions (Grob *me) { - Pointer_group_interface g (me, "ties"); - if (!g.count ()) - { - dynamic_cast (me)->set_bound (LEFT, Tie::head (s,LEFT)); - dynamic_cast (me)->set_bound (RIGHT, Tie::head (s,RIGHT)); - } - - Pointer_group_interface (me, "ties").add_element (s); - s->add_dependency (me); + werner_directions (me); } - int -tie_compare (Score_element* const & s1, - Score_element* const & s2) +tie_compare (Grob *const &s1, + Grob *const &s2) { - return sign (Tie::position_f (s1) - Tie::position_f(s2)); + return sign (Tie::get_position (s1) - Tie::get_position (s2)); } /* - See [Ross p. 138]. + Werner: + + . The algorithm to choose the direction of the ties doesn't work + properly. I suggest the following for applying ties sequentially + from top to bottom: + + The topmost tie is always `up'. - In normal chord cases, the outer ties point outwards, and the - direction of the rest is determined by their staff position. + + If there is a vertical gap to the last note above larger than + or equal to a fifth (or sixth?), the tie is `up', otherwise it + is `down'. - Ross forgets about the tie that is *on* the middle staff line. We - assume it goes UP. (TODO: make me settable) */ + + The bottommost tie is always `down'. +*/ void -Tie_column::set_directions (Score_element*me) +Tie_column::werner_directions (Grob *me) { - Link_array ties = - Pointer_group_interface__extract_elements (me, (Score_element*)0, "ties"); + Link_array ties + = extract_grob_array (me, ly_symbol2scm ("ties")); + if (!ties.size ()) + return; - Direction d = Directional_element_interface::get (me); + ties.sort (tie_compare); + Direction d = get_grob_direction (me); if (d) { for (int i = ties.size (); i--;) { - Score_element * t = ties[i]; - Directional_element_interface::set (t, d); + Grob *t = ties[i]; + if (!get_grob_direction (t)) + set_grob_direction (t, d); } return; } - + if (ties.size () == 1) { - Score_element * t = ties[0]; - Directional_element_interface::set (t,Tie::get_default_dir (t)); + Grob *t = ties[0]; + if (t->is_live () + && !get_grob_direction (t)) + set_grob_direction (t, Tie::get_default_dir (t)); return; } - - ties.sort (tie_compare); - Directional_element_interface::set( ties[0], DOWN); - ties.del (0); - - Directional_element_interface ::set(ties.pop (), UP); - for (int i=ties.size(); i--; ) + + Real last_down_pos = 10000; + if (!get_grob_direction (ties[0])) + set_grob_direction (ties[0], DOWN); + + /* + Go downward. + */ + Grob *last_tie = 0; + for (int i = ties.size (); i--;) { - Score_element * t = ties[i]; - Real p = Tie::position_f (t); - Direction d = (Direction) sign (p); + Grob *t = ties[i]; + + Direction d = get_grob_direction (t); + Real p = Tie::get_position (t); if (!d) - d = UP; - Directional_element_interface::set (t, d); + { + if (last_tie + && Tie::get_column_rank (t, LEFT) + < Tie::get_column_rank (last_tie, LEFT)) + { + d = DOWN; + } + else if (last_down_pos - p > 5) + { + d = UP; + } + else + { + d = DOWN; + } + + set_grob_direction (t, d); + } + + if (d == DOWN) + last_down_pos = p; + + last_tie = t; } - + + return; } -MAKE_SCHEME_CALLBACK(Tie_column,after_line_breaking,1); +MAKE_SCHEME_CALLBACK (Tie_column, after_line_breaking, 1); SCM Tie_column::after_line_breaking (SCM smob) { - set_directions (unsmob_element (smob)); + werner_directions (unsmob_grob (smob)); + return SCM_UNSPECIFIED; +} + +/* + Extend the spanner over its Tie constituents. +*/ +MAKE_SCHEME_CALLBACK (Tie_column, before_line_breaking, 1); +SCM +Tie_column::before_line_breaking (SCM smob) +{ + Spanner *me = dynamic_cast (unsmob_grob (smob)); + for (SCM s = me->get_property ("ties"); scm_is_pair (s); s = scm_cdr (s)) + { + Spanner *tie = dynamic_cast (unsmob_grob (scm_car (s))); + Direction dir = LEFT; + do + { + if (dir * Paper_column::get_rank (tie->get_bound (dir)->get_column ()) + > dir * Paper_column::get_rank (me->get_bound (dir)->get_column ())) + { + me->set_bound (dir, Tie::head (tie, dir)); + } + } + while (flip (&dir) != LEFT); + } return SCM_UNSPECIFIED; } + +ADD_INTERFACE (Tie_column, "tie-column-interface", + "Object that sets directions of multiple ties in a tied chord", + "direction"); +