]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond into jneeman
[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--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "item.hh"
10
11 #include "axis-group-interface.hh"
12 #include "paper-score.hh"
13 #include "warn.hh"
14 #include "paper-column.hh"
15 #include "lily-guile.hh"
16 #include "system.hh"
17 #include "pointer-group-interface.hh"
18
19 #include "moment.hh"
20
21
22 Grob *
23 Item::clone () const
24 {
25   return new Item (*this);
26 }
27
28 Item::Item (SCM s)
29   : Grob (s)
30 {
31   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
32 }
33
34 /**
35    Item copy ctor.  Copy nothing: everything should be a elt property
36    or a special purpose pointer (such as broken_to_drul_[]) */
37 Item::Item (Item const &s)
38   : Grob (s)
39 {
40   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
41 }
42
43 bool
44 Item::is_non_musical (Grob *me)
45 {
46   if (me->original ())
47     return false;
48
49   Item *i = dynamic_cast<Item *> (me->get_parent (X_AXIS));
50   return i ? Item::is_non_musical (i) : to_boolean (me->get_property ("non-musical"));
51 }
52
53 Paper_column *
54 Item::get_column () const
55 {
56   Item *parent = dynamic_cast<Item *> (get_parent (X_AXIS));
57   return parent ? parent->get_column () : 0;
58 }
59
60 System *
61 Item::get_system () const
62 {
63   Grob *g = get_parent (X_AXIS);
64   return g ? g->get_system () : 0;
65 }
66
67 void
68 Item::copy_breakable_items ()
69 {
70   Drul_array<Item *> new_copies;
71   Direction i = LEFT;
72   do
73     {
74       Grob *dolly = clone ();
75       Item *item = dynamic_cast<Item *> (dolly);
76       get_root_system (this)->typeset_grob (item);
77       new_copies[i] = item;
78     }
79   while (flip (&i) != LEFT);
80
81   broken_to_drul_ = new_copies;
82 }
83
84 bool
85 Item::is_broken () const
86 {
87   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
88 }
89
90 /*
91   Generate items for begin and end-of line.
92 */
93 void
94 Item::discretionary_processing ()
95 {
96   if (is_broken ())
97     return;
98
99   if (Item::is_non_musical (this))
100     copy_breakable_items ();
101 }
102
103 Grob *
104 Item::find_broken_piece (System *l) const
105 {
106   if (get_system () == l)
107     return (Item *) (this);
108
109   Direction d = LEFT;
110   do
111     {
112       Grob *s = broken_to_drul_[d];
113       if (s && s->get_system () == l)
114         return s;
115     }
116   while (flip (&d) != LEFT);
117
118   return 0;
119 }
120
121 Item *
122 Item::find_prebroken_piece (Direction d) const
123 {
124   Item *me = (Item *) (this);
125   if (!d)
126     return me;
127   return dynamic_cast<Item *> (broken_to_drul_[d]);
128 }
129
130 Direction
131 Item::break_status_dir () const
132 {
133   if (original ())
134     {
135       Item *i = dynamic_cast<Item *> (original ());
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   Grob::handle_prebroken_dependencies ();
147
148   /*
149     Can't do this earlier, because try_visibility_lambda () might set
150     the elt property transparent, which would then be copied.
151   */
152   SCM vis = get_property ("break-visibility");
153   if (scm_is_vector (vis))
154     {
155       bool visible = to_boolean (scm_c_vector_ref (vis, break_status_dir () + 1));
156
157       if (!visible)
158         suicide ();
159     }
160 }
161
162 bool
163 Item::pure_is_visible (int start, int end) const
164 {
165   SCM vis = get_property ("break-visibility");
166   if (scm_is_vector (vis))
167     {
168       int pos = 1;
169       int pc_rank = Paper_column::get_rank (get_column ());
170       if (pc_rank == start)
171         pos = 2;
172       else if (pc_rank == end)
173         pos = 0;
174       return to_boolean (scm_vector_ref (vis, scm_from_int (pos)));
175     }
176   return true;
177 }
178
179 Interval_t<int>
180 Item::spanned_rank_interval () const
181 {
182   int c = get_column ()->get_rank ();
183   return Interval_t<int> (c, c);
184 }
185
186 Interval_t<Moment>
187 spanned_time_interval (Item *l, Item *r) 
188 {
189   Drul_array<Item*> bounds (l, r);
190   Interval_t<Moment> iv;
191
192   Direction d = LEFT;
193   do
194     {
195       if (bounds[d] && bounds[d]->get_column ())
196         iv[d] = robust_scm2moment (bounds[d]->get_column ()->get_property ("when"),
197                                   iv[d]);
198     }
199   while (flip (&d) != LEFT);
200
201   do
202     {
203       if (!bounds[d] || !bounds[d]->get_column ())
204         iv[d] = iv[-d];
205     }
206   while (flip (&d) != LEFT);
207   
208   
209   return iv;
210 }
211
212
213 void
214 Item::derived_mark () const
215 {
216   if (broken_to_drul_[LEFT])
217     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
218   if (broken_to_drul_[RIGHT])
219     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
220 }
221
222 Item *
223 unsmob_item (SCM s)
224 {
225   return dynamic_cast<Item *> (unsmob_grob (s));
226 }
227
228 ADD_INTERFACE (Item,
229
230                "Grobs can be distinguished in their role in the horizontal spacing.\n"
231                "Many grobs define constraints on the spacing by their sizes. For\n"
232                "example, note heads, clefs, stems, and all other symbols with a fixed\n"
233                "shape.  These grobs form a subtype called @code{Item}.\n"
234                "\n"
235                "\n"
236                "Some items need special treatment for line breaking. For example, a\n"
237                "clef is normally only printed at the start of a line (i.e. after a\n"
238                "line break).  To model this, `breakable' items (clef, key signature,\n"
239                "bar lines, etc.) are copied twice. Then we have three versions of each\n"
240                "breakable item: one version if there is no line break, one version\n"
241                "that is printed before the line break (at the end of a system), one\n"
242                "version that is printed after the line break.\n"
243                "\n"
244                "Whether these versions are visible and take up space, is determined by\n"
245                "the outcome of the @code{break-visibility}. This grob property is a\n"
246                "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
247                "cons of booleans, signifying whether this grob should be transparent\n"
248                "and have no extent.\n"
249                "\n"
250                "The following variables for break-visibility are predefined:\n"
251                "@example\n"
252                "           grob will show:   before  no     after\n"
253                "                             break   break  break\n"
254                "  all-invisible              no      no     no\n"
255                "  begin-of-line-visible      no      no     yes\n"
256                "  end-of-line-visible        yes     no     no\n"
257                "  all-visible                yes     yes    yes\n"
258                "  begin-of-line-invisible    yes     yes    no\n"
259                "  end-of-line-invisible      no      yes    yes\n"
260                "  center-invisible           yes      no    yes\n"
261                "@end example\n",
262
263                /* properties */
264                "break-visibility "
265                "extra-spacing-width "
266                "infinite-spacing-height "
267                "non-musical")