]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
release: 1.1.31
[lilypond.git] / lily / item.cc
1 /*
2   item.cc -- implement Item
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 "p-score.hh"
10 #include "debug.hh"
11 #include "item.hh"
12 #include "p-col.hh"
13 #include "spanner.hh"
14
15 Item::Item ()
16 {
17   unbroken_original_l_ =0;
18   break_priority_i_ = 0;
19   breakable_b_ = false;
20   break_status_dir_ = CENTER;
21   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
22 }
23
24 bool
25 Item::breakable_b () const
26 {
27   return !unbroken_original_l_ 
28     && dynamic_cast<Item*>(parent_l (X_AXIS))->breakable_b ();
29 }
30
31 void
32 Item::do_print() const
33 {
34 #ifndef NPRINT
35   DOUT << "breakable_b_: " << breakable_b_ << 
36     " break_status_dir_: " << break_status_dir_;
37 #endif
38 }
39
40
41 Real 
42 Item::hpos_f() const
43 {
44   return absolute_coordinate (X_AXIS);
45 }
46
47 Line_of_score *
48 Item::line_l() const
49 {
50   Graphical_element *g = parent_l (X_AXIS);
51   if (!g)
52     return 0;
53   return dynamic_cast<Score_element *> (g)-> line_l ();
54 }
55
56 Direction
57 Item::break_status_dir() const
58 {
59   return break_status_dir_;
60 }
61
62 void
63 Item::copy_breakable_items()
64 {
65   if (broken_to_drul_[LEFT] || broken_to_drul_[RIGHT] 
66       || ! breakable_b ())
67     return;
68
69   Drul_array<Item *> new_copies;
70   Direction  i=LEFT;
71   do 
72     {
73       Score_element * dolly = clone();
74       Item * item_p = dynamic_cast<Item*>(dolly);
75
76       item_p->break_status_dir_ =  i;
77       pscore_l_->typeset_element (item_p);
78       new_copies[i] =item_p;
79     }
80   while (flip(&i) != LEFT);
81   broken_to_drul_= new_copies;
82
83   do 
84     {
85        broken_to_drul_[i]->handle_prebroken_dependencies();
86        broken_to_drul_[i]->try_visibility_lambda();
87     }
88   while (flip(&i) != LEFT);
89   try_visibility_lambda ();
90 }
91
92 void
93 Item::try_visibility_lambda ()
94 {
95   if (visibility_lambda_)
96     {
97       SCM args = scm_listify (gh_int2scm (break_status_dir_), SCM_UNDEFINED);
98       SCM result = gh_apply (visibility_lambda_, args);
99       int trans = gh_scm2bool (gh_car (result));
100       int empty = gh_scm2bool (gh_cdr (result));
101
102       if (empty)
103         set_empty (true);
104       if (trans)
105         transparent_b_ = true;
106     }
107 }
108
109 void
110 Item::do_break ()
111 {
112   copy_breakable_items();
113   handle_prebroken_dependencies();
114   
115   /*
116     Otherwise the broken items won't be pre_process()'ed.
117   */
118   add_dependency (broken_to_drul_[LEFT]);
119   add_dependency (broken_to_drul_[RIGHT]);
120 }
121
122 void
123 Item::do_breakable_col_processing()
124 {
125   if (breakable_b ())
126     do_break ();
127
128 }
129 Item*
130 Item::find_prebroken_piece (Line_of_score*l) const
131 {
132   if (line_l() == l) 
133     return (Item*)(this);
134   else if (broken_to_drul_[LEFT] && broken_to_drul_[LEFT]->line_l() == l)
135     return broken_to_drul_[LEFT];
136   else if (broken_to_drul_[RIGHT] && broken_to_drul_[RIGHT]->line_l() == l)
137     return broken_to_drul_[RIGHT];
138
139   return 0;
140 }
141
142 Item*
143 Item::find_prebroken_piece (Direction breakstatus) const
144 {
145   if (!breakstatus)
146     return (Item *) (this);     // ugh
147   else
148     return dynamic_cast<Item*> (broken_to_drul_[breakstatus]);
149 }
150
151 void
152 Item::handle_prebroken_dependencies()
153 {
154   if (breakable_b_)
155     Score_element::handle_prebroken_dependencies();
156 }
157
158 int
159 Item::left_right_compare(Item const *l, Item const *r)
160 {
161   Paper_column *p1 = l->column_l ();
162   Paper_column* p2 = r->column_l ();
163   return p1->rank_i () - p2->rank_i ();
164 }
165
166
167 bool
168 Item::linked_b() const
169 {
170   return Score_element::linked_b() || attached_span_l_arr_.size();
171 }
172
173 void
174 Item::do_junk_links()
175 {
176   attached_span_l_arr_.set_size(0);
177 }
178
179 void
180 Item::do_unlink()
181 {
182   Link_array<Spanner> attached=attached_span_l_arr_;
183   for (int i=0; i < attached.size (); i++)
184     {
185       Spanner *s= attached[i];
186
187       Direction d= LEFT;
188       do {
189         if (s->spanned_drul_[d] == this)
190           s->set_bounds (d, 0);
191         if (unbroken_original_l_
192             && unbroken_original_l_-> broken_to_drul_[d] == this)
193           unbroken_original_l_->broken_to_drul_[d] = 0;
194       } while (flip (&d) != LEFT);
195     }
196   assert (!attached_span_l_arr_.size ());
197   unbroken_original_l_ =0;
198 }
199
200 Paper_column *
201 Item::column_l () const
202 {
203   return dynamic_cast<Item*> (parent_l (X_AXIS))->column_l ();
204 }
205
206 Item::Item (Item const &s)
207   : Score_element (s)
208 {
209   unbroken_original_l_ = &s;
210   /* do not copy attached_span_l_arr_ */
211   breakable_b_ = s.breakable_b_;
212   visibility_lambda_ = s.visibility_lambda_;
213   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
214   break_status_dir_ = s.break_status_dir_;
215   break_priority_i_ = s.break_priority_i_;
216 }
217
218
219 void
220 Item::handle_prebroken_dependents ()
221 {
222   Item * parent =  dynamic_cast<Item*> (parent_l( X_AXIS));
223   if (breakable_b () && parent)
224     {
225        if(!(broken_to_drul_[LEFT] || broken_to_drul_[RIGHT]))
226         do_break ();
227
228       Direction d = LEFT;
229       do
230         {
231           broken_to_drul_[d]->dim_cache_[X_AXIS].parent_l_ =
232             &parent->broken_to_drul_[d]->dim_cache_[X_AXIS];
233           parent->broken_to_drul_[d]->add_dependency (broken_to_drul_[d]);
234         }
235       while ((flip (&d))!=LEFT);
236     }
237 }
238