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"
20 Spanner::break_into_pieces ()
22 if (line_l () || broken_b ())
25 Item * left = spanned_drul_[LEFT];
26 Item * right = spanned_drul_[RIGHT];
30 warning (_ ("Left spanpoint is right spanpoint"));
34 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
36 break_points.insert (left,0);
37 break_points.push (right);
39 for (int i=1; i < break_points.size(); i++)
41 Drul_array<Item*> bounds;
42 bounds[LEFT] = break_points[i-1];
43 bounds[RIGHT] = break_points[i];
47 Item *&pc_l = bounds[d] ;
49 pc_l = pc_l->find_broken_piece(- d);
53 while ((flip(&d))!= LEFT);
55 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
56 span_p->set_bounds(LEFT,bounds[LEFT]);
57 span_p->set_bounds(RIGHT,bounds[RIGHT]);
59 pscore_l_->typeset_element (span_p);
60 span_p->handle_broken_dependencies();
62 broken_into_l_arr_.push (span_p);
65 broken_into_l_arr_.sort (Spanner::compare);
69 Spanner::set_my_columns()
71 Direction i = (Direction) LEFT;
74 if (!spanned_drul_[i]->line_l())
75 set_bounds(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
77 while (flip(&i) != LEFT);
81 Spanner::set_bounds(Direction d, Item*i)
90 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
92 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
94 set_parent (i, X_AXIS);
97 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
99 warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
105 Spanner::do_break_processing()
107 break_into_pieces ();
108 handle_broken_dependencies();
113 spanned_drul_[LEFT]=0;
114 spanned_drul_[RIGHT]=0;
117 Spanner::Spanner (Spanner const &s)
120 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
125 Spanner::spanner_length() const
127 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
128 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
131 warning (_ ("spanner with negative length"));
137 Spanner::line_l() const
139 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
141 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
143 return spanned_drul_[LEFT]->line_l();
148 Spanner::find_broken_piece (Line_of_score*l) const
150 Spanner* me = (Spanner*) this;
151 break_into_pieces ();
153 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
158 return broken_into_l_arr_ [idx];
163 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
165 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
169 Spanner::broken_b() const
171 return broken_into_l_arr_.size();
175 Spanner::get_rods () const
182 Spanner::get_springs () const
189 Spanner::do_space_processing ()
191 Array<Rod> rs (get_rods ());
192 for (int i=0; i < rs.size (); i++)
194 rs[i].add_to_cols ();
197 Array<Spring> ss (get_springs ());
198 for (int i=0; i < ss.size (); i++)
200 ss[i].add_to_cols ();
209 Spanner::handle_broken_dependents ()
211 Spanner *unbrok = dynamic_cast<Spanner*> (original_l_);
212 if (!unbrok || parent_l(Y_AXIS))
215 Spanner *refpoint = dynamic_cast<Spanner*> (unbrok->parent_l (Y_AXIS));
219 Score_element * broken_refpoint = refpoint->find_broken_piece (line_l ());
221 set_parent (broken_refpoint,Y_AXIS);
223 programming_error ("Spanner y -refpoint lost.");
229 If this is a broken spanner, return the amount the left end is to be
230 shifted horizontally so that the spanner starts after the initial
231 clef and key on the staves. This is necessary for ties, slurs,
232 crescendo and decrescendo signs, for example.
235 Spanner::get_broken_left_end_align () const
239 Score_column *sc = dynamic_cast<Score_column*> (spanned_drul_[LEFT]->column_l());
241 // Relevant only if left span point is first column in line
243 sc->break_status_dir () == RIGHT)
245 // We could possibly return the right edge of the whole Score_column here,
246 // but we do a full search for the Break_align_item.
247 for(i = 0; i < sc->elem_l_arr_.size (); i++)
249 if(0 == strcmp (classname (sc->elem_l_arr_[i]), "Break_align_item"))
251 return sc->elem_l_arr_[i]->extent (X_AXIS) [RIGHT];