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