]> git.donarmstrong.com Git - lilypond.git/blob - lily/spanner.cc
0a1a74e5bd09c62a67acc44958a1c111fd8da743
[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 "tex-outputter.hh"
14 #include "molecule.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 = clone()->access_Spanner ();
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* 
122 Spanner::access_Spanner ()
123 {
124   return this;
125 }
126
127 Spanner::Spanner ()
128 {
129   unbroken_original_l_ =0;
130   spanned_drul_[LEFT]=0;
131   spanned_drul_[RIGHT]=0;
132 }
133
134 Spanner::Spanner (Spanner const &s)
135   :Score_element (s)
136 {
137   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
138   unbroken_original_l_ = &s;
139 }
140
141 void
142 Spanner::do_brew_molecule () 
143 {
144   if (transparent_b_)
145     return ;
146   Molecule *output= brew_molecule_p ();
147   Offset left_off (spanned_drul_[LEFT]->absolute_coordinate(X_AXIS), 0);
148   Offset o = absolute_offset() + left_off;
149   pscore_l_->outputter_l_->output_molecule (output, o, name ());
150   delete output;
151 }
152
153 Interval
154 Spanner::do_width() const
155 {
156   Real l = spanned_drul_[LEFT]->absolute_coordinate (X_AXIS);
157   Real r = spanned_drul_[RIGHT]->absolute_coordinate (X_AXIS);
158   assert (r>=l);
159         
160   return Interval (0, r-l);
161 }
162
163 Line_of_score *
164 Spanner::line_l() const
165 {
166   if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
167     return 0;
168   if (spanned_drul_[LEFT]->line_l() != spanned_drul_[RIGHT]->line_l())
169     return 0;
170   return spanned_drul_[LEFT]->line_l();
171 }
172
173
174 Spanner*
175 Spanner::find_broken_piece (Line_of_score*l) const
176 {
177   for (int i=0; i < broken_into_l_arr_.size(); i++)
178     if (broken_into_l_arr_[i]->line_l() == l)
179       return broken_into_l_arr_[i];
180   return 0;                                
181           
182 }
183
184 bool
185 Spanner::broken_b() const
186 {
187   return broken_into_l_arr_.size();
188 }
189
190 void
191 Spanner::do_unlink() 
192 {
193   set_bounds (LEFT, 0);
194   set_bounds (RIGHT, 0);
195
196   if (unbroken_original_l_)
197     {
198       unbroken_original_l_->broken_into_l_arr_.substitute (this, 0);
199       unbroken_original_l_ =0;
200     }
201 }
202
203 void
204 Spanner::do_junk_links()
205 {
206   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
207 }
208
209 Array<Rod>
210 Spanner::get_rods () const
211 {
212   Array<Rod> r;
213   return r;
214 }
215
216 void
217 Spanner::do_space_processing ()
218 {
219   Array<Rod> rs (get_rods ());
220   for (int i=0; i < rs.size (); i++)
221     {
222       rs[i].add_to_cols ();
223     }
224 }