]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
release: 1.5.29
[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--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9
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 #include "line-of-score.hh"
17
18 Item::Item (SCM s)
19   : Grob (s)
20 {
21   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
22 }
23
24 /**
25    Item copy ctor.  Copy nothing: everything should be a elt property
26    or a special purpose pointer (such as broken_to_drul_[]) */
27 Item::Item (Item const &s)
28   : Grob (s)
29 {
30   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
31 }
32
33
34 bool
35 Item::breakable_b (Grob*me) 
36 {
37   if (me->original_l_)
38     return false;
39
40   if (!dynamic_cast<Item*> (me))
41     programming_error ("only items can be breakable.");
42   
43   Item * i  =dynamic_cast<Item*> (me->get_parent (X_AXIS));
44   return (i) ?  Item::breakable_b (i) : to_boolean (me->get_grob_property ("breakable"));
45 }
46
47 Paper_column *
48 Item::column_l () const
49 {
50   Item *parent = dynamic_cast<Item*> (get_parent (X_AXIS));
51   return parent ? parent->column_l () : 0;
52 }
53
54 Line_of_score *
55 Item::line_l () const
56 {
57   Grob *g = get_parent (X_AXIS);
58   return g ?  g->line_l () : 0;
59 }
60
61
62 void
63 Item::copy_breakable_items ()
64 {
65   Drul_array<Item *> new_copies;
66   Direction  i=LEFT;
67   do 
68     {
69       Grob * dolly = clone ();
70       Item * item_p = dynamic_cast<Item*> (dolly);
71       pscore_l_->line_l_->typeset_grob (item_p);
72       new_copies[i] =item_p;
73     }
74   while (flip (&i) != LEFT);
75   broken_to_drul_= new_copies;
76 }
77
78
79 bool
80 Item::broken_b () const
81 {
82   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
83 }
84
85
86 /*
87   Generate items for begin and end-of line.
88  */
89 void
90 Item::discretionary_processing ()
91 {
92   if (broken_b ())
93     return;
94
95   if (Item::breakable_b (this))
96     copy_breakable_items ();
97 }
98
99 Grob*
100 Item::find_broken_piece (Line_of_score*l) const
101 {
102   if (line_l () == l) 
103     return (Item*) (this);
104
105   Direction d = LEFT;
106   do {
107     Grob *s = broken_to_drul_[d];
108     if (s && s->line_l () == l)
109       return s;
110   }
111   while (flip (&d) != LEFT);
112
113   return 0;
114 }
115
116
117 Item*
118 Item::find_prebroken_piece (Direction d) const
119 {
120   Item * me = (Item *) (this);  
121   if (!d)
122     return me;
123   return dynamic_cast<Item*> (broken_to_drul_[d]);
124 }
125
126
127 Direction
128 Item::break_status_dir () const
129 {
130   if (original_l_)
131     {
132       Item * i = dynamic_cast<Item*> (original_l_);
133
134       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
135     }
136   else
137     return CENTER;
138 }
139
140 void
141 Item::handle_prebroken_dependencies ()
142 {
143   if (original_l_)
144     {
145       mutable_property_alist_
146         = handle_broken_grobs(original_l_->mutable_property_alist_,
147                                gh_int2scm (break_status_dir ()));
148     }
149   
150   /*
151     Can't do this earlier, because try_visibility_lambda () might set
152     the elt property transparent, which would then be copied.
153
154     TODO:
155
156     handle visibility-lambda the item itself iso. breakstatusdir, so
157     the function can do more complicated things.
158     
159   */
160   SCM vis = get_grob_property ("visibility-lambda");
161   if (gh_procedure_p (vis))
162     {
163       SCM args = scm_list_n (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
164       SCM result = gh_apply (vis, args);
165       bool trans = gh_scm2bool (ly_car (result));
166       bool empty = gh_scm2bool (ly_cdr (result));
167       
168       if (empty && trans)
169         suicide ();
170       else if (empty)
171         {
172           set_extent_callback (SCM_EOL, X_AXIS);
173           set_extent_callback (SCM_EOL, Y_AXIS);
174         }
175       else if (trans)
176         set_grob_property ("molecule-callback", SCM_BOOL_T);
177     }
178 }
179
180 SCM
181 Item::do_derived_mark ()
182 {
183   if (broken_to_drul_[LEFT])
184     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
185   if (broken_to_drul_[RIGHT])
186     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
187   return SCM_EOL;
188 }
189
190 Item*
191 unsmob_item (SCM s )
192 {
193   return dynamic_cast<Item*> (unsmob_grob (s));
194 }