]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
release: 1.3.42
[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 #include "staff-symbol-referencer.hh"
13 #include "bar.hh"
14 #include "clef-item.hh"
15 #include "debug.hh"
16 #include "command-request.hh"
17 #include "timing-translator.hh"
18 #include "note-head.hh"
19 #include "key-item.hh"
20 #include "local-key-item.hh"
21 #include "array.hh"
22 #include "engraver.hh"
23 #include "direction.hh"
24
25 /// where is c-0 in the staff?
26 class Clef_engraver : public  Engraver {
27   Clef_item * clef_p_;
28   Clef_change_req * clef_req_l_;
29   void create_clef();
30   bool set_type (String);
31 protected:
32   virtual void do_process_music();
33   virtual void do_pre_move_processing();
34   virtual void do_creation_processing();
35   virtual void do_post_move_processing();
36   virtual bool do_try_music (Music*);
37   virtual void acknowledge_element (Score_element_info);
38 public:
39   VIRTUAL_COPY_CONS(Translator);
40   int c0_position_i_;
41   int clef_position_i_;
42                                 // junkme.
43   Direction octave_dir_;
44   SCM clef_glyph_;              // no need for protection. Always referenced somewhere else.
45    
46   Clef_engraver();
47 };
48
49
50 Clef_engraver::Clef_engraver()
51 {
52   clef_glyph_ = SCM_EOL;
53   clef_p_ = 0;
54   clef_req_l_ = 0;
55   c0_position_i_ = 0;
56   clef_position_i_ = 0;
57   octave_dir_ = CENTER;
58 }
59
60 bool
61 Clef_engraver::set_type (String s)
62 {
63   if (s.right_str(2) == "_8") // Down one octave
64     {
65       octave_dir_ = DOWN;
66       s = s.left_str(s.length_i() - 2);
67     }
68   else if (s.right_str(2) == "^8") // Up one octave
69     {
70       octave_dir_ = UP;
71       s = s.left_str(s.length_i() - 2);
72     }
73   else
74     octave_dir_ = CENTER;
75
76   SCM c = get_property ("supportedClefTypes");
77   SCM p = get_property ("clefPitches");
78   
79   if (gh_list_p (c))
80     {
81       SCM found = scm_assoc (ly_str02scm (s.ch_C()), c);
82       if (found == SCM_BOOL_F)
83         return false;
84       
85       clef_glyph_  = gh_cadr (found);
86       SCM pos  = gh_caddr (found);
87
88       clef_position_i_ = gh_scm2int (pos);
89
90       found = scm_assoc (clef_glyph_, p);
91       if (found == SCM_BOOL_F)
92         return false;
93
94       c0_position_i_ = clef_position_i_ + gh_scm2int (gh_cdr (found));
95     }
96
97   c0_position_i_ -= (int) octave_dir_ * 7;
98   return true;
99 }
100
101
102 /** 
103   Generate a clef at the start of a measure. (when you see a Bar,
104   ie. a breakpoint) 
105   */
106 void
107 Clef_engraver::acknowledge_element (Score_element_info info)
108 {
109   if (dynamic_cast<Bar*>(info.elem_l_)
110       && gh_string_p (clef_glyph_))
111     create_clef();
112
113   /* ugh; should make Clef_referenced baseclass */
114   Item * it_l =dynamic_cast <Item *> (info.elem_l_);
115   if (it_l)
116     {
117       if (dynamic_cast<Note_head*>(it_l)
118           || dynamic_cast<Local_key_item*> (it_l)
119           )
120           
121         {
122           Staff_symbol_referencer_interface si (it_l);
123           si.set_position (int (si.position_f ()) + c0_position_i_);
124         }
125       else if (Key_item *k = dynamic_cast<Key_item*>(it_l))
126         {
127           k->set_elt_property ("c0-position", gh_int2scm (c0_position_i_));
128         }
129     } 
130 }
131
132 void
133 Clef_engraver::do_creation_processing()
134 {
135   SCM def = get_property ("defaultClef");
136   if (gh_string_p (def))
137     {
138       set_type (ly_scm2string (def));
139       create_clef ();
140       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
141     }
142 }
143
144 bool
145 Clef_engraver::do_try_music (Music * r_l)
146 {
147   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
148     {
149       clef_req_l_ = cl;
150       if (!set_type (cl->clef_str_))
151         cl->error (_ ("unknown clef type"));
152
153       return true;
154     }
155   else
156     return false;
157
158 }
159
160 void
161 Clef_engraver::create_clef()
162 {
163   if (!clef_p_)
164     {
165       Clef_item *c= new Clef_item;
166       c->set_elt_property ("breakable", SCM_BOOL_T);
167       c->set_elt_property ("break-align-symbol", ly_symbol2scm ("Clef_item"));
168       announce_element (Score_element_info (c, clef_req_l_));
169
170       Staff_symbol_referencer_interface si(c);
171       si.set_interface ();
172       
173       clef_p_ = c;
174     }
175   Staff_symbol_referencer_interface si(clef_p_);
176   clef_p_->set_elt_property ("glyph", clef_glyph_);
177   si.set_position (clef_position_i_);
178   if (octave_dir_)
179     {
180       clef_p_->set_elt_property ("octave-dir", gh_int2scm (octave_dir_));
181     }
182 }
183
184
185 void
186 Clef_engraver::do_process_music()
187 {
188   if (clef_req_l_)
189     {
190       create_clef();
191       clef_p_->set_elt_property ("non-default", SCM_BOOL_T);
192     }
193 }
194
195 void
196 Clef_engraver::do_pre_move_processing()
197 {
198   if (clef_p_)
199     {
200       if(to_boolean (clef_p_->remove_elt_property("non-default")))
201          clef_p_->set_elt_property("visibility-lambda",
202                                    scm_eval (ly_symbol2scm ("all-visible")));
203       
204       typeset_element (clef_p_);
205       clef_p_ =0;
206     }
207 }
208
209 void
210 Clef_engraver::do_post_move_processing()
211 {
212   clef_req_l_ = 0;
213 }
214
215
216
217
218 ADD_THIS_TRANSLATOR(Clef_engraver);
219