]> git.donarmstrong.com Git - lilypond.git/blob - lily/a2-engraver.cc
release: 1.3.148
[lilypond.git] / lily / a2-engraver.cc
1 /*
2   a2-engraver.cc -- implement A2_engraver
3
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "engraver.hh"
10 #include "item.hh"
11 #include "note-head.hh"
12 #include "stem.hh"
13 #include "slur.hh"
14 #include "translator-group.hh"
15 #include "side-position-interface.hh"
16 #include "directional-element-interface.hh"
17 #include "multi-measure-rest.hh"
18
19 class A2_engraver : public Engraver
20 {
21 public:
22   A2_engraver ();
23   VIRTUAL_COPY_CONS (Translator);
24 protected:
25   virtual void acknowledge_grob (Grob_info);
26   virtual void create_grobs ();
27   virtual void stop_translation_timestep ();
28 private:
29   Item* text_p_;
30   enum State { SOLO, SPLIT_INTERVAL, UNIRHYTHM, UNISILENCE, UNISON } state_;
31 };
32
33 ADD_THIS_TRANSLATOR (A2_engraver);
34
35 A2_engraver::A2_engraver ()
36 {
37   text_p_ = 0;
38   state_ = UNISILENCE;
39 }
40
41 void
42 A2_engraver::create_grobs ()
43 {
44   if (!to_boolean (get_property ("combineParts")))
45     return ;
46   if (!text_p_)
47     {
48       SCM unison = get_property ("unison");
49       SCM solo = get_property ("solo");
50       SCM solo_adue = get_property ("soloADue");
51
52       if (solo_adue == SCM_BOOL_T
53           && ((solo == SCM_BOOL_T && state_ != SOLO)
54               || (unison == SCM_BOOL_T && state_ != UNISON
55                   && daddy_trans_l_->id_str_.left_str (3) == "one")))
56         {
57           text_p_ = new Item (get_property ("TextScript"));
58           Side_position_interface::set_axis (text_p_, Y_AXIS);
59           announce_grob (text_p_, 0);
60       
61           Direction dir = UP;
62           SCM text;
63           if (solo == SCM_BOOL_T)
64             {
65               state_ = SOLO;
66               if (daddy_trans_l_->id_str_.left_str (3) == "one")
67                 {
68                   text = get_property ("soloText");
69                 }
70               else
71                 {
72                   text = get_property ("soloIIText");
73                   dir = DOWN;
74                 }
75             }
76           else if (unison == SCM_BOOL_T)
77             {
78               state_ = UNISON;
79               if (daddy_trans_l_->id_str_.left_str (3) == "one")
80                 text = get_property ("aDueText");
81             }
82           
83           Side_position_interface::set_direction (text_p_, dir);
84           text_p_->set_grob_property ("text", text);
85         }
86     }
87 }
88
89 void
90 A2_engraver::acknowledge_grob (Grob_info i)
91 {
92   if (!to_boolean (get_property ("combineParts")))
93     return ;
94   
95   if (text_p_)
96     {
97       if (Note_head::has_interface (i.elem_l_))
98         {
99           Grob*t = text_p_;
100           Side_position_interface::add_support (t, i.elem_l_);
101           if (Side_position_interface::get_axis (t) == X_AXIS
102               && !t->parent_l (Y_AXIS))
103             t->set_parent (i.elem_l_, Y_AXIS);
104         }
105       if (Stem::has_interface (i.elem_l_))
106         {
107           Side_position_interface::add_support (text_p_, i.elem_l_);
108         }
109     }
110           
111   SCM unisilence = get_property ("unisilence");
112   SCM unison = get_property ("unison");
113   SCM unirhythm = get_property ("unirhythm");
114   SCM solo = get_property ("solo");
115   SCM split_interval = get_property ("split-interval");
116   SCM solo_adue = get_property ("soloADue");
117   
118   State previous_state = state_;
119   if (unisilence == SCM_BOOL_T)
120     /*
121       state_ = UNISILENCE;
122     */
123     ;
124   else if (solo == SCM_BOOL_T)
125     state_ = SOLO;
126   else if (unison == SCM_BOOL_T)
127     state_ = UNISON;
128   else if (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T)
129     state_ = SPLIT_INTERVAL;
130   else if (unirhythm)
131     state_ = UNIRHYTHM;
132
133   Direction d = CENTER;
134   if (daddy_trans_l_->id_str_.left_str (3) == "one")
135     d =  UP;
136   else if (daddy_trans_l_->id_str_.left_str (3) == "two")
137     d = DOWN;
138
139   /* Must only set direction for VoiceCombines, not for StaffCombines:
140      we can't detect that here, so, ugh, yet another property */
141   if (!to_boolean (get_property ("noDirection"))
142       && (Stem::has_interface (i.elem_l_)
143           || Slur::has_interface (i.elem_l_)
144           // || Tie::has_interface (i.elem_l_)
145           || i.elem_l_->has_interface (ly_symbol2scm ("tie-interface"))
146           
147           /*
148             Usually, dynamics are removed by *_devnull_engravers for the
149             second voice.  On the one hand, we don't want all dynamics for
150             the first voice to be placed above the staff.  On the other
151             hand, colliding of scripts may be worse.
152             So, we don't set directions for these when we're playing solo.
153           */
154           || (i.elem_l_->has_interface (ly_symbol2scm ("dynamic-interface"))
155               && state_ != SOLO)
156           || (i.elem_l_->has_interface (ly_symbol2scm ("text-interface"))
157               && state_ != SOLO)
158           ))
159     {
160       /*
161         Hmm.  We must set dir when solo, in order to get
162         the rests collided to the right position
163       */
164       if ((unirhythm != SCM_BOOL_T) || (solo == SCM_BOOL_T)
165           || ((unisilence == SCM_BOOL_T && previous_state != UNISON))
166           || (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T
167               && (unison != SCM_BOOL_T || solo_adue != SCM_BOOL_T)))
168         {
169         
170           /*
171             Blunt axe method: every grob gets a propertysetting.
172            */
173           i.elem_l_->set_grob_property ("direction", gh_int2scm (d));
174         }
175     }
176
177   /*
178     todo: should we have separate state variable for being "rest while
179     other has solo?"  */
180   if ( Multi_measure_rest::has_interface (i.elem_l_) && d )
181     if (state_ == UNIRHYTHM
182         && unisilence != SCM_BOOL_T)
183     {
184       i.elem_l_->set_grob_property ("staff-position", gh_int2scm (d * 6));
185     }
186 }
187
188 void 
189 A2_engraver::stop_translation_timestep ()
190 {
191   if (text_p_)
192     {
193       Side_position_interface::add_staff_support (text_p_);
194       typeset_grob (text_p_);
195       text_p_ = 0;
196     }
197 }
198