]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
release: 1.3.94
[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--2000 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   : Score_element (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   : Score_element (s)
29 {
30   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
31 }
32
33
34 bool
35 Item::breakable_b (Score_element*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->parent_l (X_AXIS));
44   return (i) ?  Item::breakable_b (i) : to_boolean (me->get_elt_property ("breakable"));
45 }
46
47 Paper_column *
48 Item::column_l () const
49 {
50   return dynamic_cast<Item*> (parent_l (X_AXIS))->column_l ();
51 }
52
53 Line_of_score *
54 Item::line_l() const
55 {
56   Score_element *g = parent_l (X_AXIS);
57   return g ?  g->line_l () : 0;
58 }
59
60
61 void
62 Item::copy_breakable_items()
63 {
64   Drul_array<Item *> new_copies;
65   Direction  i=LEFT;
66   do 
67     {
68       Score_element * dolly = clone();
69       Item * item_p = dynamic_cast<Item*>(dolly);
70       pscore_l_->line_l_->typeset_element (item_p);
71       new_copies[i] =item_p;
72     }
73   while (flip(&i) != LEFT);
74   broken_to_drul_= new_copies;
75 }
76
77
78 bool
79 Item::broken_b () const
80 {
81   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
82 }
83
84
85 /*
86   Generate items for begin and end-of line.
87  */
88 void
89 Item::discretionary_processing()
90 {
91   if (broken_b ())
92     return;
93
94   if (Item::breakable_b (this))
95     copy_breakable_items();
96 }
97
98 Score_element*
99 Item::find_broken_piece (Line_of_score*l) const
100 {
101   if (line_l() == l) 
102     return (Item*)(this);
103
104   Direction d = LEFT;
105   do {
106     Score_element *s = broken_to_drul_[d];
107     if (s && s->line_l () == l)
108       return s;
109   }
110   while (flip (&d) != LEFT);
111
112   return 0;
113 }
114
115
116 Item*
117 Item::find_prebroken_piece (Direction d) const
118 {
119   Item * me = (Item *) (this);  
120   if (!d)
121     return me;
122   return dynamic_cast<Item*> (broken_to_drul_[d]);
123 }
124
125
126 Direction
127 Item::break_status_dir () const
128 {
129   if (original_l_)
130     {
131       Item * i = dynamic_cast<Item*> (original_l_);
132
133       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
134     }
135   else
136     return CENTER;
137 }
138
139 void
140 Item::handle_prebroken_dependencies ()
141 {
142   if (original_l_)
143     {
144       mutable_property_alist_
145         = handle_broken_smobs (original_l_->mutable_property_alist_,
146                                gh_int2scm (break_status_dir ()));
147     }
148   
149   /*
150     Can't do this earlier, because try_visibility_lambda () might set
151     the elt property transparent, which would then be copied.
152
153     TODO:
154
155     handle visibility-lambda the item itself iso. breakstatusdir, so
156     the function can do more complicated things.
157     
158   */
159   SCM vis = get_elt_property ("visibility-lambda");
160   if (gh_procedure_p (vis))
161     {
162       SCM args = scm_listify (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
163       SCM result = gh_apply (vis, args);
164       bool trans = gh_scm2bool (gh_car (result));
165       bool empty = gh_scm2bool (gh_cdr (result));
166       
167       if (empty && trans)
168         suicide ();
169       else if (empty)
170         {
171           set_extent_callback (SCM_EOL, X_AXIS);
172           set_extent_callback (SCM_EOL, Y_AXIS);
173         }
174       else if (trans)
175         set_elt_property ("molecule-callback", SCM_BOOL_T);
176     }
177 }
178
179 SCM
180 Item::do_derived_mark ()
181 {
182   if (broken_to_drul_[LEFT])
183     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
184   if (broken_to_drul_[RIGHT])
185     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
186   return SCM_EOL;
187 }