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)))
45 Urg, should use instantiate-compare, or maybe mysterious
46 column_width/contains functions?
48 if (spanned_drul_[LEFT] && spanned_drul_[RIGHT]
49 && parent->spanned_drul_[LEFT] && parent->spanned_drul_[RIGHT])
51 if (parent->spanned_drul_[LEFT]->column_l ()->rank_i ()
52 > spanned_drul_[LEFT]->column_l ()->rank_i () > 0
53 || parent->spanned_drul_[RIGHT]->column_l ()->rank_i ()
54 < spanned_drul_[RIGHT]->column_l ()->rank_i ())
56 warning (_f ("Spanner `%s' is not fully contained in parent spanner `%s'.",
57 classname (this), classname (parent)));
62 column_width (), contains ()?
64 if (!parent->column_width ().contains (this->column_width ()))
66 warning (_f ("Spanner `%s' is not fully contained in parent spanner `%s'.",
67 classname (this), classname (parent)));
73 if (line_l () || broken_b ())
79 FIXME: this is broken.
82 If we have a spanner spanning one column, we must break it
83 anyway because it might provide a parent for another item. */
87 Item* bound = left->find_broken_piece (d);
88 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
89 span_p->set_bound (LEFT, bound);
90 span_p->set_bound (RIGHT, bound);
92 assert (span_p->line_l ());
93 pscore_l_->typeset_element (span_p);
94 broken_into_l_arr_.push (span_p);
96 while ((flip(&d))!= LEFT);
100 Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
102 break_points.insert (left,0);
103 break_points.push (right);
105 for (int i=1; i < break_points.size(); i++)
107 Drul_array<Item*> bounds;
108 bounds[LEFT] = break_points[i-1];
109 bounds[RIGHT] = break_points[i];
113 Item *&pc_l = bounds[d] ;
115 pc_l = pc_l->find_broken_piece(- d);
119 while ((flip(&d))!= LEFT);
121 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
122 span_p->set_bound(LEFT,bounds[LEFT]);
123 span_p->set_bound(RIGHT,bounds[RIGHT]);
125 pscore_l_->typeset_element (span_p);
126 broken_into_l_arr_.push (span_p);
129 broken_into_l_arr_.sort (Spanner::compare);
133 Spanner::set_my_columns()
135 Direction i = (Direction) LEFT;
138 if (!spanned_drul_[i]->line_l())
139 set_bound(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
141 while (flip(&i) != LEFT);
146 Spanner::get_bound (Direction d) const
148 return spanned_drul_ [d];
152 Spanner::set_bound(Direction d, Item*i)
161 Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
163 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
165 set_parent (i, X_AXIS);
168 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
170 warning (_f ("Spanner `%s' has equal left and right spanpoints",
177 spanned_drul_[LEFT]=0;
178 spanned_drul_[RIGHT]=0;
181 Spanner::Spanner (Spanner const &s)
184 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
189 Spanner::spanner_length() const
191 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
192 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
195 programming_error ("spanner with negative length");
201 Spanner::line_l() const
203 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
205 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
207 return spanned_drul_[LEFT]->line_l();
212 Spanner::find_broken_piece (Line_of_score*l) const
214 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
219 return broken_into_l_arr_ [idx];
224 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
226 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
230 Spanner::broken_b() const
232 return broken_into_l_arr_.size();
236 Spanner::get_rods () const
243 Spanner::get_springs () const
250 Spanner::do_space_processing ()
252 Array<Rod> rs (get_rods ());
253 for (int i=0; i < rs.size (); i++)
255 rs[i].add_to_cols ();
258 Array<Spring> ss (get_springs ());
259 for (int i=0; i < ss.size (); i++)
261 if (isinf (ss[i].distance_f_))
262 programming_error ("weird spring");
264 ss[i].add_to_cols ();
269 If this is a broken spanner, return the amount the left end is to be
270 shifted horizontally so that the spanner starts after the initial
271 clef and key on the staves. This is necessary for ties, slurs,
272 crescendo and decrescendo signs, for example.
275 Spanner::get_broken_left_end_align () const
277 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
279 // Relevant only if left span point is first column in line
281 sc->break_status_dir () == RIGHT)
285 We used to do a full search for the Break_align_item.
286 But that doesn't make a difference, since the Paper_column
287 is likely to contain only a Break_align_item.
289 return sc->extent (X_AXIS)[RIGHT];