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];
34 warning (_f ("Spanner `%s' has equal left and right spanpoints",
39 Check if our parent in X-direction spans equally wide
42 for (int a = X_AXIS; a < NO_AXES; a ++)
44 if (Spanner* parent = dynamic_cast<Spanner*> (parent_l ((Axis)a)))
46 if (!parent->spanned_rank_iv ().contains_b (this->spanned_rank_iv ()))
48 programming_error (to_str ("Spanner `%s' is not fully contained in parent spanner `%s'.",
55 if (line_l () || broken_b ())
61 FIXME: this is broken.
64 If we have a spanner spanning one column, we must break it
65 anyway because it might provide a parent for another item. */
69 Item* bound = left->find_prebroken_piece (d);
72 Spanner * span_p = dynamic_cast<Spanner*>( clone ());
73 span_p->set_bound (LEFT, bound);
74 span_p->set_bound (RIGHT, bound);
76 assert (span_p->line_l ());
77 span_p->line_l ()->typeset_element (span_p);
78 broken_into_l_arr_.push (span_p);
81 while ((flip(&d))!= LEFT);
85 Link_array<Item> break_points = pscore_l_->line_l_->broken_col_range (left,right);
87 break_points.insert (left,0);
88 break_points.push (right);
90 for (int i=1; i < break_points.size(); i++)
92 Drul_array<Item*> bounds;
93 bounds[LEFT] = break_points[i-1];
94 bounds[RIGHT] = break_points[i];
98 if (!bounds[d]->line_l())
99 bounds[d] = bounds[d]->find_prebroken_piece(- d);
101 while ((flip(&d))!= LEFT);
103 if (!bounds[LEFT] || ! bounds[RIGHT])
105 programming_error ("bounds of this piece aren't breakable. ");
109 Spanner *span_p = dynamic_cast<Spanner*>(clone ());
110 span_p->set_bound(LEFT,bounds[LEFT]);
111 span_p->set_bound(RIGHT,bounds[RIGHT]);
114 assert (bounds[LEFT]->line_l () ==
115 bounds[RIGHT]->line_l ());
117 bounds[LEFT]->line_l ()->typeset_element (span_p);
118 broken_into_l_arr_.push (span_p);
121 broken_into_l_arr_.sort (Spanner::compare);
125 Spanner::set_my_columns()
127 Direction i = (Direction) LEFT;
130 if (!spanned_drul_[i]->line_l())
131 set_bound(i,spanned_drul_[i]->find_prebroken_piece((Direction) -i));
133 while (flip(&i) != LEFT);
137 Spanner::spanned_rank_iv ()
139 Interval_t<int> iv (0, 0);
141 if (spanned_drul_[LEFT])
143 iv[LEFT] = spanned_drul_[LEFT]->column_l ()->rank_i ();
145 if ( spanned_drul_[RIGHT])
147 iv[RIGHT] = spanned_drul_[RIGHT]->column_l ()->rank_i ();
153 Spanner::get_bound (Direction d) const
155 return spanned_drul_ [d];
159 Spanner::set_bound(Direction d, Item*i)
168 We check for Line_of_score to prevent the column -> line_of_score
169 -> column -> line_of_score -> etc situation */
170 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
172 set_parent (i, X_AXIS);
175 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
177 warning (_f ("Spanner `%s' has equal left and right spanpoints",
184 spanned_drul_[LEFT]=0;
185 spanned_drul_[RIGHT]=0;
188 Spanner::Spanner (Spanner const &s)
191 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
196 Spanner::spanner_length() const
198 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
199 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
202 programming_error ("spanner with negative length");
208 Spanner::line_l() const
210 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
212 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
214 return spanned_drul_[LEFT]->line_l();
219 Spanner::find_broken_piece (Line_of_score*l) const
221 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
226 return broken_into_l_arr_ [idx];
231 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
233 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
237 Spanner::broken_b() const
239 return broken_into_l_arr_.size();
243 Spanner::get_rods () const
250 Spanner::get_springs () const
257 Spanner::do_space_processing ()
259 Array<Rod> rs (get_rods ());
260 for (int i=0; i < rs.size (); i++)
262 rs[i].add_to_cols ();
265 Array<Spring> ss (get_springs ());
266 for (int i=0; i < ss.size (); i++)
268 if (isinf (ss[i].distance_f_))
269 programming_error ("weird spring");
271 ss[i].add_to_cols ();
276 If this is a broken spanner, return the amount the left end is to be
277 shifted horizontally so that the spanner starts after the initial
278 clef and key on the staves. This is necessary for ties, slurs,
279 crescendo and decrescendo signs, for example.
282 Spanner::get_broken_left_end_align () const
284 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
286 // Relevant only if left span point is first column in line
288 sc->break_status_dir () == RIGHT)
292 We used to do a full search for the Break_align_item.
293 But that doesn't make a difference, since the Paper_column
294 is likely to contain only a Break_align_item.
296 return sc->extent (X_AXIS)[RIGHT];