]> git.donarmstrong.com Git - lilypond.git/blob - lily/spanner.cc
release: 1.3.14
[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--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "dimension-cache.hh"
10 #include "debug.hh"
11 #include "spanner.hh"
12 #include "paper-column.hh"
13 #include "paper-score.hh"
14 #include "molecule.hh"
15 #include "paper-outputter.hh"
16 #include "paper-column.hh"
17 #include "line-of-score.hh"
18 #include "break-align-item.hh"
19
20 void
21 Spanner::do_break_processing()
22 {
23   //break_into_pieces
24   
25   if (line_l () || broken_b ())
26     return;
27   
28   Item * left = spanned_drul_[LEFT];
29   Item * right = spanned_drul_[RIGHT];
30
31   if  (left == right)
32     {
33       warning (_ ("Left spanpoint is right spanpoint"));
34       return;
35     }
36   
37   Link_array<Item> break_points = pscore_l_->broken_col_range (left,right);
38
39   break_points.insert (left,0);
40   break_points.push (right);
41
42   for (int i=1; i < break_points.size(); i++) 
43     {
44       Drul_array<Item*> bounds;
45       bounds[LEFT] = break_points[i-1];
46       bounds[RIGHT] = break_points[i];
47       Direction d = LEFT;
48       do
49         {
50           Item *&pc_l = bounds[d] ;
51           if (!pc_l->line_l())
52             pc_l =  pc_l->find_broken_piece(- d);
53           
54           assert (pc_l);
55         }
56       while ((flip(&d))!= LEFT);
57
58       Spanner *span_p = dynamic_cast<Spanner*>(clone ());
59       span_p->set_bounds(LEFT,bounds[LEFT]);
60       span_p->set_bounds(RIGHT,bounds[RIGHT]);
61       
62       pscore_l_->typeset_element (span_p);
63       broken_into_l_arr_.push (span_p);
64     }
65
66   broken_into_l_arr_.sort (Spanner::compare);
67 }
68
69 void
70 Spanner::set_my_columns()
71 {
72   Direction i = (Direction) LEFT;
73   do 
74     {
75       if (!spanned_drul_[i]->line_l())
76         set_bounds(i,spanned_drul_[i]->find_broken_piece((Direction) -i));
77     } 
78   while (flip(&i) != LEFT);
79 }       
80
81 void
82 Spanner::set_bounds(Direction d, Item*i)
83 {
84   spanned_drul_[d] =i;
85   if (i)
86     {
87       i->used_b_ = true;
88     }
89
90   /**
91      Prevent the column -> line_of_score -> column -> line_of_score -> etc situation
92   */
93   if (d== LEFT && !dynamic_cast<Line_of_score*> (this))
94     {
95       set_parent (i, X_AXIS);
96     }
97   
98   if (spanned_drul_[Direction(-d)] == spanned_drul_[d]
99        && i)
100     warning (_f ("Spanner `%s' has equal left and right spanpoints", classname (this)));
101 }
102
103
104 Spanner::Spanner ()
105 {
106   spanned_drul_[LEFT]=0;
107   spanned_drul_[RIGHT]=0;
108 }
109
110 Spanner::Spanner (Spanner const &s)
111   : Score_element (s)
112 {
113   spanned_drul_[LEFT] = spanned_drul_[RIGHT] =0;
114 }
115
116
117 Real
118 Spanner::spanner_length() const
119 {  
120   Real l = spanned_drul_[LEFT]->relative_coordinate (0, X_AXIS);
121   Real r = spanned_drul_[RIGHT]->relative_coordinate (0, X_AXIS);
122
123   if (r< l)
124     programming_error ("spanner with negative length");
125
126   return r-l;
127 }
128
129 Line_of_score *
130 Spanner::line_l() const
131 {
132   if (!spanned_drul_[LEFT] || !spanned_drul_[RIGHT])
133     return 0;
134   if (spanned_drul_[LEFT]->line_l () != spanned_drul_[RIGHT]->line_l ())
135     return 0;
136   return spanned_drul_[LEFT]->line_l();
137 }
138
139
140 Score_element*
141 Spanner::find_broken_piece (Line_of_score*l) const
142 {
143   int idx = binsearch_link_array (broken_into_l_arr_,  (Spanner*)l, Spanner::compare);
144   
145   if (idx < 0)
146     return 0;
147   else
148     return broken_into_l_arr_ [idx];
149 }
150
151
152 int
153 Spanner::compare (Spanner * const &p1, Spanner * const &p2)
154 {
155   return p1->line_l ()->rank_i_ - p2->line_l ()->rank_i_;
156 }
157
158 bool
159 Spanner::broken_b() const
160 {
161   return broken_into_l_arr_.size();
162 }
163
164 Array<Rod>
165 Spanner::get_rods () const
166 {
167   Array<Rod> r;
168   return r;
169 }
170
171 Array<Spring>
172 Spanner::get_springs () const
173 {
174   Array<Spring> s;
175   return s;    
176 }
177
178 void
179 Spanner::do_space_processing ()
180 {
181   Array<Rod> rs (get_rods ());
182   for (int i=0; i < rs.size (); i++)
183     {
184       rs[i].add_to_cols ();
185     }
186
187   Array<Spring> ss (get_springs ());
188   for (int i=0; i < ss.size (); i++)
189     {
190       ss[i].add_to_cols ();
191     }
192 }
193
194 /*
195   If this is a broken spanner, return the amount the left end is to be
196   shifted horizontally so that the spanner starts after the initial
197   clef and key on the staves. This is necessary for ties, slurs,
198   crescendo and decrescendo signs, for example.
199 */
200 Real
201 Spanner::get_broken_left_end_align () const
202 {
203   Paper_column *sc = dynamic_cast<Paper_column*> (spanned_drul_[LEFT]->column_l());
204
205   // Relevant only if left span point is first column in line
206   if(sc != NULL &&
207      sc->break_status_dir () == RIGHT)
208     {
209       /*
210         
211         We used to do a full search for the Break_align_item.
212         But that doesn't make a difference, since the Paper_column
213         is likely to contain only a Break_align_item.
214       */
215       return sc->extent (X_AXIS)[RIGHT];
216     }
217
218   return 0.0;
219 }