]> git.donarmstrong.com Git - lilypond.git/blob - lily/item.cc
Fix some bugs in the dynamic engraver and PostScript backend
[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 "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_non_musical (Grob *me)
41 {
42   if (me->original ())
43     return false;
44
45   Item *i = dynamic_cast<Item *> (me->get_parent (X_AXIS));
46   return i ? Item::is_non_musical (i) : to_boolean (me->get_property ("non-musical"));
47 }
48
49 Paper_column *
50 Item::get_column () const
51 {
52   Item *parent = dynamic_cast<Item *> (get_parent (X_AXIS));
53   return parent ? parent->get_column () : 0;
54 }
55
56 System *
57 Item::get_system () const
58 {
59   Grob *g = get_parent (X_AXIS);
60   return g ? g->get_system () : 0;
61 }
62
63 void
64 Item::copy_breakable_items ()
65 {
66   Drul_array<Item *> new_copies;
67   Direction i = LEFT;
68   int count = 0;
69   do
70     {
71       Grob *dolly = clone (count++);
72       Item *item = dynamic_cast<Item *> (dolly);
73       get_root_system (this)->typeset_grob (item);
74       new_copies[i] = item;
75     }
76   while (flip (&i) != LEFT);
77
78   broken_to_drul_ = new_copies;
79 }
80
81 bool
82 Item::is_broken () const
83 {
84   return broken_to_drul_[LEFT] || broken_to_drul_[RIGHT];
85 }
86
87 /*
88   Generate items for begin and end-of line.
89 */
90 void
91 Item::discretionary_processing ()
92 {
93   if (is_broken ())
94     return;
95
96   if (Item::is_non_musical (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     {
109       Grob *s = broken_to_drul_[d];
110       if (s && s->get_system () == l)
111         return s;
112     }
113   while (flip (&d) != LEFT);
114
115   return 0;
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 Direction
128 Item::break_status_dir () const
129 {
130   if (original ())
131     {
132       Item *i = dynamic_cast<Item *> (original ());
133
134       return (i->broken_to_drul_[LEFT] == this) ? LEFT : RIGHT;
135     }
136   else
137     return CENTER;
138 }
139
140 void
141 Item::handle_prebroken_dependencies ()
142 {
143   Grob::handle_prebroken_dependencies ();
144
145   /*
146     Can't do this earlier, because try_visibility_lambda () might set
147     the elt property transparent, which would then be copied.
148   */
149   SCM vis = get_property ("break-visibility");
150   if (scm_is_vector (vis))
151     {
152       bool visible = to_boolean (scm_vector_ref (vis, scm_from_int (break_status_dir () + 1)));
153
154       if (!visible)
155         suicide ();
156     }
157 }
158
159 void
160 Item::derived_mark () const
161 {
162   if (broken_to_drul_[LEFT])
163     scm_gc_mark (broken_to_drul_[LEFT]->self_scm ());
164   if (broken_to_drul_[RIGHT])
165     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
166 }
167
168 Item *
169 unsmob_item (SCM s)
170 {
171   return dynamic_cast<Item *> (unsmob_grob (s));
172 }
173
174 ADD_INTERFACE (Item,
175                "item-interface",
176                "\n"
177                "\n"
178                "Grobs can be distinguished in their role in the horizontal spacing.\n"
179                "Many grobs define constraints on the spacing by their sizes. For\n"
180                "example, note heads, clefs, stems, and all other symbols with a fixed\n"
181                "shape.  These grobs form a subtype called @code{Item}.\n"
182                "\n"
183                "\n"
184                "Some items need special treatment for line breaking. For example, a\n"
185                "clef is normally only printed at the start of a line (i.e. after a\n"
186                "line break).  To model this, `breakable' items (clef, key signature,\n"
187                "bar lines, etc.) are copied twice. Then we have three versions of each\n"
188                "breakable item: one version if there is no line break, one version\n"
189                "that is printed before the line break (at the end of a system), one\n"
190                "version that is printed after the line break.\n"
191                "\n"
192                "Whether these versions are visible and take up space, is determined by\n"
193                "the outcome of the @code{break-visibility}. This grob property is a\n"
194                "function taking a direction (-1, 0 or 1) as argument. It returns a\n"
195                "cons of booleans, signifying whether this grob should be transparent\n"
196                "and have no extent.\n"
197                "\n"
198                "The following variables for break-visibility are predefined:\n"
199                "@example\n"
200                "           grob will show:   before  no     after\n"
201                "                             break   break  break\n"
202                "  all-invisible              no      no     no\n"
203                "  begin-of-line-visible      no      no     yes\n"
204                "  end-of-line-visible        yes     no     no\n"
205                "  all-visible                yes     yes    yes\n"
206                "  begin-of-line-invisible    yes     yes    no\n"
207                "  end-of-line-invisible      no      yes    yes\n"
208                "  center-invisible           yes      no    yes\n"
209                "@end example\n",
210
211                /* properties */
212                "break-visibility "
213                "no-spacing-rods "
214                "non-musical")