]> git.donarmstrong.com Git - lilypond.git/blob - lily/spacing-spanner.cc
release: 1.1.48
[lilypond.git] / lily / spacing-spanner.cc
1 /*   
2   spacing-spanner.cc --  implement Spacing_spanner
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "spacing-spanner.hh"
11 #include "score-column.hh"
12 #include "dimensions.hh"
13 #include "paper-def.hh"
14 #include "warn.hh"
15 #include "p-score.hh"
16 #include "line-of-score.hh"
17
18 Spacing_spanner::Spacing_spanner ()
19 {
20   set_elt_property (break_helper_only_scm_sym, SCM_BOOL_T);
21   set_elt_property (transparent_scm_sym, SCM_BOOL_T);
22 }
23
24 int
25 Spacing_spanner::col_count () const
26 {
27   return pscore_l_->line_l_->cols_.size ();
28 }
29
30 Score_column *
31 Spacing_spanner::scol (int i)const
32 {
33   return dynamic_cast<Score_column*> (pscore_l_->line_l_->cols_[i]);
34 }
35
36 /*
37   cut 'n paste from spring-spacer.cc
38
39   generate springs between columns.
40
41
42   TODO
43   
44   * Spacing should take optical effects into account
45   
46   The algorithm is partly taken from :
47
48   John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
49   OSU-CISRC-10/87-TR35, Department of Computer and Information
50   Science, The Ohio State University, 1987.
51   
52  */
53 Array<Spring>
54 Spacing_spanner::do_measure (int col1, int col2) const
55 {
56   for (int i =col1; i < col2; i++)
57     {
58       scol (i)->preprocess ();
59       scol (i)->print ();
60     }
61
62   Moment shortest;
63   shortest.set_infinite (1);
64   for (int i =col1; i < col2; i++)
65     {
66       if (scol(i)->musical_b ())
67         {
68           shortest = shortest <? scol(i)->shortest_starter_mom_;
69         }
70     }
71
72   Array<Spring> meas_springs;
73
74   /*
75     UGR GUR URG.  duplicate code for spacing generation.
76    */
77   for (int i= col1; i < col2; i++)
78     {
79       SCM hint = scol (i)->get_elt_property (extra_space_scm_sym);
80       if (hint != SCM_BOOL_F)
81         {
82           hint = SCM_CDR (hint);
83
84           Spring s;
85           s.item_l_drul_[LEFT] = scol (i);
86           s.item_l_drul_[RIGHT] = scol (i+1);
87           Real unbroken_dist =  gh_scm2double (SCM_CDR(hint));
88
89           s.distance_f_ = unbroken_dist;
90           s.strength_f_ = 2.0;
91           
92
93           meas_springs.push (s);
94
95           
96           Item * l = scol(i)->find_prebroken_piece (RIGHT);
97           Item * r = scol(i+1)->find_prebroken_piece (LEFT);
98           if (l)
99             {
100                 Spring s;
101                 s.item_l_drul_[LEFT] = l;
102                 s.item_l_drul_[RIGHT] = scol (i+1);
103                 hint = l->get_elt_property (extra_space_scm_sym);
104
105                 if (hint == SCM_BOOL_F)
106                   {
107                     programming_error ("No postbreak breakable spacing hint set.");
108                     s.distance_f_= unbroken_dist;
109                   }
110                 else
111                   s.distance_f_ =  gh_scm2double (SCM_CDDR(hint));
112
113                 /*
114                   space around barlines should not stretch very much.
115                  */
116                 s.strength_f_ = 2.0;
117                 meas_springs.push (s);
118             }
119
120           if (r)
121             {
122               Spring s;
123               s.item_l_drul_[LEFT] = scol (i);
124               s.item_l_drul_[RIGHT] = r;
125               s.distance_f_ =  unbroken_dist;
126               
127               /*
128                 space around barlines should not stretch very much.
129                  */
130               s.strength_f_ = 2.0;
131               meas_springs.push (s);
132             }
133
134           if (l&&r)
135             {
136               Spring s;
137               s.item_l_drul_[LEFT] = l;
138               s.item_l_drul_[RIGHT] = r;
139               
140               hint = l->get_elt_property (extra_space_scm_sym);
141               if (hint == SCM_BOOL_F)
142                 {
143                   programming_error ("No postbreak breakable spacing hint set.");
144                   s.distance_f_= unbroken_dist;
145                 }
146               else
147                 s.distance_f_ =  gh_scm2double (SCM_CDDR(hint));
148               
149               /*
150                 space around barlines should not stretch very much.
151               */
152               s.strength_f_ = 2.0;
153               meas_springs.push (s);
154             }
155         }
156       else if (!scol (i)->musical_b() && i+1 < col_count())
157         {
158           Real symbol_distance = scol (i)->extent (X_AXIS)[RIGHT] ;
159           Real durational_distance = 0;
160           Moment delta_t =  scol (i+1)->when_mom () - scol (i)->when_mom () ;
161           /*
162             ugh should use shortest_playing distance
163           */
164           if (delta_t)
165             {
166               Real k=  paper_l()->arithmetic_constant (shortest);
167               durational_distance =  paper_l()->length_mom_to_dist (delta_t,k);
168             }
169           symbol_distance += -scol (i+1)->extent(X_AXIS)[LEFT];
170
171           Spring s ;
172           s.item_l_drul_[LEFT] = scol (i);
173           s.item_l_drul_[RIGHT] = scol (i+1);
174           s.distance_f_ =  symbol_distance >? durational_distance;
175           meas_springs.push (s);
176
177           Item *l = s.item_l_drul_[LEFT]->find_prebroken_piece (RIGHT);
178           Item *r = s.item_l_drul_[RIGHT]->find_prebroken_piece (LEFT);
179           Spring sp_orig (s);
180           
181           if (l)
182             {
183               s = sp_orig;
184               s.item_l_drul_[LEFT] =l ;
185               meas_springs.push (s);
186             }
187
188           if (l && r)
189             {
190               s = sp_orig;
191               s.item_l_drul_[RIGHT] = r;
192               s.item_l_drul_[LEFT] = l;
193               meas_springs.push (s);
194             }
195           
196         }
197     }
198
199   for (int i=col1; i < col2; i++)
200     {
201       if (scol (i)->musical_b())
202         {
203           Moment shortest_playing_len = scol(i)->shortest_playing_mom_;
204           if (! shortest_playing_len)
205             {
206               warning (_f ("can't find a ruling note at %s", 
207                 scol (i)->when_mom ().str ()));
208               shortest_playing_len = 1;
209             }
210           if (! shortest)
211             {
212               warning (_f ("no minimum in measure at %s", 
213                       scol (i)->when_mom ().str ()));
214               shortest = 1;
215             }
216           Moment delta_t = scol (i+1)->when_mom () - scol (i)->when_mom ();
217           Real k=  paper_l()->arithmetic_constant(shortest);
218           Real dist = paper_l()->length_mom_to_dist (shortest_playing_len, k);
219           dist *= (double)(delta_t / shortest_playing_len);
220
221
222           Spring sp;
223           sp.distance_f_ =  dist;
224           sp.item_l_drul_[LEFT] = scol (i);
225           sp.item_l_drul_[RIGHT] = scol (i+1);
226
227           meas_springs.push (sp);
228
229           /*
230             UGH. TODO: more
231             advanced spacing here.
232            */
233           Spring sp_orig (sp);
234
235           Item *r =  sp.item_l_drul_[RIGHT]->find_prebroken_piece (LEFT);
236           
237           if (r)
238             {
239               sp = sp_orig;
240               sp.item_l_drul_[RIGHT] =r ;
241               meas_springs.push (sp);
242             }
243         }
244     }
245   return meas_springs;
246 }
247
248 Array<Spring>
249 Spacing_spanner::get_springs () const
250 {
251   Array<Spring> springs;
252   int last_break =0;
253   for (int i=1; i < col_count (); i++)
254     {
255       if (scol (i)->breakable_b ())
256         {
257           springs.concat (do_measure (last_break, i));
258           last_break  = i;
259         }
260     }
261   return springs;
262 }
263
264