]> git.donarmstrong.com Git - lilypond.git/blob - lily/spacing-loose-columns.cc
9eda23b1a1dff2379b0deadd41cd094fd01bb0e5
[lilypond.git] / lily / spacing-loose-columns.cc
1 /*
2   spacing-loose-columns.cc -- implement loose column spacing.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9
10 #include "system.hh"
11 #include "paper-column.hh"
12 #include "column-x-positions.hh"
13 #include "pointer-group-interface.hh"
14 #include "staff-spacing.hh"
15 #include "note-spacing.hh"
16 #include "spacing-spanner.hh"
17
18 #include "moment.hh"
19
20 /* Find the loose columns in POSNS, and drape them around the columns
21    specified in BETWEEN-COLS.  */
22 void
23 set_loose_columns (System *which, Column_x_positions const *posns)
24 {
25   int loose_col_count = posns->loose_cols_.size ();
26   if (!loose_col_count)
27     return; 
28
29   Real default_padding = 1.0;
30   for (int i = 0; i < loose_col_count; i++)
31     {
32       int divide_over = 1;
33       Item *loose = dynamic_cast<Item *> (posns->loose_cols_[i]);
34       Paper_column *col = dynamic_cast<Paper_column *> (loose);
35
36       if (col->get_system ())
37         continue;
38
39       Item *left = 0;
40       Item *right = 0;
41
42       Link_array<Item> clique;
43       while (1)
44         {
45           SCM between = loose->get_object ("between-cols");
46           if (!scm_is_pair (between))
47             break;
48
49           Item *le = dynamic_cast<Item *> (unsmob_grob (scm_car (between)));
50           Item *re = dynamic_cast<Item *> (unsmob_grob (scm_cdr (between)));
51
52           if (! (le && re))
53             break;
54
55           if (!left && le)
56             {
57               left = le->get_column ();
58               if (!left->get_system ())
59                 left = left->find_prebroken_piece (RIGHT);
60
61               clique.push (left);
62             }
63           
64           clique.push (loose);
65
66           divide_over++;
67           loose = right = re->get_column ();
68         }
69
70       if (!right->get_system ())
71         right = right->find_prebroken_piece (LEFT);
72
73       clique.push (right);
74
75       Grob *common = right->common_refpoint (left, X_AXIS);
76       Item *finished_right_column = clique.top();
77       
78       for (int j = clique.size() - 2; j > 0; j--)
79         {
80           int count = 0;
81           Real total_space = 0.0;
82           Real total_fixed = 0.0;
83
84           extract_grob_set (col, "spacing-wishes", wishes);
85           for (int i = 0; i < wishes.size (); i++)
86             {
87               Grob *spacing = wishes[i];
88               Real space = 0.0;
89               Real fixed = 0.0;
90
91               if (Staff_spacing::has_interface (spacing))
92                 {
93                   Staff_spacing::get_spacing_params (spacing, &space, &fixed);
94                 }
95               else if (Note_spacing::has_interface (spacing))
96                 {
97                   Spacing_options options;
98                   options.init ();
99
100                   fixed = robust_relative_extent (col, col, X_AXIS)[RIGHT];
101
102                   Moment dt = Paper_column::when_mom (right) - Paper_column::when_mom (col);
103                   bool expand;
104                   space = options.get_duration_space (dt, &expand);
105                   Note_spacing::get_spacing (spacing, right, space, options.increment_,
106                                              &space, &fixed);
107                 }
108               else
109                 {
110                   continue;
111                 }
112           
113               count++;
114
115               total_space += space;
116               total_fixed += fixed;
117             }
118
119           Real distance_to_next = 0.0;
120           Real right_point = 0.0;  
121           if (count)
122             {
123               total_space /= count;
124               total_fixed /= count;
125
126               distance_to_next = total_space;
127               right_point
128                 = finished_right_column->relative_coordinate (common, X_AXIS);
129             }
130           else
131             {
132               Interval my_extent = col->extent (col, X_AXIS);
133               distance_to_next = my_extent[RIGHT] + default_padding;
134               right_point = finished_right_column->extent (common, X_AXIS)[LEFT];
135             }
136
137           Real my_offset = right_point - distance_to_next;
138           
139           col->system_ = which;
140           col->translate_axis (my_offset - col->relative_coordinate (common, X_AXIS), X_AXIS);
141
142           finished_right_column = col;
143         }
144     }
145 }
146
147