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