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);
69 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
70 span_p->set_bound (LEFT, bound);
71 span_p->set_bound (RIGHT, bound);
73 assert (span_p->line_l ());
74 span_p->line_l ()->typeset_element (span_p);
75 broken_into_l_arr_.push (span_p);
78 while ((flip(&d))!= LEFT);
82 Link_array<Item> break_points = pscore_l_->line_l_->broken_col_range (left,right);
84 break_points.insert (left,0);
85 break_points.push (right);
87 for (int i=1; i < break_points.size(); i++)
89 Drul_array<Item*> bounds;
90 bounds[LEFT] = break_points[i-1];
91 bounds[RIGHT] = break_points[i];
95 Item *&pc_l = bounds[d] ;
97 pc_l = pc_l->find_broken_piece(- d);
101 while ((flip(&d))!= LEFT);
103 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
104 span_p->set_bound(LEFT,bounds[LEFT]);
105 span_p->set_bound(RIGHT,bounds[RIGHT]);
108 assert (bounds[LEFT]->line_l () ==
109 bounds[RIGHT]->line_l ());
111 bounds[LEFT]->line_l ()->typeset_element (span_p);
112 broken_into_l_arr_.push (span_p);
115 broken_into_l_arr_.sort (Spanner::compare);
119 Spanner::set_my_columns()
121 Direction i = (Direction) LEFT;
124 if (!spanned_drul_[i]->line_l())
125 set_bound(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
127 while (flip(&i) != LEFT);
131 Spanner::spanned_rank_iv ()
133 Interval_t<int> iv (0, 0);
135 if (spanned_drul_[LEFT])
137 iv[LEFT] = spanned_drul_[LEFT]->column_l ()->rank_i ();
139 if ( spanned_drul_[RIGHT])
141 iv[RIGHT] = spanned_drul_[RIGHT]->column_l ()->rank_i ();
147 Spanner::get_bound (Direction d) const
149 return spanned_drul_ [d];
153 Spanner::set_bound(Direction d, Item*i)
162 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
164 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
166 set_parent (i, X_AXIS);
169 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
171 warning (_f ("Spanner `%s' has equal left and right spanpoints",
178 spanned_drul_[LEFT]=0;
179 spanned_drul_[RIGHT]=0;
182 Spanner::Spanner (Spanner const &s)
185 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
190 Spanner::spanner_length() const
192 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
193 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
196 programming_error ("spanner with negative length");
202 Spanner::line_l() const
204 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
206 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
208 return spanned_drul_[LEFT]->line_l();
213 Spanner::find_broken_piece (Line_of_score*l) const
215 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
220 return broken_into_l_arr_ [idx];
225 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
227 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
231 Spanner::broken_b() const
233 return broken_into_l_arr_.size();
237 Spanner::get_rods () const
244 Spanner::get_springs () const
251 Spanner::do_space_processing ()
253 Array<Rod> rs (get_rods ());
254 for (int i=0; i < rs.size (); i++)
256 rs[i].add_to_cols ();
259 Array<Spring> ss (get_springs ());
260 for (int i=0; i < ss.size (); i++)
262 if (isinf (ss[i].distance_f_))
263 programming_error ("weird spring");
265 ss[i].add_to_cols ();
270 If this is a broken spanner, return the amount the left end is to be
271 shifted horizontally so that the spanner starts after the initial
272 clef and key on the staves. This is necessary for ties, slurs,
273 crescendo and decrescendo signs, for example.
276 Spanner::get_broken_left_end_align () const
278 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
280 // Relevant only if left span point is first column in line
282 sc->break_status_dir () == RIGHT)
286 We used to do a full search for the Break_align_item.
287 But that doesn't make a difference, since the Paper_column
288 is likely to contain only a Break_align_item.
290 return sc->extent (X_AXIS)[RIGHT];