2 spanner.cc -- implement Spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1996--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "dimension-cache.hh"
13 #include "paper-column.hh"
14 #include "paper-score.hh"
15 #include "molecule.hh"
16 #include "paper-outputter.hh"
17 #include "paper-column.hh"
18 #include "line-of-score.hh"
19 #include "break-align-item.hh"
23 Spanner::do_break_processing ()
26 Item * left = spanned_drul_[LEFT];
27 Item * right = spanned_drul_[RIGHT];
31 warning (_f ("Spanner `%s' has equal left and right spanpoints",
36 Check if our parent in X-direction spans equally wide
39 for (int a = X_AXIS; a < NO_AXES; a ++)
41 if (Spanner* parent = dynamic_cast<Spanner*> (parent_l ((Axis)a)))
43 if (!parent->spanned_rank_iv ().contains_b (this->spanned_rank_iv ()))
45 programming_error (to_str ("Spanner `%s' is not fully contained in parent spanner `%s'.",
52 if (line_l () || broken_b ())
58 FIXME: this is broken.
61 If we have a spanner spanning one column, we must break it
62 anyway because it might provide a parent for another item. */
66 Item* bound = left->find_broken_piece (d);
67 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
68 span_p->set_bound (LEFT, bound);
69 span_p->set_bound (RIGHT, bound);
71 assert (span_p->line_l ());
72 pscore_l_->typeset_element (span_p);
73 broken_into_l_arr_.push (span_p);
75 while ((flip(&d))!= LEFT);
79 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
81 break_points.insert (left,0);
82 break_points.push (right);
84 for (int i=1; i < break_points.size(); i++)
86 Drul_array<Item*> bounds;
87 bounds[LEFT] = break_points[i-1];
88 bounds[RIGHT] = break_points[i];
92 Item *&pc_l = bounds[d] ;
94 pc_l = pc_l->find_broken_piece(- d);
98 while ((flip(&d))!= LEFT);
100 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
101 span_p->set_bound(LEFT,bounds[LEFT]);
102 span_p->set_bound(RIGHT,bounds[RIGHT]);
104 pscore_l_->typeset_element (span_p);
105 broken_into_l_arr_.push (span_p);
108 broken_into_l_arr_.sort (Spanner::compare);
112 Spanner::set_my_columns()
114 Direction i = (Direction) LEFT;
117 if (!spanned_drul_[i]->line_l())
118 set_bound(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
120 while (flip(&i) != LEFT);
124 Spanner::spanned_rank_iv ()
126 Interval_t<int> iv (0, 0);
128 if (spanned_drul_[LEFT])
130 iv[LEFT] = spanned_drul_[LEFT]->column_l ()->rank_i ();
132 if ( spanned_drul_[RIGHT])
134 iv[RIGHT] = spanned_drul_[RIGHT]->column_l ()->rank_i ();
140 Spanner::get_bound (Direction d) const
142 return spanned_drul_ [d];
146 Spanner::set_bound(Direction d, Item*i)
155 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
157 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
159 set_parent (i, X_AXIS);
162 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
164 warning (_f ("Spanner `%s' has equal left and right spanpoints",
171 spanned_drul_[LEFT]=0;
172 spanned_drul_[RIGHT]=0;
175 Spanner::Spanner (Spanner const &s)
178 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
183 Spanner::spanner_length() const
185 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
186 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
189 programming_error ("spanner with negative length");
195 Spanner::line_l() const
197 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
199 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
201 return spanned_drul_[LEFT]->line_l();
206 Spanner::find_broken_piece (Line_of_score*l) const
208 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
213 return broken_into_l_arr_ [idx];
218 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
220 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
224 Spanner::broken_b() const
226 return broken_into_l_arr_.size();
230 Spanner::get_rods () const
237 Spanner::get_springs () const
244 Spanner::do_space_processing ()
246 Array<Rod> rs (get_rods ());
247 for (int i=0; i < rs.size (); i++)
249 rs[i].add_to_cols ();
252 Array<Spring> ss (get_springs ());
253 for (int i=0; i < ss.size (); i++)
255 if (isinf (ss[i].distance_f_))
256 programming_error ("weird spring");
258 ss[i].add_to_cols ();
263 If this is a broken spanner, return the amount the left end is to be
264 shifted horizontally so that the spanner starts after the initial
265 clef and key on the staves. This is necessary for ties, slurs,
266 crescendo and decrescendo signs, for example.
269 Spanner::get_broken_left_end_align () const
271 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
273 // Relevant only if left span point is first column in line
275 sc->break_status_dir () == RIGHT)
279 We used to do a full search for the Break_align_item.
280 But that doesn't make a difference, since the Paper_column
281 is likely to contain only a Break_align_item.
283 return sc->extent (X_AXIS)[RIGHT];