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::do_print() const
23 DEBUG_OUT << "Between " << classname (spanned_drul_[LEFT])
24 << " and " << classname (spanned_drul_[RIGHT]) << '\n';
27 DEBUG_OUT << "Broken in " << to_str (broken_into_l_arr_.size ()) << " pieces";
32 Spanner::break_into_pieces ()
37 Item * left = spanned_drul_[LEFT];
38 Item * right = spanned_drul_[RIGHT];
42 warning (_ ("Left spanpoint is right spanpoint"));
46 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
48 break_points.insert (left,0);
49 break_points.push (right);
51 for (int i=1; i < break_points.size(); i++)
53 Drul_array<Item*> bounds;
54 bounds[LEFT] = break_points[i-1];
55 bounds[RIGHT] = break_points[i];
59 Item *&pc_l = bounds[d] ;
61 pc_l = pc_l->find_broken_piece(- d);
65 while ((flip(&d))!= LEFT);
67 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
68 span_p->set_bounds(LEFT,bounds[LEFT]);
69 span_p->set_bounds(RIGHT,bounds[RIGHT]);
71 pscore_l_->typeset_element (span_p);
72 span_p->handle_broken_dependencies();
74 broken_into_l_arr_.push (span_p);
77 broken_into_l_arr_.sort (Spanner::compare);
81 Spanner::set_my_columns()
83 Direction i = (Direction)1;
86 if (!spanned_drul_[i]->line_l())
87 set_bounds(i,spanned_drul_[i]->find_broken_piece((Direction)-i));
89 while (flip(&i) != 1);
93 Spanner::set_bounds(Direction d, Item*i)
102 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
104 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
106 set_parent (i, X_AXIS);
109 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
111 warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
115 Spanner::do_break_processing()
118 break_into_pieces ();
120 handle_broken_dependencies();
125 spanned_drul_[LEFT]=0;
126 spanned_drul_[RIGHT]=0;
129 Spanner::Spanner (Spanner const &s)
132 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
137 Spanner::do_width() const
139 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
140 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
143 warning (_ ("spanner with negative length"));
145 return Interval (0, r-l);
149 Spanner::line_l() const
151 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
153 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
155 return spanned_drul_[LEFT]->line_l();
160 Spanner::find_broken_piece (Line_of_score*l) const
162 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
166 return broken_into_l_arr_ [idx];
170 for (int i=0; i < broken_into_l_arr_.size (); i++)
172 if (broken_into_l_arr_[i]->line_l () == l)
173 return broken_into_l_arr_[i];
180 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
182 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
186 Spanner::broken_b() const
188 return broken_into_l_arr_.size();
192 Spanner::get_rods () const
199 Spanner::get_springs () const
206 Spanner::do_space_processing ()
208 Array<Rod> rs (get_rods ());
209 for (int i=0; i < rs.size (); i++)
211 rs[i].add_to_cols ();
214 Array<Spring> ss (get_springs ());
215 for (int i=0; i < ss.size (); i++)
217 ss[i].add_to_cols ();
225 Spanner::handle_broken_dependents ()
227 Spanner *unbrok = dynamic_cast<Spanner*> (original_l_);
228 if (!unbrok || parent_l(Y_AXIS))
231 Spanner *refpoint = dynamic_cast<Spanner*> (unbrok->parent_l (Y_AXIS));
235 Score_element * broken_refpoint = refpoint->find_broken_piece (line_l ());
237 set_parent (broken_refpoint,Y_AXIS);
239 programming_error ("Spanner y -refpoint lost.");
244 If this is a broken spanner, return the amount the left end is to be
245 shifted horizontally so that the spanner starts after the initial
246 clef and key on the staves. This is necessary for ties, slurs,
247 crescendo and decrescendo signs, for example.
250 Spanner::get_broken_left_end_align () const
254 Score_column *sc = dynamic_cast<Score_column*> (spanned_drul_[LEFT]->column_l());
256 // Relevant only if left span point is first column in line
257 if(sc != NULL && sc->line_l ()->cols_.find_i (sc) == 0)
259 // We could possibly return the right edge of the whole Score_column here,
260 // but we do a full search for the Break_align_item.
261 for(i = 0; i < sc->elem_l_arr_.size (); i++)
263 if(0 == strcmp (classname (sc->elem_l_arr_[i]), "Break_align_item"))
265 return sc->elem_l_arr_[i]->extent (X_AXIS) [RIGHT];