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>
8 #include "dimension-cache.hh"
11 #include "paper-column.hh"
12 #include "paper-score.hh"
13 #include "molecule.hh"
14 #include "paper-outputter.hh"
15 #include "score-column.hh"
16 #include "line-of-score.hh"
19 Spanner::do_print() const
22 DOUT << "Between " << classname (spanned_drul_[LEFT])
23 << " and " << classname (spanned_drul_[RIGHT]) << '\n';
26 DOUT << "Broken in " << to_str (broken_into_l_arr_.size ()) << " pieces";
31 Spanner::break_into_pieces ()
36 Item * left = spanned_drul_[LEFT];
37 Item * right = spanned_drul_[RIGHT];
41 warning (_ ("Left spanpoint is right spanpoint"));
45 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
47 break_points.insert (left,0);
48 break_points.push (right);
50 for (int i=1; i < break_points.size(); i++)
52 Drul_array<Item*> bounds;
53 bounds[LEFT] = break_points[i-1];
54 bounds[RIGHT] = break_points[i];
58 Item *&pc_l = bounds[d] ;
60 pc_l = pc_l->find_broken_piece(- d);
64 while ((flip(&d))!= LEFT);
66 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
67 span_p->set_bounds(LEFT,bounds[LEFT]);
68 span_p->set_bounds(RIGHT,bounds[RIGHT]);
70 pscore_l_->typeset_element (span_p);
71 span_p->handle_broken_dependencies();
73 broken_into_l_arr_.push (span_p);
76 broken_into_l_arr_.sort (Spanner::compare);
80 Spanner::set_my_columns()
82 Direction i = (Direction)1;
85 if (!spanned_drul_[i]->line_l())
86 set_bounds(i,spanned_drul_[i]->find_broken_piece((Direction)-i));
88 while (flip(&i) != 1);
92 Spanner::set_bounds(Direction d, Item*i)
101 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
103 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
105 set_parent (i, X_AXIS);
108 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
110 warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
114 Spanner::do_break_processing()
117 break_into_pieces ();
119 handle_broken_dependencies();
124 spanned_drul_[LEFT]=0;
125 spanned_drul_[RIGHT]=0;
128 Spanner::Spanner (Spanner const &s)
131 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
136 Spanner::do_width() const
138 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
139 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
142 warning (_ ("spanner with negative length"));
144 return Interval (0, r-l);
148 Spanner::line_l() const
150 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
152 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
154 return spanned_drul_[LEFT]->line_l();
159 Spanner::find_broken_piece (Line_of_score*l) const
161 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
165 return broken_into_l_arr_ [idx];
169 for (int i=0; i < broken_into_l_arr_.size (); i++)
171 if (broken_into_l_arr_[i]->line_l () == l)
172 return broken_into_l_arr_[i];
179 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
181 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
185 Spanner::broken_b() const
187 return broken_into_l_arr_.size();
191 Spanner::get_rods () const
198 Spanner::get_springs () const
205 Spanner::do_space_processing ()
207 Array<Rod> rs (get_rods ());
208 for (int i=0; i < rs.size (); i++)
210 rs[i].add_to_cols ();
213 Array<Spring> ss (get_springs ());
214 for (int i=0; i < ss.size (); i++)
216 ss[i].add_to_cols ();
224 Spanner::handle_broken_dependents ()
226 Spanner *unbrok = dynamic_cast<Spanner*> (original_l_);
227 if (!unbrok || parent_l(Y_AXIS))
230 Spanner *refpoint = dynamic_cast<Spanner*> (unbrok->parent_l (Y_AXIS));
234 Score_element * broken_refpoint = refpoint->find_broken_piece (line_l ());
236 set_parent (broken_refpoint,Y_AXIS);
238 programming_error ("Spanner y -refpoint lost.");
243 If this is a broken spanner, return the amount the left end is to be
244 shifted horizontally so that the spanner starts after the initial
245 clef and key on the staves. This is necessary for ties, slurs,
246 crescendo and decrescendo signs, for example.
249 Spanner::get_broken_left_end_align () const
253 Score_column *sc = dynamic_cast<Score_column*> (spanned_drul_[LEFT]->column_l());
255 // Relevant only if left span point is first column in line
256 if(sc != NULL && sc->line_l ()->cols_.find_i (sc) == 0)
258 // We could possibly return the right edge of the whole Score_column here,
259 // but we do a full search for the Break_align_item.
260 for(i = 0; i < sc->elem_l_arr_.size (); i++)
262 if(0 == strcmp (classname (sc->elem_l_arr_[i]), "Break_align_item"))
264 return sc->elem_l_arr_[i]->extent (X_AXIS) [RIGHT];