]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
lilypond-1.3.102
[lilypond.git] / lily / clef-engraver.cc
1 /*
2   clef-engraver.cc -- implement Clef_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>,
7
8   Mats Bengtsson <matsb@s3.kth.se>
9 */
10
11 #include <ctype.h>
12
13 #include "translator-group.hh"
14 #include "key-item.hh"
15 #include "local-key-item.hh"
16 #include "bar.hh"
17 #include "note-head.hh"
18 #include "staff-symbol-referencer.hh"
19 #include "debug.hh"
20 #include "command-request.hh"
21 #include "engraver.hh"
22 #include "direction.hh"
23 #include "side-position-interface.hh"
24 #include "item.hh"
25 #include "custos.hh"
26
27 /// where is c-0 in the staff?
28 class Clef_engraver : public  Engraver
29 {
30 public:
31   VIRTUAL_COPY_CONS (Translator);
32   Clef_engraver ();
33
34   Direction octave_dir_;
35   bool  first_b_;
36
37 protected:
38   virtual void do_process_music ();
39   virtual void do_pre_move_processing ();
40   virtual void do_creation_processing ();
41   virtual void do_post_move_processing ();
42   virtual bool do_try_music (Music*);
43   virtual void acknowledge_element (Score_element_info);
44
45 private:
46   Item * clef_p_;
47   Item * octavate_p_;
48   Clef_change_req * clef_req_l_;
49   
50   void create_clef ();
51   bool set_type (String);
52 };
53
54 Clef_engraver::Clef_engraver ()
55 {
56   first_b_ = true;
57   clef_p_ = 0;
58   clef_req_l_ = 0;
59   octave_dir_ = CENTER;
60   octavate_p_ = 0;
61 }
62
63 bool
64 Clef_engraver::set_type (String s)
65 {
66   if (s.right_str (2) == "_8") // Down one octave
67     {
68       octave_dir_ = DOWN;
69       s = s.left_str (s.length_i () - 2);
70     }
71   else if (s.right_str (2) == "^8") // Up one octave
72     {
73       octave_dir_ = UP;
74       s = s.left_str (s.length_i () - 2);
75     }
76   else
77     octave_dir_ = CENTER;
78
79   SCM c = get_property ("supportedClefTypes");
80   SCM p = get_property ("clefPitches");
81   
82   if (gh_list_p (c))
83     {
84       SCM found = scm_assoc (ly_str02scm (s.ch_C ()), c);
85       if (found == SCM_BOOL_F)
86         return false;
87       
88       SCM glyph = gh_cadr (found);
89       SCM pos = gh_caddr (found);
90
91       daddy_trans_l_->set_property ("clefGlyph", glyph);
92       daddy_trans_l_->set_property ("clefPosition", pos);
93
94       found = scm_assoc (glyph, p);
95       if (found == SCM_BOOL_F)
96         return false;
97
98       int c0_position = gh_scm2int (pos) + gh_scm2int (gh_cdr (found));
99       daddy_trans_l_->set_property ("centralCPosition", gh_int2scm (c0_position));
100     }
101
102   int c0_position = gh_scm2int (get_property ("centralCPosition"));
103   c0_position -= (int)octave_dir_ * 7;
104   daddy_trans_l_->set_property ("centralCPosition", gh_int2scm (c0_position));
105
106
107   SCM basic = ly_symbol2scm ("Clef");
108   SCM gl = ly_symbol2scm ("glyph");
109
110   daddy_trans_l_->execute_single_pushpop_property (basic, gl, SCM_UNDEFINED);
111   daddy_trans_l_->execute_single_pushpop_property (basic, gl,
112                                                    get_property ("clefGlyph"));
113
114   return true;
115 }
116
117 /** 
118   Generate a clef at the start of a measure. (when you see a Bar,
119   ie. a breakpoint) 
120   */
121 void
122 Clef_engraver::acknowledge_element (Score_element_info info)
123 {
124   Item * item =dynamic_cast <Item *> (info.elem_l_);
125   if (item)
126     {
127       if (Bar::has_interface (info.elem_l_)
128           && gh_string_p (get_property ("clefGlyph")))
129         create_clef ();
130       
131
132       if (Note_head::has_interface (item)
133           || Local_key_item::has_interface (item)
134           || Custos::has_interface (item)
135           )
136         {
137           int p = int (Staff_symbol_referencer::position_f (item))
138             + gh_scm2int (get_property ("centralCPosition"));
139           Staff_symbol_referencer::set_position (item, p);
140         }
141       else if (Key_item::has_interface (item))
142         {
143           /*
144             Key_item adapts its formatting to make sure that the
145             accidentals stay in the upper half of the staff. It needs
146             to know c0-pos for this.  (?)
147           */
148
149           item->set_elt_property ("c0-position", get_property ("centralCPosition"));
150         }
151     } 
152 }
153
154 void
155 Clef_engraver::do_creation_processing ()
156 {
157   daddy_trans_l_->set_property ("clefPosition", gh_int2scm (0));
158   daddy_trans_l_->set_property ("clefGlyph", SCM_EOL);
159   daddy_trans_l_->set_property ("centralCPosition", gh_int2scm (0));
160
161   SCM def = get_property ("defaultClef");
162   if (gh_string_p (def))
163     {
164       set_type (ly_scm2string (def));
165     }
166 }
167
168 bool
169 Clef_engraver::do_try_music (Music * r_l)
170 {
171   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
172     {
173       clef_req_l_ = cl;
174       if (!set_type (cl->clef_str_))
175         cl->origin ()->warning (_ ("unknown clef type"));
176
177       return true;
178     }
179   return false;
180 }
181
182 void
183 Clef_engraver::create_clef ()
184 {
185   if (!clef_p_)
186     {
187       Item *c= new Item (get_property ("Clef"));
188       announce_element (c, clef_req_l_);
189
190       Staff_symbol_referencer::set_interface (c);
191       
192       clef_p_ = c;
193     }
194   Staff_symbol_referencer::set_position (clef_p_,
195                                          gh_scm2int (get_property ("clefPosition")
196                                                      ));
197   if (octave_dir_)
198     {
199       Item * g = new Item (get_property ("OctavateEight"));
200
201       Side_position::add_support (g,clef_p_);      
202
203       g->set_parent (clef_p_, Y_AXIS);
204       g->set_parent (clef_p_, X_AXIS);
205
206       g->set_elt_property ("direction", gh_int2scm (octave_dir_));
207       octavate_p_ = g;
208       announce_element (octavate_p_, clef_req_l_);
209     }
210 }
211
212 void
213 Clef_engraver::do_process_music ()
214 {
215   if (clef_req_l_ || first_b_)
216     {
217       create_clef ();
218       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
219     }
220 }
221
222 void
223 Clef_engraver::do_pre_move_processing ()
224 {
225   if (clef_p_)
226     {
227       SCM vis = 0; 
228       if (to_boolean (clef_p_->get_elt_property ("non-default")))
229         {
230           vis = get_property ("explicitClefVisibility");
231         }
232
233       if (vis)
234         {
235           clef_p_->set_elt_property ("visibility-lambda", vis);
236           if (octavate_p_)
237             octavate_p_->set_elt_property ("visibility-lambda", vis);
238         }
239       
240       typeset_element (clef_p_);
241       clef_p_ =0;
242
243       if (octavate_p_)
244         typeset_element (octavate_p_);
245
246       octavate_p_ = 0;
247     }
248
249   first_b_ = 0;
250 }
251
252 void
253 Clef_engraver::do_post_move_processing ()
254 {
255   clef_req_l_ = 0;
256 }
257
258 ADD_THIS_TRANSLATOR (Clef_engraver);
259