]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
32882aac71303f656978bb72eeee7863529304d2
[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--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "item.hh"
10
11 #include "paper-score.hh"
12 #include "warn.hh"
13 #include "paper-column.hh"
14 #include "lily-guile.hh"
15 #include "system.hh"
16 #include "pointer-group-interface.hh"
17
18 Grob *
19 Item::clone (int count) const
20 {
21   return new Item (*this, count);
22 }
23
24 Item::Item (SCM s, Object_key const *key)
25   : Grob (s, key)
26 {
27   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
28 }
29
30 /**
31    Item copy ctor.  Copy nothing: everything should be a elt property
32    or a special purpose pointer (such as broken_to_drul_[]) */
33 Item::Item (Item const &s, int copy_count)
34   : Grob (s, copy_count)
35 {
36   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] = 0;
37 }
38
39 bool
40 Item::is_breakable (Grob *me)
41 {
42   if (me->original ())
43     return false;
44
45   if (!dynamic_cast<Item *> (me))
46     me->programming_error ("only items can be breakable.");
47
48   Item *i = dynamic_cast<Item *> (me->get_parent (X_AXIS));
49   return (i) ? Item::is_breakable (i) : to_boolean (me->get_property ("breakable"));
50 }
51
52 Paper_column *
53 Item::get_column () const
54 {
55   Item *parent = dynamic_cast<Item *> (get_parent (X_AXIS));
56   return parent ? parent->get_column () : 0;
57 }
58
59 System *
60 Item::get_system () const
61 {
62   Grob *g = get_parent (X_AXIS);
63   return g ? g->get_system () : 0;
64 }
65
66 void
67 Item::copy_breakable_items ()
68 {
69   Drul_array<Item *> new_copies;
70   Direction i = LEFT;
71   int count = 0;
72   do
73     {
74       Grob *dolly = clone (count++);
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_breakable (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_vector_ref (vis, scm_from_int (break_status_dir () + 1)));
156
157       if (!visible)
158         suicide ();
159     }
160 }
161
162 void
163 Item::derived_mark () const
164 {
165   if (broken_to_drul_[LEFT])
166     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
167   if (broken_to_drul_[RIGHT])
168     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
169 }
170
171 Item *
172 unsmob_item (SCM s)
173 {
174   return dynamic_cast<Item *> (unsmob_grob (s));
175 }
176
177 ADD_INTERFACE (Item,
178                "item-interface",
179                "\n"
180                "\n"
181                "Grobs can be distinguished in their role in the horizontal spacing.\n"
182                "Many grobs define constraints on the spacing by their sizes. For\n"
183                "example, note heads, clefs, stems, and all other symbols with a fixed\n"
184                "shape.  These grobs form a subtype called @code{Item}.\n"
185                "\n"
186                "\n"
187                "Some items need special treatment for line breaking. For example, a\n"
188                "clef is normally only printed at the start of a line (i.e. after a\n"
189                "line break).  To model this, `breakable' items (clef, key signature,\n"
190                "bar lines, etc.) are copied twice. Then we have three versions of each\n"
191                "breakable item: one version if there is no line break, one version\n"
192                "that is printed before the line break (at the end of a system), one\n"
193                "version that is printed after the line break.\n"
194                "\n"
195                "Whether these versions are visible and take up space, is determined by\n"
196                "the outcome of the @code{break-visibility}. This grob property is a\n"
197                "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
198                "cons of booleans, signifying whether this grob should be transparent\n"
199                "and have no extent.\n"
200                "\n"
201                "The following variables for break-visibility are predefined:\n"
202                "@example\n"
203                "           grob will show:   before  no     after\n"
204                "                             break   break  break\n"
205                "  all-invisible              no      no     no\n"
206                "  begin-of-line-visible      no      no     yes\n"
207                "  end-of-line-visible        yes     no     no\n"
208                "  all-visible                yes     yes    yes\n"
209                "  begin-of-line-invisible    yes     yes    no\n"
210                "  end-of-line-invisible      no      yes    yes\n"
211                "  center-invisible           yes      no    yes\n"
212                "@end example\n",
213                "no-spacing-rods break-visibility breakable")