]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
release: 1.1.6
[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_req_l_ = 0;
24   clef_type_str_ = "";
25   c0_position_i_ = 0;
26   clef_position_i_ = 0;
27   octave_dir_ = CENTER;
28 }
29
30 struct Clef_settings {
31   char const *name;
32   char const *cleftype;
33   int position;
34 } clef_settings[] = {
35   {"treble", "treble", -2},
36   {"violin", "treble", -2},
37   {"G", "treble", -2},
38   {"G2", "treble", -2},  
39   {"scarlatti", "scarlatti", 0 },
40   {"french", "treble",-4 },
41   {"soprano", "alto",-4 },
42   {"mezzosoprano", "alto",-2 },
43   {"alto", "alto",0 },
44   {"tenor", "alto",2 },
45   {"baritone", "alto",4 },
46   {"varbaritone", "bass",0 },
47   {"bass" , "bass",2 },
48   {"F", "bass", 2},
49   {"subbass", "bass",4},
50   {0,0,0}
51 };
52
53
54
55
56 /*
57   Ugh.  Should have support for Dictionaries in mudela.
58  */
59 bool
60 Clef_engraver::set_type (String s)
61 {
62   if (s.right_str(2) == "_8") // Down one octave
63     {
64       octave_dir_ = DOWN;
65       s = s.left_str(s.length_i() - 2);
66     }
67   else if (s.right_str(2) == "^8") // Up one octave
68     {
69       octave_dir_ = UP;
70       s = s.left_str(s.length_i() - 2);
71     }
72   else
73     octave_dir_ = CENTER;
74
75   bool found = 0;
76   for (Clef_settings *c = clef_settings; !found && c->name; c++)
77     {
78       if (c->name == s)
79         {
80           clef_type_str_ = c->cleftype;
81           clef_position_i_ = c->position;
82           found = 1;
83         }
84       }
85   if (!found)
86     {
87       switch(toupper (s[0]))
88         {
89         case 'F': 
90           clef_type_str_ = "bass";
91           break;
92         case  'G':
93           clef_type_str_ = "treble";
94           break;
95         case 'C': 
96           clef_type_str_ = "alto";
97           break;
98         default:
99           return false;
100         }
101       clef_position_i_ = 2 * (s[1] - '0') - 6;
102     }
103
104   if (clef_type_str_ == "treble")
105     c0_position_i_ = clef_position_i_ - 4;
106   else if (clef_type_str_ == "alto")
107     c0_position_i_ = clef_position_i_;
108   else if (clef_type_str_ == "bass")
109     c0_position_i_ = clef_position_i_ + 4;
110   else if (clef_type_str_ == "scarlatti")
111     c0_position_i_ = 0;
112   else
113     assert (false);
114       
115   c0_position_i_ -= (int) octave_dir_ * 7;
116   
117   return true;
118 }
119
120 void
121 Clef_engraver::read_req (Clef_change_req*c_l)
122 {
123   if (!set_type (c_l->clef_str_))
124     c_l->error (_ ("unknown clef type "));
125 }
126
127
128 /** 
129   Generate a clef at the start of a measure. (when you see a Bar,
130   ie. a breakpoint) 
131   */
132 void
133 Clef_engraver::acknowledge_element (Score_element_info info)
134 {
135   if (dynamic_cast<Bar*>(info.elem_l_)
136       && clef_type_str_.length_i())
137     {
138       create_clef();
139       if (!clef_req_l_)
140         for (int i=0; i < clef_p_arr_.size (); i++)
141           {
142             clef_p_arr_[i]->default_b_ = true;
143           }
144
145     }
146
147   /* ugh; should make Clef_referenced baseclass */
148   Item * it_l =dynamic_cast <Item *> (info.elem_l_);
149   if (it_l)
150     {
151       if (Note_head * h = dynamic_cast<Note_head*>(it_l))
152         {
153           h->position_i_ += c0_position_i_;
154         }
155       else if (Local_key_item *i = dynamic_cast<Local_key_item*> (it_l))
156         {
157           i->c0_position_i_ =c0_position_i_;
158         }
159       else if (Key_item *k = dynamic_cast<Key_item*>(it_l))
160         {
161           k-> set_c_position (c0_position_i_);
162         }
163     } 
164 }
165
166 void
167 Clef_engraver::do_creation_processing()
168 {
169   Scalar def = get_property ("defaultClef");
170   if (def.to_bool ()) // egcs: Scalar to bool is ambiguous
171     set_type (def);
172   
173   if (clef_type_str_.length_i ())
174     { 
175       create_clef();
176         for (int i=0; i < clef_p_arr_.size (); i++)
177
178             clef_p_arr_[i]->default_b_ = false;
179     }
180 }
181
182 bool
183 Clef_engraver::do_try_music (Music * r_l)
184 {
185   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
186     {
187       clef_req_l_ = cl;
188       read_req (clef_req_l_);
189       return true;
190     }
191   else
192     return false;
193
194 }
195
196 void
197 Clef_engraver::create_clef()
198 {
199   if (clef_type_str_ == "scarlatti")
200     {
201       while (clef_p_arr_.size () < 2)
202         {
203           Clef_item *ct= new Clef_item;
204           ct->break_priority_i_ =  -2; // UGH
205           announce_element (Score_element_info (ct, clef_req_l_));
206           clef_p_arr_.push (ct);
207         }
208       clef_p_arr_[0]->symbol_ = "treble";
209       clef_p_arr_[0]->y_position_i_ = 4;
210       clef_p_arr_[1]->symbol_ = "bass";
211       clef_p_arr_[1]->y_position_i_ = -4;
212     }
213   else
214     {
215       if (!clef_p_arr_.size ())
216         {
217           Clef_item *c= new Clef_item;
218           c->break_priority_i_ = -2; // ugh
219           announce_element (Score_element_info (c, clef_req_l_));
220           clef_p_arr_.push (c);
221         }
222
223       for (int i=0; i < clef_p_arr_.size (); i++)
224         {
225           clef_p_arr_[i]->symbol_ = clef_type_str_;
226           clef_p_arr_[i]->y_position_i_ = clef_position_i_;
227           clef_p_arr_[i]->octave_dir_ = octave_dir_;
228         }
229     }
230 }
231
232
233 void
234 Clef_engraver::do_process_requests()
235 {
236   if (clef_req_l_)
237     {
238       create_clef();
239       for (int i=0; i < clef_p_arr_.size (); i++)
240         clef_p_arr_[i]->default_b_ = false;
241     }
242 }
243
244 void
245 Clef_engraver::do_pre_move_processing()
246 {
247   for (int i=0; i <clef_p_arr_.size (); i++)
248     {
249       typeset_element (clef_p_arr_[i]);
250     }
251   clef_p_arr_.clear ();
252 }
253
254 void
255 Clef_engraver::do_post_move_processing()
256 {
257   clef_req_l_ = 0;
258 }
259
260 void
261 Clef_engraver::do_removal_processing()
262 {
263   if (clef_p_arr_.size ())
264     {
265       assert (false);
266     }
267 }
268
269
270
271 ADD_THIS_TRANSLATOR(Clef_engraver);