]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
release: 1.1.1
[lilypond.git] / lily / clef-engraver.cc
1 /*
2   clef.cc -- implement Clef_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>,
7   Mats Bengtsson <matsb@s3.kth.se>
8 */
9
10 #include <ctype.h>
11 #include "bar.hh"
12 #include "clef-engraver.hh"
13 #include "clef-item.hh"
14 #include "debug.hh"
15 #include "command-request.hh"
16 #include "time-description.hh"
17 #include "note-head.hh"
18 #include "key-item.hh"
19 #include "local-key-item.hh"
20
21 Clef_engraver::Clef_engraver()
22 {
23   clef_p_ = 0;
24   clef_req_l_ = 0;
25   clef_type_str_ = "";
26   c0_position_i_ = 0;
27   clef_position_i_ = 0;
28   octave_dir_ = CENTER;
29 }
30
31 /*
32   Ugh.  Should have support for Dictionaries in mudela.
33  */
34 bool
35 Clef_engraver::set_type (String s)
36 {
37   if (s.right_str(2) == "_8") // Down one octave
38     {
39       octave_dir_ = DOWN;
40       s = s.left_str(s.length_i() - 2);
41     }
42   else if (s.right_str(2) == "^8") // Up one octave
43     {
44       octave_dir_ = UP;
45       s = s.left_str(s.length_i() - 2);
46     }
47   else
48     octave_dir_ = CENTER;
49   if (s == "treble" ||
50       s == "violin" ||
51       s == "G" || s == "G2")
52     {
53       clef_type_str_ = "violin";
54       clef_position_i_ = -2;
55     }
56   else if (s == "french")
57     {
58       clef_type_str_ = "violin";
59       clef_position_i_ = -4;
60     }
61   else if (s == "soprano")
62     {
63       clef_type_str_ = "alto";
64       clef_position_i_ = -4;
65     }
66   else if (s == "mezzosoprano")
67     {
68       clef_type_str_ = "alto";
69       clef_position_i_ = -2;
70     }
71   else if (s == "alto")
72     {
73       clef_type_str_ = "alto";
74       clef_position_i_ = 0;
75     }
76   else if (s == "tenor")
77     {
78       clef_type_str_ = "alto";
79       clef_position_i_ = 2;
80     }
81   else if (s == "baritone")
82     {
83       clef_type_str_ = "alto";
84       clef_position_i_ = 4;
85     }
86   else if (s == "varbaritone")
87     {
88       clef_type_str_ = "bass";
89       clef_position_i_ = 0;
90     }
91   else if (s == "bass" || s == "F")
92     {
93       clef_type_str_ = "bass";
94       clef_position_i_ = 2;
95     }
96   else if (s == "subbass")
97     {
98       clef_type_str_ = "bass";
99       clef_position_i_ = 4;
100     }
101   else 
102     {
103       switch(toupper (s[0]))
104         {
105         case 'F': 
106           clef_type_str_ = "bass";
107           break;
108         case  'G':
109           clef_type_str_ = "violin";
110           break;
111         case 'C': 
112           clef_type_str_ = "alto";
113           break;
114         default:
115           return false;
116         }
117       clef_position_i_ = 2 * (s[1] - '0') - 6;
118     }
119   if (clef_type_str_ == "violin")
120     c0_position_i_ = clef_position_i_ - 4;
121   else if (clef_type_str_ == "alto")
122     c0_position_i_ = clef_position_i_;
123   else if (clef_type_str_ == "bass")
124     c0_position_i_ = clef_position_i_ + 4;
125   else
126     assert (false);
127
128       
129   c0_position_i_ -= (int) octave_dir_ * 7;
130   
131   return true;
132 }
133
134 void
135 Clef_engraver::read_req (Clef_change_req*c_l)
136 {
137   if (!set_type (c_l->clef_str_))
138     c_l->error (_ ("unknown clef type "));
139 }
140
141
142 /** 
143   Generate a clef at the start of a measure. (when you see a Bar,
144   ie. a breakpoint) 
145   */
146 void
147 Clef_engraver::acknowledge_element (Score_element_info info)
148 {
149   if (dynamic_cast<Bar*>(info.elem_l_)
150       && clef_type_str_.length_i())
151     {
152       create_clef();
153       if (!clef_req_l_)
154         clef_p_->default_b_ = true;
155     }
156
157   /* ugh; should make Clef_referenced baseclass */
158   Item * it_l =dynamic_cast <Item *> (info.elem_l_);
159   if (it_l)
160     {
161       if (Note_head * h = dynamic_cast<Note_head*>(it_l))
162         {
163           h->position_i_ += c0_position_i_;
164         }
165       else if (Local_key_item *i = dynamic_cast<Local_key_item*> (it_l))
166         {
167           i->c0_position_i_ =c0_position_i_;
168         }
169       else if (Key_item *k = dynamic_cast<Key_item*>(it_l))
170         {
171           k-> set_c_position (c0_position_i_);
172         }
173     } 
174 }
175
176 void
177 Clef_engraver::do_creation_processing()
178 {
179   Scalar def = get_property ("defaultClef");
180   if (def.to_bool ()) // egcs: Scalar to bool is ambiguous
181     set_type (def);
182   
183   if (clef_type_str_.length_i ())
184     { 
185       create_clef();
186       clef_p_->default_b_ = false;
187     }
188 }
189
190 bool
191 Clef_engraver::do_try_request (Request * r_l)
192 {
193   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
194     {
195       clef_req_l_ = cl;
196       read_req (clef_req_l_);
197       return true;
198     }
199   else
200     return false;
201
202 }
203
204 void
205 Clef_engraver::create_clef()
206 {
207   if (!clef_p_)
208     {
209       clef_p_ = new Clef_item;
210       clef_p_->break_priority_i_ = -2; // ugh
211       announce_element (Score_element_info (clef_p_,clef_req_l_));
212     }
213   clef_p_->read (*this);
214 }
215
216 void
217 Clef_engraver::do_process_requests()
218 {
219   if (clef_req_l_)
220     {
221       create_clef();
222       clef_p_->default_b_ = false;
223     }
224 }
225
226 void
227 Clef_engraver::do_pre_move_processing()
228 {
229   if (clef_p_)
230     {
231       typeset_element (clef_p_);
232       clef_p_ = 0;
233     }
234 }
235 void
236 Clef_engraver::do_post_move_processing()
237 {
238   clef_req_l_ = 0;
239 }
240
241 void
242 Clef_engraver::do_removal_processing()
243 {
244   if (clef_p_)
245     {
246       clef_p_->unlink ();       
247       delete clef_p_;
248       clef_p_ =0;
249     }
250 }
251
252
253 IMPLEMENT_IS_TYPE_B1(Clef_engraver,Engraver);
254 ADD_THIS_TRANSLATOR(Clef_engraver);