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