]> git.donarmstrong.com Git - lilypond.git/blob - lily/spanner.cc
release: 1.1.18
[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
17
18 void
19 Spanner::do_print() const
20 {
21 #ifndef NPRINT
22   DOUT << "Between " << classname (spanned_drul_[LEFT])
23        << " and " << classname (spanned_drul_[RIGHT]) << '\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", classname (this)));
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::output_processing () 
137 {
138   if (transparent_b_)
139     return ;
140   output_p_ = do_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_p_, o, classname (this));
144 }
145
146 Interval
147 Spanner::do_width() const
148 {
149   Real l = spanned_drul_[LEFT]->absolute_coordinate (X_AXIS);
150   Real r = spanned_drul_[RIGHT]->absolute_coordinate (X_AXIS);
151   assert (r>=l);
152         
153   return Interval (0, r-l);
154 }
155
156 Line_of_score *
157 Spanner::line_l() const
158 {
159   if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
160     return 0;
161   if (spanned_drul_[LEFT]->line_l() != spanned_drul_[RIGHT]->line_l())
162     return 0;
163   return spanned_drul_[LEFT]->line_l();
164 }
165
166
167 Spanner*
168 Spanner::find_broken_piece (Line_of_score*l) const
169 {
170   for (int i=0; i < broken_into_l_arr_.size(); i++)
171     if (broken_into_l_arr_[i]->line_l() == l)
172       return broken_into_l_arr_[i];
173   return 0;                                
174           
175 }
176
177 bool
178 Spanner::broken_b() const
179 {
180   return broken_into_l_arr_.size();
181 }
182
183 void
184 Spanner::do_unlink() 
185 {
186   set_bounds (LEFT, 0);
187   set_bounds (RIGHT, 0);
188
189   if (unbroken_original_l_)
190     {
191       unbroken_original_l_->broken_into_l_arr_.substitute (this, 0);
192       unbroken_original_l_ =0;
193     }
194 }
195
196 void
197 Spanner::do_junk_links()
198 {
199   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
200 }
201
202 Array<Rod>
203 Spanner::get_rods () const
204 {
205   Array<Rod> r;
206   return r;
207 }
208
209 void
210 Spanner::do_space_processing ()
211 {
212   Array<Rod> rs (get_rods ());
213   for (int i=0; i < rs.size (); i++)
214     {
215       rs[i].add_to_cols ();
216     }
217 }