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