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