]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
release: 1.1.58
[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 "paper-score.hh"
10 #include "debug.hh"
11 #include "item.hh"
12 #include "paper-column.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   else
118     try_visibility_lambda ();
119 }
120 Item*
121 Item::find_prebroken_piece (Line_of_score*l) const
122 {
123   if (line_l() == l) 
124     return (Item*)(this);
125   else if (broken_to_drul_[LEFT] && broken_to_drul_[LEFT]->line_l() == l)
126     return broken_to_drul_[LEFT];
127   else if (broken_to_drul_[RIGHT] && broken_to_drul_[RIGHT]->line_l() == l)
128     return broken_to_drul_[RIGHT];
129
130   return 0;
131 }
132
133 Item*
134 Item::find_prebroken_piece (Direction d) const
135 {
136   if (!d)
137     return (Item *) (this);     // ugh
138   else
139     return dynamic_cast<Item*> (broken_to_drul_[d]);
140 }
141
142 void
143 Item::handle_prebroken_dependencies()
144 {
145   if (original_l_)
146     Score_element::handle_prebroken_dependencies();
147 }
148
149 bool
150 Item::broken_original_b () const
151 {
152   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
153 }
154
155 int
156 Item::left_right_compare(Item const *l, Item const *r)
157 {
158   Paper_column *p1 = l->column_l ();
159   Paper_column* p2 = r->column_l ();
160   return p1->rank_i () - p2->rank_i ();
161 }
162
163 Paper_column *
164 Item::column_l () const
165 {
166   return dynamic_cast<Item*> (parent_l (X_AXIS))->column_l ();
167 }
168
169 Item::Item (Item const &s)
170   : Score_element (s)
171 {
172   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
173 }
174
175
176 void
177 Item::handle_prebroken_dependents ()
178 {
179   Item * parent =  dynamic_cast<Item*> (parent_l (X_AXIS));
180   if (breakable_b () && parent)
181     {
182        if(!(broken_to_drul_[LEFT] || broken_to_drul_[RIGHT]))
183         do_break ();
184
185       Direction d = LEFT;
186       do
187         {
188           Item * broken_self = find_prebroken_piece (d);
189           Item * broken_parent = parent->find_prebroken_piece (d);
190
191           broken_self->dim_cache_[X_AXIS]->parent_l_ =
192             broken_parent->dim_cache_[X_AXIS];
193
194           /*
195             ugh. Should do this is after breaking?
196            */
197           if (!broken_self->parent_l (Y_AXIS))
198             {
199               Score_element * yparent =dynamic_cast<Score_element*>(parent_l (Y_AXIS));
200               Item *yparenti = dynamic_cast<Item*> (yparent);
201               Item *broken_yparent = yparenti ?
202                 yparenti->find_prebroken_piece (d) : 0;
203               
204               if (!yparent)
205                 programming_error ("Vertical refpoint lost!");
206               else if (yparenti)
207                 {
208                   broken_self->dim_cache_[Y_AXIS]->parent_l_ =
209                     broken_yparent->dim_cache_[Y_AXIS];
210                 }
211             }
212         }
213       while ((flip (&d))!=LEFT);
214     }
215 }
216
217 Direction
218 Item::break_status_dir () const
219 {
220   if (original_l_)
221     {
222       Item * i = dynamic_cast<Item*> (original_l_);
223
224       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
225     }
226   else
227     return CENTER;
228 }