]> git.donarmstrong.com Git - lilypond.git/blob - lily/a2-engraver.cc
patch::: 1.3.132.jcn1
[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
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::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::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::add_support (t, i.elem_l_);
101           if (Side_position::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::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   /* Must only set direction for VoiceCombines, not for StaffCombines:
134      we can't detect that here, so, ugh, yet another property */
135   if (!to_boolean (get_property ("noDirection"))
136       && (Stem::has_interface (i.elem_l_)
137           || Slur::has_interface (i.elem_l_)
138           // || Tie::has_interface (i.elem_l_)
139           || i.elem_l_->has_interface (ly_symbol2scm ("tie-interface"))
140           /*
141             Usually, dynamics are removed by *_devnull_engravers for the
142             second voice.  On the one hand, we don't want all dynamics for
143             the first voice to be placed above the staff.  On the other
144             hand, colliding of scripts may be worse */
145 #if 0
146           || i.elem_l_->has_interface (ly_symbol2scm ("dynamic-interface"))
147           || i.elem_l_->has_interface (ly_symbol2scm ("text-interface"))
148 #endif
149           ))
150     {
151       /*
152         Hmm.  We must set dir when solo, in order to get
153         the rests collided to the right position
154       */
155       if ((unirhythm != SCM_BOOL_T) || (solo == SCM_BOOL_T)
156           || ((unisilence == SCM_BOOL_T && previous_state != UNISON))
157           || (unirhythm == SCM_BOOL_T && split_interval == SCM_BOOL_T
158               && (unison != SCM_BOOL_T || solo_adue != SCM_BOOL_T)))
159         {
160           if (daddy_trans_l_->id_str_.left_str (3) == "one")
161             {
162               i.elem_l_->set_grob_property ("direction", gh_int2scm (1));
163             }
164           else if (daddy_trans_l_->id_str_.left_str (3) == "two")
165             {
166               i.elem_l_->set_grob_property ("direction", gh_int2scm (-1));
167             }
168         }
169     }
170 }
171
172 void 
173 A2_engraver::stop_translation_timestep ()
174 {
175   if (text_p_)
176     {
177       Side_position::add_staff_support (text_p_);
178       typeset_grob (text_p_);
179       text_p_ = 0;
180     }
181 }
182