]> git.donarmstrong.com Git - lilypond.git/blob - lily/align-element.cc
b637ebd5d0fab21dd7d5e8e39175928aeb3a0182
[lilypond.git] / lily / align-element.cc
1 /*
2   align-elem.cc -- implement Align_elem
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "align-element.hh"
10 #include "interval.hh"
11 #include "direction.hh"
12 #include "debug.hh"
13
14 struct Align_element_content {
15   Score_element * elem_l_;
16   int priority_i_;
17   
18   static int compare (Align_element_content const &h1, 
19                       Align_element_content const &h2) 
20     {
21       return h1.priority_i_ - h2.priority_i_;
22     }
23   Align_element_content (Score_element *elem_l, int p) 
24     {
25       priority_i_ = p;
26       elem_l_ = elem_l;
27     }
28   Align_element_content () {
29     elem_l_ = 0;
30     priority_i_ = 0;
31   }
32 };
33
34
35
36 void
37 Align_element::add_element (Score_element*el_l)
38 {
39   int p = priority_i_arr_.size ();
40   add_element_priority (el_l, p);
41 }
42
43 void
44 Align_element::add_element_priority (Score_element *el, int p)
45 {
46   assert (! contains_b (el));
47   elem_l_arr_.push (el);
48   priority_i_arr_.push (p);
49   add_dependency (el);
50 }
51
52 void
53 Align_element::do_substitute_element_pointer (Score_element*o,
54                                               Score_element*n)
55 {
56   int i;
57   while ((i = elem_l_arr_.find_i (o))>=0) 
58     if (n) 
59       elem_l_arr_[i] = n;
60     else
61       elem_l_arr_.del (i);
62
63   if (o == center_l_)
64     {
65       center_l_ = n;
66     }
67 }
68
69 void
70 Align_element::do_post_processing()
71 {
72   if (axis_ == Y_AXIS)
73     do_side_processing ();
74 }
75
76 void
77 Align_element::do_pre_processing ()
78 {
79   if (axis_ == X_AXIS)
80     do_side_processing ();
81 }
82
83 void
84 Align_element::do_side_processing ()
85 {
86   sort_elements ();
87   Array<Interval> dims;
88   
89   for (int i=0; i < elem_l_arr_.size(); i++) 
90     {
91       Interval y = elem_l_arr_[i]->extent(axis_) ;
92       if (y.empty_b())
93         y = Interval (0,0);
94         
95       dims.push (y);
96     }
97
98   Real where_f=0;
99   Real center_f = 0.0;
100   for (int i=0 ;  i < elem_l_arr_.size(); i++) 
101     {
102       Real dy = - stacking_dir_ * dims[i][-stacking_dir_];
103       if (i)
104         dy += stacking_dir_ * dims[i-1][stacking_dir_];
105
106       if (i)
107         {
108           dy = (dy >? threshold_interval_[SMALLER] )
109             <? threshold_interval_[BIGGER];
110         }
111
112       
113       if (!i && align_dir_ == LEFT)
114         center_f = where_f;
115       else if (align_dir_ == CENTER && elem_l_arr_[i] == center_l_)
116         center_f = where_f;
117
118       where_f += stacking_dir_ * dy;
119       elem_l_arr_[i]->translate_axis (where_f, axis_);
120     }
121
122   if (align_dir_ == RIGHT)
123     center_f = where_f;
124   
125   if (center_f)
126     for  (int i=0 ;  i < elem_l_arr_.size(); i++)
127       elem_l_arr_[i]->translate_axis (- center_f, axis_);
128 }
129
130 Align_element::Align_element()
131 {
132   threshold_interval_ = Interval (0, Interval::infinity ());
133   set_elt_property (transparent_scm_sym, SCM_BOOL_T);
134   set_empty (true);
135   stacking_dir_ = DOWN;
136   align_dir_ = LEFT;
137   axis_ = X_AXIS;
138   center_l_ =0;
139 }
140
141
142 bool
143 Align_element::contains_b (Score_element const *e) const
144 {
145   return elem_l_arr_.find_l (e);
146 }
147
148 void
149 Align_element::sort_elements ()
150 {
151   Array<Align_element_content> content;
152   for  (int i =0; i < elem_l_arr_.size(); i++) 
153     content.push (Align_element_content (elem_l_arr_[i], priority_i_arr_[i]));
154   content.sort (Align_element_content::compare);
155   
156   elem_l_arr_.clear();
157   priority_i_arr_.clear();
158
159   for  (int i =0; i < content.size(); i++) 
160     {
161       elem_l_arr_.push (content[i].elem_l_);
162       priority_i_arr_.push (content[i].priority_i_);
163     }
164 }
165
166 void
167 Align_element::do_print () const
168 {
169 #ifndef NPRINT
170   DOUT << "contains: ";
171   for (int i=0 ;  i < elem_l_arr_.size(); i++) 
172     DOUT << classname (elem_l_arr_[i]) << ", ";
173 #endif
174 }
175
176 Score_element*
177 Align_element::get_elt_by_priority (int p) const
178 {
179   for (int i=0; i < priority_i_arr_.size (); i++)
180     {
181       if (priority_i_arr_[i] == p)
182         return elem_l_arr_[i];
183     }
184   return 0;
185 }