2 a2-engraver.cc -- implement A2_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
11 #include "note-head.hh"
14 #include "translator-group.hh"
15 #include "side-position-interface.hh"
16 #include "directional-element-interface.hh"
17 #include "multi-measure-rest.hh"
19 class A2_engraver : public Engraver
21 TRANSLATOR_DECLARATIONS(A2_engraver);
24 virtual void acknowledge_grob (Grob_info);
25 virtual void create_grobs ();
26 virtual void stop_translation_timestep ();
29 enum State { SOLO, SPLIT_INTERVAL, UNIRHYTHM, UNISILENCE, UNISON } state_;
34 A2_engraver::A2_engraver ()
41 A2_engraver::create_grobs ()
43 if (!to_boolean (get_property ("combineParts")))
47 SCM unison = get_property ("unison");
48 SCM solo = get_property ("solo");
49 SCM solo_adue = get_property ("soloADue");
51 if (solo_adue == SCM_BOOL_T
52 && ((solo == SCM_BOOL_T && state_ != SOLO)
53 || (unison == SCM_BOOL_T && state_ != UNISON
54 && daddy_trans_l_->id_str_.left_str (3) == "one")))
56 text_p_ = new Item (get_property ("TextScript"));
57 Side_position_interface::set_axis (text_p_, Y_AXIS);
58 announce_grob (text_p_, 0);
62 if (solo == SCM_BOOL_T)
65 if (daddy_trans_l_->id_str_.left_str (3) == "one")
67 text = get_property ("soloText");
71 text = get_property ("soloIIText");
75 else if (unison == SCM_BOOL_T)
78 if (daddy_trans_l_->id_str_.left_str (3) == "one")
79 text = get_property ("aDueText");
82 Side_position_interface::set_direction (text_p_, dir);
83 text_p_->set_grob_property ("text", text);
89 A2_engraver::acknowledge_grob (Grob_info i)
91 if (!to_boolean (get_property ("combineParts")))
96 if (Note_head::has_interface (i.grob_l_))
99 Side_position_interface::add_support (t, i.grob_l_);
100 if (Side_position_interface::get_axis (t) == X_AXIS
101 && !t->get_parent (Y_AXIS))
102 t->set_parent (i.grob_l_, Y_AXIS);
104 if (Stem::has_interface (i.grob_l_))
106 Side_position_interface::add_support (text_p_, i.grob_l_);
110 SCM unisilence = get_property ("unisilence");
111 SCM unison = get_property ("unison");
112 SCM unirhythm = get_property ("unirhythm");
113 SCM solo = get_property ("solo");
114 SCM split_interval = get_property ("split-interval");
115 SCM solo_adue = get_property ("soloADue");
117 State previous_state = state_;
118 if (unisilence == SCM_BOOL_T)
123 else if (solo == SCM_BOOL_T)
125 else if (unison == SCM_BOOL_T)
127 else if (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T)
128 state_ = SPLIT_INTERVAL;
132 Direction d = CENTER;
133 if (daddy_trans_l_->id_str_.left_str (3) == "one")
135 else if (daddy_trans_l_->id_str_.left_str (3) == "two")
138 /* Must only set direction for VoiceCombines, not for StaffCombines:
139 we can't detect that here, so, ugh, yet another property */
140 if (!to_boolean (get_property ("noDirection"))
141 && (Stem::has_interface (i.grob_l_)
142 || Slur::has_interface (i.grob_l_)
143 // || Tie::has_interface (i.grob_l_)
144 || i.grob_l_->has_interface (ly_symbol2scm ("tie-interface"))
147 Usually, dynamics are removed by *_devnull_engravers for the
148 second voice. On the one hand, we don't want all dynamics for
149 the first voice to be placed above the staff. On the other
150 hand, colliding of scripts may be worse.
151 So, we don't set directions for these when we're playing solo.
153 || (i.grob_l_->has_interface (ly_symbol2scm ("dynamic-interface"))
155 || (i.grob_l_->has_interface (ly_symbol2scm ("text-interface"))
160 Hmm. We must set dir when solo, in order to get
161 the rests collided to the right position
163 if ((unirhythm != SCM_BOOL_T) || (solo == SCM_BOOL_T)
164 || ((unisilence == SCM_BOOL_T && previous_state != UNISON))
165 || (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T
166 && (unison != SCM_BOOL_T || solo_adue != SCM_BOOL_T)))
170 Blunt axe method: every grob gets a propertysetting.
172 i.grob_l_->set_grob_property ("direction", gh_int2scm (d));
177 todo: should we have separate state variable for being "rest while
179 if ( Multi_measure_rest::has_interface (i.grob_l_) && d )
180 if (state_ == UNIRHYTHM
181 && unisilence != SCM_BOOL_T)
183 i.grob_l_->set_grob_property ("staff-position", gh_int2scm (d * 6));
188 A2_engraver::stop_translation_timestep ()
192 Side_position_interface::add_staff_support (text_p_);
193 typeset_grob (text_p_);
198 ENTER_DESCRIPTION(A2_engraver,
199 /* descr */ "Part combine engraver for orchestral scores.
201 The markings @emph{a2}, @emph{Solo} and @emph{Solo II}, are
202 created by this engraver. It also acts upon instructions of the part
203 combiner. Another thing that the this engraver, is forcing of stem,
204 slur and tie directions, always when both threads are not identical;
205 up for the musicexpr called @code{one}, down for the musicexpr called
209 /* creats*/ "TextScript",
210 /* acks */ "grob-interface tie-interface note-head-interface ",
211 /* reads */ "combineParts noDirection soloADue soloText soloIIText aDueText split-interval unison solo unisilence unirhythm",