]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
* lily/context.cc (Context): take key argument in ctor.
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "paper-score.hh"
10 #include "warn.hh"
11 #include "item.hh"
12 #include "paper-column.hh"
13 #include "spanner.hh"
14 #include "lily-guile.hh"
15 #include "system.hh"
16 #include "group-interface.hh"
17
18
19 Grob * 
20 Item::clone (int count) const
21 {
22   return new Item (*this, count);
23 }
24
25
26 Item::Item (SCM s, Object_key const *key)
27   : Grob (s, key)
28 {
29   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
30   Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("item-interface"));
31 }
32
33 /**
34    Item copy ctor.  Copy nothing: everything should be a elt property
35    or a special purpose pointer (such as broken_to_drul_[]) */
36 Item::Item (Item const &s, int copy_count)
37   : Grob (s, copy_count)
38 {
39   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
40 }
41
42
43 bool
44 Item::is_breakable (Grob*me) 
45 {
46   if (me->original_)
47     return false;
48
49   if (!dynamic_cast<Item*> (me))
50     me->programming_error ("only items can be breakable.");
51   
52   Item * i = dynamic_cast<Item*> (me->get_parent (X_AXIS));
53   return (i) ? Item::is_breakable (i) : to_boolean (me->get_property ("breakable"));
54 }
55
56 Paper_column *
57 Item::get_column () const
58 {
59   Item *parent = dynamic_cast<Item*> (get_parent (X_AXIS));
60   return parent ? parent->get_column () : 0;
61 }
62
63 System *
64 Item::get_system () const
65 {
66   Grob *g = get_parent (X_AXIS);
67   return g ?  g->get_system () : 0;
68 }
69
70
71 void
72 Item::copy_breakable_items ()
73 {
74   Drul_array<Item *> new_copies;
75   Direction i = LEFT;
76   int count = 0;
77   do 
78     {
79       Grob * dolly = clone (count ++);
80       Item * item = dynamic_cast<Item*> (dolly);
81       pscore_->system_->typeset_grob (item);
82       new_copies[i] =item;
83     }
84   while (flip (&i) != LEFT);
85   broken_to_drul_= new_copies;
86 }
87
88
89 bool
90 Item::is_broken () const
91 {
92   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
93 }
94
95
96 /*
97   Generate items for begin and end-of line.
98  */
99 void
100 Item::discretionary_processing ()
101 {
102   if (is_broken ())
103     return;
104
105   if (Item::is_breakable (this))
106     copy_breakable_items ();
107 }
108
109 Grob*
110 Item::find_broken_piece (System*l) const
111 {
112   if (get_system () == l) 
113     return (Item*) (this);
114
115   Direction d = LEFT;
116   do {
117     Grob *s = broken_to_drul_[d];
118     if (s && s->get_system () == l)
119       return s;
120   }
121   while (flip (&d) != LEFT);
122
123   return 0;
124 }
125
126
127 Item*
128 Item::find_prebroken_piece (Direction d) const
129 {
130   Item * me = (Item *) (this);  
131   if (!d)
132     return me;
133   return dynamic_cast<Item*> (broken_to_drul_[d]);
134 }
135
136
137 Direction
138 Item::break_status_dir () const
139 {
140   if (original_)
141     {
142       Item * i = dynamic_cast<Item*> (original_);
143
144       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
145     }
146   else
147     return CENTER;
148 }
149
150 void
151 Item::handle_prebroken_dependencies ()
152 {
153   Grob::handle_prebroken_dependencies ();
154   
155   /*
156     Can't do this earlier, because try_visibility_lambda () might set
157     the elt property transparent, which would then be copied.
158
159     TODO:
160
161     give the item to break-visibility itself, so the function can do
162     more complicated things.
163   */
164   SCM vis = get_property ("break-visibility");
165   if (ly_c_procedure_p (vis))
166     {
167       SCM args = scm_list_n (scm_int2num (break_status_dir ()), SCM_UNDEFINED);
168       SCM result = scm_apply_0 (vis, args);
169       bool trans = ly_scm2bool (scm_car (result));
170       bool empty = ly_scm2bool (scm_cdr (result));
171       
172       if (empty && trans)
173         suicide ();
174       else if (empty)
175         {
176           set_extent (SCM_EOL, X_AXIS);
177           set_extent (SCM_EOL, Y_AXIS);
178         }
179       else if (trans)
180         set_property ("print-function", SCM_EOL);
181     }
182 }
183
184 SCM
185 Item::do_derived_mark ()const
186 {
187   if (broken_to_drul_[LEFT])
188     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
189   if (broken_to_drul_[RIGHT])
190     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
191   return SCM_EOL;
192 }
193
194 Item*
195 unsmob_item (SCM s )
196 {
197   return dynamic_cast<Item*> (unsmob_grob (s));
198 }
199
200
201
202 ADD_INTERFACE (Item,
203               "item-interface",
204               "\n"
205               "\n"
206               "Grobs can be distinguished in their role in the horizontal spacing.\n"
207               "Many grobs define constraints on the spacing by their sizes. For\n"
208               "example, note heads, clefs, stems, and all other symbols with a fixed\n"
209               "shape.  These grobs form a subtype called @code{Item}.\n"
210               "\n"
211               "\n"
212               "Some items need special treatment for line breaking. For example, a\n"
213               "clef is normally only printed at the start of a line (i.e. after a\n"
214               "line break).  To model this, `breakable' items (clef, key signature,\n"
215               "bar lines, etc.) are copied twice. Then we have three versions of each\n"
216               "breakable item: one version if there is no line break, one version\n"
217               "that is printed before the line break (at the end of a system), one\n"
218               "version that is printed after the line break.\n"
219               "\n"
220               "Whether these versions are visible and take up space, is determined by\n"
221               "the outcome of the @code{break-visibility}. This grob property is a\n"
222               "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
223               "cons of booleans, signifying whether this grob should be transparent\n"
224               "and have no extent.\n"
225               "\n"
226               "The following variables for break-visibility are predefined:\n"
227               "@example\n"
228               "           grob will show:   before  no     after\n"
229               "                             break   break  break\n"
230               "  all-invisible              no      no     no\n"
231               "  begin-of-line-visible      no      no     yes\n"
232               "  end-of-line-visible        yes     no     no\n"
233               "  all-visible                yes     yes    yes\n"
234               "  begin-of-line-invisible    yes     yes    no\n"
235               "  end-of-line-invisible      no      yes    yes\n"
236               "@end example\n"
237               ,
238               "no-spacing-rods break-visibility breakable")