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)
164 We check for Line_of_score to prevent the column -> line_of_score
165 -> column -> line_of_score -> etc situation */
166 if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
168 set_parent (i, X_AXIS);
171 if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
173 warning (_f ("Spanner `%s' has equal left and right spanpoints",
178 Spanner::Spanner (SCM s)
181 spanned_drul_[LEFT]=0;
182 spanned_drul_[RIGHT]=0;
185 Spanner::Spanner (Spanner const &s)
188 spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
193 Spanner::spanner_length() const
195 Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
196 Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
199 programming_error ("spanner with negative length");
205 Spanner::line_l() const
207 if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
209 if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
211 return spanned_drul_[LEFT]->line_l();
216 Spanner::find_broken_piece (Line_of_score*l) const
218 int idx = binsearch_link_array (broken_into_l_arr_, (Spanner*)l, Spanner::compare);
223 return broken_into_l_arr_ [idx];
228 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
230 return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
234 Spanner::broken_b() const
236 return broken_into_l_arr_.size();
240 Spanner::get_rods () const
247 Spanner::get_springs () const
254 Spanner::do_space_processing ()
256 Array<Rod> rs (get_rods ());
257 for (int i=0; i < rs.size (); i++)
259 rs[i].add_to_cols ();
262 Array<Spring> ss (get_springs ());
263 for (int i=0; i < ss.size (); i++)
265 if (isinf (ss[i].distance_f_))
266 programming_error ("weird spring");
268 ss[i].add_to_cols ();
273 If this is a broken spanner, return the amount the left end is to be
274 shifted horizontally so that the spanner starts after the initial
275 clef and key on the staves. This is necessary for ties, slurs,
276 crescendo and decrescendo signs, for example.
279 Spanner::get_broken_left_end_align () const
281 Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
283 // Relevant only if left span point is first column in line
285 sc->break_status_dir () == RIGHT)
289 We used to do a full search for the Break_align_item.
290 But that doesn't make a difference, since the Paper_column
291 is likely to contain only a Break_align_item.
293 return sc->extent (X_AXIS)[RIGHT];