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>
9 #include <libc-extension.hh>
11 #include "dimension-cache.hh"
14 #include "paper-column.hh"
15 #include "paper-score.hh"
16 #include "molecule.hh"
17 #include "paper-outputter.hh"
18 #include "paper-column.hh"
19 #include "line-of-score.hh"
20 #include "break-align-item.hh"
24 Spanner::do_break_processing ()
27 Item * left = spanned_drul_[LEFT];
28 Item * right = spanned_drul_[RIGHT];
35 warning (_f ("Spanner `%s' has equal left and right spanpoints",
40 Check if our parent in X-direction spans equally wide
43 for (int a = X_AXIS; a < NO_AXES; a ++)
45 if (Spanner* parent = dynamic_cast<Spanner*> (parent_l ((Axis)a)))
47 if (!parent->spanned_rank_iv ().contains_b (this->spanned_rank_iv ()))
49 programming_error (to_str ("Spanner `%s' is not fully contained in parent spanner `%s'.",
56 if (line_l () || broken_b ())
62 FIXME: this is broken.
65 If we have a spanner spanning one column, we must break it
66 anyway because it might provide a parent for another item. */
70 Item* bound = left->find_prebroken_piece (d);
73 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
74 span_p->set_bound (LEFT, bound);
75 span_p->set_bound (RIGHT, bound);
77 assert (span_p->line_l ());
78 span_p->line_l ()->typeset_element (span_p);
79 broken_into_l_arr_.push (span_p);
82 while ((flip(&d))!= LEFT);
86 Link_array<Item> break_points = pscore_l_->line_l_->broken_col_range (left,right);
88 break_points.insert (left,0);
89 break_points.push (right);
91 for (int i=1; i < break_points.size(); i++)
93 Drul_array<Item*> bounds;
94 bounds[LEFT] = break_points[i-1];
95 bounds[RIGHT] = break_points[i];
99 if (!bounds[d]->line_l())
100 bounds[d] = bounds[d]->find_prebroken_piece(- d);
102 while ((flip(&d))!= LEFT);
104 if (!bounds[LEFT] || ! bounds[RIGHT])
106 programming_error ("bounds of this piece aren't breakable. ");
110 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
111 span_p->set_bound(LEFT,bounds[LEFT]);
112 span_p->set_bound(RIGHT,bounds[RIGHT]);
115 assert (bounds[LEFT]->line_l () ==
116 bounds[RIGHT]->line_l ());
118 bounds[LEFT]->line_l ()->typeset_element (span_p);
119 broken_into_l_arr_.push (span_p);
122 broken_into_l_arr_.sort (Spanner::compare);
126 Spanner::set_my_columns()
128 Direction i = (Direction) LEFT;
131 if (!spanned_drul_[i]->line_l())
132 set_bound(i,spanned_drul_[i]->find_prebroken_piece((Direction) -i));
134 while (flip(&i) != LEFT);
138 Spanner::spanned_rank_iv ()
140 Interval_t<int> iv (0, 0);
142 if (spanned_drul_[LEFT])
144 iv[LEFT] = spanned_drul_[LEFT]->column_l ()->rank_i ();
146 if (spanned_drul_[RIGHT])
148 iv[RIGHT] = spanned_drul_[RIGHT]->column_l ()->rank_i ();
154 Spanner::get_bound (Direction d) const
156 return spanned_drul_ [d];
160 Spanner::set_bound(Direction d, Item*i)
165 We check for Line_of_score to prevent the column -> line_of_score
166 -> column -> line_of_score -> etc situation */
167 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
169 set_parent (i, X_AXIS);
172 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
174 warning (_f ("Spanner `%s' has equal left and right spanpoints",
179 Spanner::Spanner (SCM s)
182 spanned_drul_[LEFT]=0;
183 spanned_drul_[RIGHT]=0;
186 Spanner::Spanner (Spanner const &s)
189 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
194 Spanner::spanner_length() const
196 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
197 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
200 programming_error ("spanner with negative length");
206 Spanner::line_l() const
208 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
210 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
212 return spanned_drul_[LEFT]->line_l();
217 Spanner::find_broken_piece (Line_of_score*l) const
219 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
224 return broken_into_l_arr_ [idx];
229 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
231 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
235 Spanner::broken_b() const
237 return broken_into_l_arr_.size();
241 Spanner::get_rods () const
248 Spanner::get_springs () const
255 Spanner::do_space_processing ()
257 Array<Rod> rs (get_rods ());
258 for (int i=0; i < rs.size (); i++)
260 rs[i].add_to_cols ();
263 Array<Spring> ss (get_springs ());
264 for (int i=0; i < ss.size (); i++)
266 if (isinf (ss[i].distance_f_))
267 programming_error ("weird spring");
269 ss[i].add_to_cols ();
274 If this is a broken spanner, return the amount the left end is to be
275 shifted horizontally so that the spanner starts after the initial
276 clef and key on the staves. This is necessary for ties, slurs,
277 crescendo and decrescendo signs, for example.
280 Spanner::get_broken_left_end_align () const
282 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
284 // Relevant only if left span point is first column in line
286 sc->break_status_dir () == RIGHT)
290 We used to do a full search for the Break_align_item.
291 But that doesn't make a difference, since the Paper_column
292 is likely to contain only a Break_align_item.
294 return sc->extent (X_AXIS)[RIGHT];
301 Spanner::do_derived_mark ()
305 if (spanned_drul_[d])
306 scm_gc_mark (spanned_drul_[d]->self_scm_);
307 while (flip (&d) != LEFT);