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