]> git.donarmstrong.com Git - lilypond.git/blob - lily/clef-engraver.cc
patch::: 1.1.22.jcn1: slur fixjes
[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           h->position_i_ = h->steps_i_ + c0_position_i_;
155         }
156       else if (Local_key_item *i = dynamic_cast<Local_key_item*> (it_l))
157         {
158           i->c0_position_i_ =c0_position_i_;
159         }
160       else if (Key_item *k = dynamic_cast<Key_item*>(it_l))
161         {
162           k-> set_c_position (c0_position_i_);
163         }
164     } 
165 }
166
167 void
168 Clef_engraver::do_creation_processing()
169 {
170   Scalar def = get_property ("defaultClef", 0);
171   if (def.to_bool ()) // egcs: Scalar to bool is ambiguous
172     set_type (def);
173   
174   if (clef_type_str_.length_i ())
175     { 
176       create_clef();
177         for (int i=0; i < clef_p_arr_.size (); i++)
178
179             clef_p_arr_[i]->default_b_ = false;
180     }
181 }
182
183 bool
184 Clef_engraver::do_try_music (Music * r_l)
185 {
186   if (Clef_change_req *cl = dynamic_cast <Clef_change_req *> (r_l))
187     {
188       clef_req_l_ = cl;
189       read_req (clef_req_l_);
190       return true;
191     }
192   else
193     return false;
194
195 }
196
197 void
198 Clef_engraver::create_clef()
199 {
200   if (clef_type_str_ == "scarlatti")
201     {
202       while (clef_p_arr_.size () < 2)
203         {
204           Clef_item *ct= new Clef_item;
205           ct->break_priority_i_ =  -2; // UGH
206           announce_element (Score_element_info (ct, clef_req_l_));
207           clef_p_arr_.push (ct);
208         }
209       clef_p_arr_[0]->symbol_ = "treble";
210       clef_p_arr_[0]->y_position_i_ = 4;
211       clef_p_arr_[1]->symbol_ = "bass";
212       clef_p_arr_[1]->y_position_i_ = -4;
213     }
214   else
215     {
216       if (!clef_p_arr_.size ())
217         {
218           Clef_item *c= new Clef_item;
219           c->break_priority_i_ = -2; // ugh
220           announce_element (Score_element_info (c, clef_req_l_));
221           clef_p_arr_.push (c);
222         }
223
224       for (int i=0; i < clef_p_arr_.size (); i++)
225         {
226           clef_p_arr_[i]->symbol_ = clef_type_str_;
227           clef_p_arr_[i]->y_position_i_ = clef_position_i_;
228           clef_p_arr_[i]->octave_dir_ = octave_dir_;
229         }
230     }
231 }
232
233
234 void
235 Clef_engraver::do_process_requests()
236 {
237   if (clef_req_l_)
238     {
239       create_clef();
240       for (int i=0; i < clef_p_arr_.size (); i++)
241         clef_p_arr_[i]->default_b_ = false;
242     }
243 }
244
245 void
246 Clef_engraver::do_pre_move_processing()
247 {
248   for (int i=0; i <clef_p_arr_.size (); i++)
249     {
250       typeset_element (clef_p_arr_[i]);
251     }
252   clef_p_arr_.clear ();
253 }
254
255 void
256 Clef_engraver::do_post_move_processing()
257 {
258   clef_req_l_ = 0;
259 }
260
261 void
262 Clef_engraver::do_removal_processing()
263 {
264   if (clef_p_arr_.size ())
265     {
266       assert (false);
267     }
268 }
269
270
271
272 ADD_THIS_TRANSLATOR(Clef_engraver);