]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
cleanup. Separate into internal
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "paper-score.hh"
10 #include "warn.hh"
11 #include "item.hh"
12 #include "paper-column.hh"
13 #include "spanner.hh"
14 #include "lily-guile.hh"
15 #include "system.hh"
16 #include "group-interface.hh"
17
18 Item::Item (SCM s)
19   : Grob (s)
20 {
21   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT]=0;
22   Group_interface::add_thing (this, ly_symbol2scm ("interfaces"), ly_symbol2scm ("item-interface"));
23 }
24
25 /**
26    Item copy ctor.  Copy nothing: everything should be a elt property
27    or a special purpose pointer (such as broken_to_drul_[]) */
28 Item::Item (Item const &s)
29   : Grob (s)
30 {
31   broken_to_drul_[LEFT] = broken_to_drul_[RIGHT] =0;
32 }
33
34
35 bool
36 Item::breakable_b (Grob*me) 
37 {
38   if (me->original_)
39     return false;
40
41   if (!dynamic_cast<Item*> (me))
42     me->programming_error ("only items can be breakable.");
43   
44   Item * i  =dynamic_cast<Item*> (me->get_parent (X_AXIS));
45   return (i) ?  Item::breakable_b (i) : to_boolean (me->get_grob_property ("breakable"));
46 }
47
48 Paper_column *
49 Item::get_column () const
50 {
51   Item *parent = dynamic_cast<Item*> (get_parent (X_AXIS));
52   return parent ? parent->get_column () : 0;
53 }
54
55 System *
56 Item::get_system () const
57 {
58   Grob *g = get_parent (X_AXIS);
59   return g ?  g->get_system () : 0;
60 }
61
62
63 void
64 Item::copy_breakable_items ()
65 {
66   Drul_array<Item *> new_copies;
67   Direction  i=LEFT;
68   do 
69     {
70       Grob * dolly = clone ();
71       Item * item = dynamic_cast<Item*> (dolly);
72       pscore_->system_->typeset_grob (item);
73       new_copies[i] =item;
74     }
75   while (flip (&i) != LEFT);
76   broken_to_drul_= new_copies;
77 }
78
79
80 bool
81 Item::broken_b () const
82 {
83   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
84 }
85
86
87 /*
88   Generate items for begin and end-of line.
89  */
90 void
91 Item::discretionary_processing ()
92 {
93   if (broken_b ())
94     return;
95
96   if (Item::breakable_b (this))
97     copy_breakable_items ();
98 }
99
100 Grob*
101 Item::find_broken_piece (System*l) const
102 {
103   if (get_system () == l) 
104     return (Item*) (this);
105
106   Direction d = LEFT;
107   do {
108     Grob *s = broken_to_drul_[d];
109     if (s && s->get_system () == l)
110       return s;
111   }
112   while (flip (&d) != LEFT);
113
114   return 0;
115 }
116
117
118 Item*
119 Item::find_prebroken_piece (Direction d) const
120 {
121   Item * me = (Item *) (this);  
122   if (!d)
123     return me;
124   return dynamic_cast<Item*> (broken_to_drul_[d]);
125 }
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     TODO:
151
152     give the item to break-visibility itself, so the function can do
153     more complicated things.
154   */
155   SCM vis = get_grob_property ("break-visibility");
156   if (gh_procedure_p (vis))
157     {
158       SCM args = scm_list_n (gh_int2scm (break_status_dir ()), SCM_UNDEFINED);
159       SCM result = gh_apply (vis, args);
160       bool trans = gh_scm2bool (ly_car (result));
161       bool empty = gh_scm2bool (ly_cdr (result));
162       
163       if (empty && trans)
164         suicide ();
165       else if (empty)
166         {
167           set_extent (SCM_EOL, X_AXIS);
168           set_extent (SCM_EOL, Y_AXIS);
169         }
170       else if (trans)
171         set_grob_property ("print-function", SCM_EOL);
172     }
173 }
174
175 SCM
176 Item::do_derived_mark ()const
177 {
178   if (broken_to_drul_[LEFT])
179     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
180   if (broken_to_drul_[RIGHT])
181     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
182   return SCM_EOL;
183 }
184
185 Item*
186 unsmob_item (SCM s )
187 {
188   return dynamic_cast<Item*> (unsmob_grob (s));
189 }
190
191
192
193 ADD_INTERFACE(Item,
194               "item-interface",
195               "\n"
196               "\n"
197               "Grobs can be distinguished in their role in the horizontal spacing.\n"
198               "Many grobs define constraints on the spacing by their sizes. For\n"
199               "example, note heads, clefs, stems, and all other symbols with a fixed\n"
200               "shape.  These grobs form a subtype called @code{Item}.\n"
201               "\n"
202               "\n"
203               "Some items need special treatment for line breaking. For example, a\n"
204               "clef is normally only printed at the start of a line (i.e. after a\n"
205               "line break).  To model this, `breakable' items (clef, key signature,\n"
206               "bar lines, etc.) are copied twice. Then we have three versions of each\n"
207               "breakable item: one version if there is no line break, one version\n"
208               "that is printed before the line break (at the end of a system), one\n"
209               "version that is printed after the line break.\n"
210               "\n"
211               "Whether these versions are visible and take up space, is determined by\n"
212               "the outcome of the @code{break-visibility}. This grob property is a\n"
213               "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
214               "cons of booleans, signifying whether this grob should be transparent\n"
215               "and have no extent.\n"
216               "\n"
217               "The following variables for break-visibility are predefined:\n"
218               "@example\n"
219               "           grob will show:   before  no     after\n"
220               "                             break   break  break\n"
221               "  all-invisible              no      no     no\n"
222               "  begin-of-line-visible      no      no     yes\n"
223               "  end-of-line-visible        yes     no     no\n"
224               "  all-visible                yes     yes    yes\n"
225               "  begin-of-line-invisible    yes     yes    no\n"
226               "  end-of-line-invisible      no      yes    yes\n"
227               "@end example\n"
228               ,
229               "no-spacing-rods break-visibility breakable")