]> git.donarmstrong.com Git - lilypond.git/blob - lily/spanner.cc
release: 1.1.1
[lilypond.git] / lily / spanner.cc
1 /*
2   spanner.cc -- implement Spanner
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996, 1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "debug.hh"
10 #include "spanner.hh"
11 #include "p-col.hh"
12 #include "p-score.hh"
13 #include "molecule.hh"
14 #include "paper-outputter.hh"
15
16 IMPLEMENT_IS_TYPE_B1(Spanner,Score_element);
17
18 void
19 Spanner::do_print() const
20 {
21 #ifndef NPRINT
22   DOUT << "Between " << spanned_drul_[LEFT]->name ()
23        << " and " << spanned_drul_[RIGHT]->name() << '\n';
24   if (broken_into_l_arr_.size())
25     {
26       DOUT << "with broken pieces:\n";
27       for (int i=0; i < broken_into_l_arr_.size (); i++)
28         broken_into_l_arr_[i]->print ();
29     }  
30 #endif
31 }
32
33 void
34 Spanner::break_into_pieces ()
35 {
36   if (broken_into_l_arr_.size())
37     return; 
38          
39   Item * left = spanned_drul_[LEFT];
40   Item * right = spanned_drul_[RIGHT];
41   
42   if  (left == right)
43     {
44       warning (_ ("left spanpoint is right spanpoint\n"));
45       return;
46     }
47   
48   Link_array<Item> break_cols = pscore_l_->broken_col_range (left,right);
49   Link_array<Spanner> broken_into_l_arr;
50
51   break_cols.insert (left,0);
52   break_cols.push (right);
53
54   for (int i=1; i < break_cols.size(); i++) 
55     {
56       Spanner* span_p = dynamic_cast<Spanner*> (clone());
57       Item *left = break_cols[i-1];
58       Item *right = break_cols[i];
59       if (!right->line_l())
60         right = right->find_prebroken_piece(LEFT);
61       if (!left->line_l())
62         left = left->find_prebroken_piece(RIGHT);
63
64       assert (left&&right && left->line_l() == right->line_l());
65
66       span_p->set_bounds(LEFT,left);
67       span_p->set_bounds(RIGHT,right);
68         
69       pscore_l_->typeset_broken_spanner (span_p);
70       broken_into_l_arr.push (span_p);
71     }
72    
73   broken_into_l_arr_ = broken_into_l_arr;
74 }
75
76 void
77 Spanner::set_my_columns()
78 {
79   Direction i = (Direction)1;
80   do 
81     {
82       if (!spanned_drul_[i]->line_l())
83         set_bounds(i,spanned_drul_[i]->find_prebroken_piece((Direction)-i));
84     } 
85   while (flip(&i) != 1);
86 }       
87
88
89 void
90 Spanner::set_bounds(Direction d, Item*i)
91 {
92   if (spanned_drul_[d])
93     spanned_drul_[d]->attached_span_l_arr_.substitute(this,0);
94   
95   spanned_drul_[d] =i;
96   if (i)
97     i->attached_span_l_arr_.push(this);
98
99   if  (spanned_drul_[Direction(-d)] == spanned_drul_[d]
100        && i)
101     warning (_f ("Spanner `%s\' with equal left and right spanpoints", name ()));
102 }
103
104 void
105 Spanner::do_break_processing()
106 {
107   if (!line_l())
108     {
109       break_into_pieces ();
110       for (int i=0; i < broken_into_l_arr_.size(); i++)
111         {
112           broken_into_l_arr_[i]->handle_broken_dependencies();
113         }
114     }
115   else 
116     {
117       handle_broken_dependencies();
118     }
119 }
120
121 Spanner::Spanner ()
122 {
123   unbroken_original_l_ =0;
124   spanned_drul_[LEFT]=0;
125   spanned_drul_[RIGHT]=0;
126 }
127
128 Spanner::Spanner (Spanner const &s)
129   :Score_element (s)
130 {
131   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
132   unbroken_original_l_ = &s;
133 }
134
135 void
136 Spanner::do_brew_molecule () 
137 {
138   if (transparent_b_)
139     return ;
140   Molecule *output= brew_molecule_p ();
141   Offset left_off (spanned_drul_[LEFT]->absolute_coordinate(X_AXIS), 0);
142   Offset o = absolute_offset() + left_off;
143   pscore_l_->outputter_l_->output_molecule (output, o, name ());
144   delete output;
145 }
146
147 Interval
148 Spanner::do_width() const
149 {
150   Real l = spanned_drul_[LEFT]->absolute_coordinate (X_AXIS);
151   Real r = spanned_drul_[RIGHT]->absolute_coordinate (X_AXIS);
152   assert (r>=l);
153         
154   return Interval (0, r-l);
155 }
156
157 Line_of_score *
158 Spanner::line_l() const
159 {
160   if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
161     return 0;
162   if (spanned_drul_[LEFT]->line_l() != spanned_drul_[RIGHT]->line_l())
163     return 0;
164   return spanned_drul_[LEFT]->line_l();
165 }
166
167
168 Spanner*
169 Spanner::find_broken_piece (Line_of_score*l) const
170 {
171   for (int i=0; i < broken_into_l_arr_.size(); i++)
172     if (broken_into_l_arr_[i]->line_l() == l)
173       return broken_into_l_arr_[i];
174   return 0;                                
175           
176 }
177
178 bool
179 Spanner::broken_b() const
180 {
181   return broken_into_l_arr_.size();
182 }
183
184 void
185 Spanner::do_unlink() 
186 {
187   set_bounds (LEFT, 0);
188   set_bounds (RIGHT, 0);
189
190   if (unbroken_original_l_)
191     {
192       unbroken_original_l_->broken_into_l_arr_.substitute (this, 0);
193       unbroken_original_l_ =0;
194     }
195 }
196
197 void
198 Spanner::do_junk_links()
199 {
200   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
201 }
202
203 Array<Rod>
204 Spanner::get_rods () const
205 {
206   Array<Rod> r;
207   return r;
208 }
209
210 void
211 Spanner::do_space_processing ()
212 {
213   Array<Rod> rs (get_rods ());
214   for (int i=0; i < rs.size (); i++)
215     {
216       rs[i].add_to_cols ();
217     }
218 }