]> git.donarmstrong.com Git - lilypond.git/blob - lily/separating-group-spanner.cc
release: 1.5.29
[lilypond.git] / lily / separating-group-spanner.cc
1 /*   
2   separating-group-spanner.cc --  implement Separating_group_spanner
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1998--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "separating-group-spanner.hh"
11 #include "separation-item.hh"
12 #include "paper-column.hh"
13 #include "paper-def.hh"
14 #include "dimensions.hh"
15 #include "group-interface.hh"
16
17 void
18 Separating_group_spanner::find_rods (Item * r, SCM next)
19 {
20   Interval ri (Separation_item::my_width (r));
21   if (ri.empty_b ())
22     return;
23
24   /*
25     This is an inner loop, however, in most cases, the interesting L
26     will just be the first entry of NEXT, making it linear in most of
27     the cases.  */
28   for(; gh_pair_p (next); next = ly_cdr (next))
29     {
30       Item *l = dynamic_cast<Item*> (unsmob_grob (ly_car( next)));
31       Item *lb = l->find_prebroken_piece (RIGHT);
32
33       if (lb)
34         {
35           Interval li (Separation_item::my_width (lb));
36
37           if (!li.empty_b ())
38             {
39               Rod rod;
40
41               rod.item_l_drul_[LEFT] = lb;
42               rod.item_l_drul_[RIGHT] = r;
43
44               rod.distance_f_ = li[RIGHT] - ri[LEFT];
45         
46               rod.columnize ();
47               rod.add_to_cols ();
48             }
49         }
50
51       Interval li (Separation_item::my_width (l));
52       if (!li.empty_b ())
53         {
54           Rod rod;
55
56           rod.item_l_drul_[LEFT] =l;
57           rod.item_l_drul_[RIGHT]=r;
58
59           rod.distance_f_ = li[RIGHT] - ri[LEFT];
60         
61           rod.columnize ();
62           rod.add_to_cols ();
63
64           break;
65         }
66       else
67         /*
68           this grob doesn't cause a constraint. We look further until we
69           find one that does.  */
70         ;
71     }
72 }
73
74 MAKE_SCHEME_CALLBACK (Separating_group_spanner,set_spacing_rods_and_seqs,1);
75 SCM
76 Separating_group_spanner::set_spacing_rods_and_seqs (SCM smob)
77 {
78   set_spacing_rods (smob);
79   find_musical_sequences (unsmob_grob (smob));
80   return SCM_UNSPECIFIED;
81 }
82
83 MAKE_SCHEME_CALLBACK (Separating_group_spanner,set_spacing_rods,1);
84 SCM
85 Separating_group_spanner::set_spacing_rods (SCM smob)
86 {
87   Grob*me = unsmob_grob (smob);
88   
89   for (SCM s = me->get_grob_property ("elements"); gh_pair_p (s) && gh_pair_p (ly_cdr (s)); s = ly_cdr (s))
90     {
91       /*
92         Order of elements is reversed!
93        */
94       SCM elt = ly_car (s);
95       Item *r = unsmob_item (elt);
96
97       if (!r)
98         continue;
99
100       Item *rb
101         = dynamic_cast<Item*> (r->find_prebroken_piece (LEFT));
102       
103       find_rods (r, ly_cdr (s));
104       if (rb)
105         find_rods (rb, ly_cdr (s));
106     }
107   find_musical_sequences (me);
108
109 #if 0
110   /*
111     TODO; restore this.
112    */
113   /*
114     We've done our job, so we get lost. 
115    */
116   for (SCM s = me->get_grob_property ("elements"); gh_pair_p (s); s = ly_cdr (s))
117     {
118       Item * it =dynamic_cast<Item*> (unsmob_grob (ly_car (s)));
119       if (it && it->broken_b ())
120         {
121           it->find_prebroken_piece (LEFT) ->suicide ();
122           it->find_prebroken_piece (RIGHT)->suicide ();
123         }
124       it->suicide ();
125     }
126   me->suicide ();
127 #endif
128   return SCM_UNSPECIFIED ;
129 }
130
131 void
132 Separating_group_spanner::add_spacing_unit (Grob* me ,Item*i)
133 {
134   Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), i);
135   me->add_dependency (i);
136 }
137
138
139 void
140 Separating_group_spanner::find_musical_sequences (Grob *me)
141 {
142   Item *last = 0;
143   Item *llast = 0;
144   for (SCM s = me->get_grob_property ("elements");
145        gh_pair_p (s); s = ly_cdr (s))
146     {
147       Item *it = dynamic_cast<Item*> (unsmob_grob (ly_car (s)));
148       if (last)
149         {       
150           Item *lcol = last->column_l ();
151           Item *col = it->column_l ();
152
153           int lrank = Paper_column::rank_i (lcol);
154           int rank = Paper_column ::rank_i (col);
155
156           bool mus = Paper_column::musical_b (col);
157           bool lmus = Paper_column::musical_b (lcol);
158
159           if ((lrank - rank == 2) && lmus && mus)
160             {
161               SCM seq = col->get_grob_property ("spacing-sequence");
162               col->set_grob_property ("spacing-sequence",
163                                       gh_cons (gh_cons (it->self_scm (), last->self_scm ()), seq));
164             }
165
166           if (llast && !Paper_column::breakable_b (last))
167             {
168               Item *llcol = llast->column_l ();
169               int llrank = Paper_column::rank_i (llcol);
170               bool llmus= Paper_column::musical_b (llcol);
171               if (llrank - lrank == 1
172                   && lrank - rank == 1
173                   && llmus && !lmus && mus)
174                 {
175                   /*
176                     these columns are adjacent, so set spacing-sequence in
177                     IT.
178                     
179                      Q     Q+1    Q+2   (rank)
180                     Note  Clef   Note
181
182                     IT    LAST   LLAST  
183                     
184                    */
185                   SCM seq = col->get_grob_property ("spacing-sequence");
186                   col->set_grob_property ("spacing-sequence",
187                                           gh_cons (gh_cons (it->self_scm (), last->self_scm ()), seq));
188
189                   /*
190                     lcol can not be a loose column, so we make sure
191                     that is and will not be marked as such.
192                   */
193                   lcol->set_grob_property ("between-cols" ,  SCM_BOOL_F);
194                 }
195               else if (!lmus)
196                 {
197                   SCM between = lcol->get_grob_property ("between-cols");
198
199                   if (between == SCM_BOOL_F)
200                     continue;
201                   
202                   if (!gh_pair_p (between))
203                     {
204                       between = gh_cons (it->self_scm (), llast->self_scm ());
205                       lcol ->set_grob_property ("between-cols", between);
206                     }
207
208                   Item * left
209                     = dynamic_cast<Item*> (unsmob_grob (ly_car (between)));
210                   if(Paper_column::rank_i (left->column_l ()) < rank)
211                     gh_set_car_x (between, col->self_scm());
212                   
213                   Item * right
214                     = dynamic_cast<Item*> (unsmob_grob (ly_cdr (between)));
215                   if (Paper_column::rank_i (right->column_l ()) > llrank )
216                     gh_set_cdr_x (between, llcol->self_scm ());
217                 }
218             }
219         }
220
221       llast = last;
222       last = it;
223     }
224 }
225
226 #if 0
227 void
228 Separating_group_spanner::set_loose_rods ()
229 {
230   // loose columns should  also generate minimum distances.
231   // TODO
232 }
233 #endif
234
235
236 void
237 Separating_group_spanner::set_interface (Grob*)
238 {
239 }
240
241 bool
242 Separating_group_spanner::has_interface (Grob*)
243 {//todo
244   assert (false);
245 }