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"
22 Spanner::do_break_processing()
26 if (line_l () || broken_b ())
29 Item * left = spanned_drul_[LEFT];
30 Item * right = spanned_drul_[RIGHT];
34 warning (_ ("Left spanpoint is right spanpoint"));
37 FIXME: this is broken.
40 If we have a spanner spanning one column, we must break it
41 anyway because it might provide a parent for another item. */
45 Item* bound = left->find_broken_piece (d);
46 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
47 span_p->set_bound (LEFT, bound);
48 span_p->set_bound (RIGHT, bound);
50 assert (span_p->line_l ());
51 pscore_l_->typeset_element (span_p);
52 broken_into_l_arr_.push (span_p);
54 while ((flip(&d))!= LEFT);
58 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
60 break_points.insert (left,0);
61 break_points.push (right);
63 for (int i=1; i < break_points.size(); i++)
65 Drul_array<Item*> bounds;
66 bounds[LEFT] = break_points[i-1];
67 bounds[RIGHT] = break_points[i];
71 Item *&pc_l = bounds[d] ;
73 pc_l = pc_l->find_broken_piece(- d);
77 while ((flip(&d))!= LEFT);
79 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
80 span_p->set_bound(LEFT,bounds[LEFT]);
81 span_p->set_bound(RIGHT,bounds[RIGHT]);
83 pscore_l_->typeset_element (span_p);
84 broken_into_l_arr_.push (span_p);
87 broken_into_l_arr_.sort (Spanner::compare);
91 Spanner::set_my_columns()
93 Direction i = (Direction) LEFT;
96 if (!spanned_drul_[i]->line_l())
97 set_bound(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
99 while (flip(&i) != LEFT);
104 Spanner::get_bound (Direction d) const
106 return spanned_drul_ [d];
110 Spanner::set_bound(Direction d, Item*i)
119 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
121 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
123 set_parent (i, X_AXIS);
126 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
128 warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
134 spanned_drul_[LEFT]=0;
135 spanned_drul_[RIGHT]=0;
138 Spanner::Spanner (Spanner const &s)
141 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
146 Spanner::spanner_length() const
148 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
149 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
152 programming_error ("spanner with negative length");
158 Spanner::line_l() const
160 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
162 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
164 return spanned_drul_[LEFT]->line_l();
169 Spanner::find_broken_piece (Line_of_score*l) const
171 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
176 return broken_into_l_arr_ [idx];
181 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
183 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
187 Spanner::broken_b() const
189 return broken_into_l_arr_.size();
193 Spanner::get_rods () const
200 Spanner::get_springs () const
207 Spanner::do_space_processing ()
209 Array<Rod> rs (get_rods ());
210 for (int i=0; i < rs.size (); i++)
212 rs[i].add_to_cols ();
215 Array<Spring> ss (get_springs ());
216 for (int i=0; i < ss.size (); i++)
218 if (isinf (ss[i].distance_f_))
219 programming_error ("weird spring");
221 ss[i].add_to_cols ();
226 If this is a broken spanner, return the amount the left end is to be
227 shifted horizontally so that the spanner starts after the initial
228 clef and key on the staves. This is necessary for ties, slurs,
229 crescendo and decrescendo signs, for example.
232 Spanner::get_broken_left_end_align () const
234 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
236 // Relevant only if left span point is first column in line
238 sc->break_status_dir () == RIGHT)
242 We used to do a full search for the Break_align_item.
243 But that doesn't make a difference, since the Paper_column
244 is likely to contain only a Break_align_item.
246 return sc->extent (X_AXIS)[RIGHT];