2 spanner.cc -- implement Spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1996, 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "dimension-cache.hh"
12 #include "paper-column.hh"
13 #include "paper-score.hh"
14 #include "molecule.hh"
15 #include "paper-outputter.hh"
16 #include "score-column.hh"
17 #include "line-of-score.hh"
18 #include "break-align-item.hh"
21 Spanner::break_into_pieces ()
23 if (line_l () || broken_b ())
26 Item * left = spanned_drul_[LEFT];
27 Item * right = spanned_drul_[RIGHT];
31 warning (_ ("Left spanpoint is right spanpoint"));
35 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
37 break_points.insert (left,0);
38 break_points.push (right);
40 for (int i=1; i < break_points.size(); i++)
42 Drul_array<Item*> bounds;
43 bounds[LEFT] = break_points[i-1];
44 bounds[RIGHT] = break_points[i];
48 Item *&pc_l = bounds[d] ;
50 pc_l = pc_l->find_broken_piece(- d);
54 while ((flip(&d))!= LEFT);
56 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
57 span_p->set_bounds(LEFT,bounds[LEFT]);
58 span_p->set_bounds(RIGHT,bounds[RIGHT]);
60 pscore_l_->typeset_element (span_p);
61 span_p->handle_broken_dependencies();
63 broken_into_l_arr_.push (span_p);
66 broken_into_l_arr_.sort (Spanner::compare);
70 Spanner::set_my_columns()
72 Direction i = (Direction) LEFT;
75 if (!spanned_drul_[i]->line_l())
76 set_bounds(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
78 while (flip(&i) != LEFT);
82 Spanner::set_bounds(Direction d, Item*i)
91 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
93 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
95 set_parent (i, X_AXIS);
98 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
100 warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
106 Spanner::do_break_processing()
108 break_into_pieces ();
109 handle_broken_dependencies();
114 spanned_drul_[LEFT]=0;
115 spanned_drul_[RIGHT]=0;
118 Spanner::Spanner (Spanner const &s)
121 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
126 Spanner::spanner_length() const
128 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
129 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
132 warning (_ ("spanner with negative length"));
138 Spanner::line_l() const
140 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
142 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
144 return spanned_drul_[LEFT]->line_l();
149 Spanner::find_broken_piece (Line_of_score*l) const
151 Spanner* me = (Spanner*) this;
152 break_into_pieces ();
154 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
159 return broken_into_l_arr_ [idx];
164 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
166 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
170 Spanner::broken_b() const
172 return broken_into_l_arr_.size();
176 Spanner::get_rods () const
183 Spanner::get_springs () const
190 Spanner::do_space_processing ()
192 Array<Rod> rs (get_rods ());
193 for (int i=0; i < rs.size (); i++)
195 rs[i].add_to_cols ();
198 Array<Spring> ss (get_springs ());
199 for (int i=0; i < ss.size (); i++)
201 ss[i].add_to_cols ();
206 If this is a broken spanner, return the amount the left end is to be
207 shifted horizontally so that the spanner starts after the initial
208 clef and key on the staves. This is necessary for ties, slurs,
209 crescendo and decrescendo signs, for example.
212 Spanner::get_broken_left_end_align () const
214 Score_column *sc = dynamic_cast<Score_column*> (spanned_drul_[LEFT]->column_l());
216 // Relevant only if left span point is first column in line
218 sc->break_status_dir () == RIGHT)
220 // We could possibly return the right edge of the whole Score_column here,
221 // but we do a full search for the Break_align_item.
224 In fact that doesn't make a difference, since the Score_column
225 is likely to contain only a Break_align_item.
228 for(SCM s = sc->get_elt_property ("elements"); gh_pair_p (s);
231 Score_element *e = SMOB_TO_TYPE (Score_element, gh_car (s));
232 if(dynamic_cast<Break_align_item*> (e))
234 return e->extent (X_AXIS) [RIGHT];
238 return sc->extent (X_AXIS)[RIGHT];