]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
83eb544afe64ebca957910a826afa3d4cdc79ce4
[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       String t = ly_scm2string (cl->get_mus_property ("clef-type"));
175       if (!set_type (t))
176         cl->origin ()->warning (_ ("unknown clef type"));
177
178       return true;
179     }
180   return false;
181 }
182
183 void
184 Clef_engraver::create_clef ()
185 {
186   if (!clef_p_)
187     {
188       Item *c= new Item (get_property ("Clef"));
189       announce_element (c, clef_req_l_);
190
191       Staff_symbol_referencer::set_interface (c);
192       
193       clef_p_ = c;
194     }
195   Staff_symbol_referencer::set_position (clef_p_,
196                                          gh_scm2int (get_property ("clefPosition")
197                                                      ));
198   if (octave_dir_)
199     {
200       Item * g = new Item (get_property ("OctavateEight"));
201
202       Side_position::add_support (g,clef_p_);      
203
204       g->set_parent (clef_p_, Y_AXIS);
205       g->set_parent (clef_p_, X_AXIS);
206
207       g->set_elt_property ("direction", gh_int2scm (octave_dir_));
208       octavate_p_ = g;
209       announce_element (octavate_p_, clef_req_l_);
210     }
211 }
212
213 void
214 Clef_engraver::do_process_music ()
215 {
216   if (clef_req_l_ || first_b_)
217     {
218       create_clef ();
219       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
220     }
221 }
222
223 void
224 Clef_engraver::do_pre_move_processing ()
225 {
226   if (clef_p_)
227     {
228       SCM vis = 0; 
229       if (to_boolean (clef_p_->get_elt_property ("non-default")))
230         {
231           vis = get_property ("explicitClefVisibility");
232         }
233
234       if (vis)
235         {
236           clef_p_->set_elt_property ("visibility-lambda", vis);
237           if (octavate_p_)
238             octavate_p_->set_elt_property ("visibility-lambda", vis);
239         }
240       
241       typeset_element (clef_p_);
242       clef_p_ =0;
243
244       if (octavate_p_)
245         typeset_element (octavate_p_);
246
247       octavate_p_ = 0;
248     }
249
250   first_b_ = 0;
251 }
252
253 void
254 Clef_engraver::do_post_move_processing ()
255 {
256   clef_req_l_ = 0;
257 }
258
259 ADD_THIS_TRANSLATOR (Clef_engraver);
260