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